Skip to content
Go back

HLSLメモ

· Updated:

DXCで使えるHLSLの文法について個人的にまとめたものです。内容には間違いが含まれている場合があります。

変数

[Storage_Class] [Type_Modifier] Type Name[Index] [: Semantic] [: Packoffset [: Register]; [Annotations] [= Initial_Value]

Storage_Class(記憶域クラス指定子)

  • extern:グローバル変数がアプリケーション側から入力を受け入れる
    • 通常のグローバル変数では既定で有効
  • precise:近似による算術命令の最適化を禁止する
    • addとmulをmadにまとめる、など
  • shared:エフェクト間で変数を共有していることを示すヒント
    • techniqueやpassがあったころの名残?
  • static:変数が永続化する
    • グローバル変数ではアプリケーション側から見えなくなる
  • uniform:変数の値が実行中に一意に定まる
    • グローバル変数では既定で有効
  • volatile:(予約済み)

頂点シェーダ出力およびピクセルシェーダ入力に指定できるもの

  • linear:線形補間
    • 指定なしの場合に既定で有効
  • centroid:ピクセル位置がプリミティブ範囲内に納まるようにする
  • nointerpolation:補間しない
  • noperspective:perspective-correctionを行わない
  • sample:サンプリング位置を使う
    • シェーダーモデル4.1から利用できる
    • ピクセルシェーダがサンプルごとに走るようになる

コンピュートシェーダで指定できるもの

  • groupshared:変数がスレッドグループで共有されるメモリに置かれる

Type_Modifier(型修飾子)

  • const:値を変更できない
    • グローバル変数では既定で有効
  • row_major/column_major:変数が行優先/列優先で格納される
    • 既定ではcolumn_majorが有効

Type(型)

参考:https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-data-types

  • スカラ
    • bool:true or false
    • int:32ビット符号あり整数
    • uint:32ビット符号なし整数
    • dword:32ビット符号なし整数
    • half:16ビット浮動小数点数(相当)
      • 互換性のために通常はfloatにマップされる
      • -enable-16bit-typesオプションを有効にすると、実際に16ビットになる
    • float:32ビット浮動小数点数
    • double:64ビット浮動小数点数
    • min16float:最低限16ビットの浮動小数点数
    • min10float:最低限10ビットの浮動小数点数
    • min16int:最低限16ビットの符号あり整数
    • min12int:最低限12ビットの符号あり整数
    • min16uint:最低限16ビットの符号なし整数
    • snorm float:[1,1][-1, 1]の範囲に正規化されるfloat
    • unorm float:[0,1][0, 1]の範囲に正規化されるfloat
    • string:文字列
    • HLSL 2018以降では、int16_t、uint32_t、float64_tなどのビット数指定型も利用できる
  • ベクトル
    • スカラ型の後ろに要素数をつける:int1、float3、など
    • vector<Type, NumComponents>でも可
  • 行列
    • スカラ型の後ろに”行数x列数”をつける:int1x1、float4x3、など
    • matrix<Type, NumRows, NumColumns>でも可
  • サンプラ
    • SamplerStateやSamplerComparisonStateを使う
      • sampler、sampler1D、sampler2D、sampler3D、samplerCUBEはテクスチャと紐づいていたDirectX9時代の名残なので、現在は不要
    • Static samplerはRoot signatureで定義する
      • 初期化構文も古い時代の名残なので、現在は不要
  • テクスチャ
    • Texture1D、Texture1DArray、Texture2D、Texture2DArray、Texture3D、TextureCubeを使う
      • textureは古い時代の名残なので、現在は不要
      • 取得する値の型はTexture2D<T>の形で指定する
    • RWTexture系は書き込みができる
  • バッファ
    • ConstantBuffer<T>:定数バッファ
    • Buffer<T>:いわゆる配列だが、古いやつ
    • StructuredBuffer<T>:いわゆる配列で、新しいやつ
      • T型の値を読み出す
      • AppendStructuredBufferはpush_backができる
      • ConsumeStructuredBufferはpop_backができる
    • ByteAddressBuffer:いわゆるバイト列
      • StructuredBufferのような型指定はできないが、DXCならLoadメソッドに出力の型を指定できる

Name[Index]

変数名および配列要素数

  • 通常、配列のインデックスは定数である(ドローコール内で変化しない)必要がある
    • 定数でないことをコンパイラに伝えるためにはNonUniformResourceIndex(index)を使う

Semantic

Packoffset

Register

  • register(t0, space0)の形
    • 第一引数は対応するデスクリプタを指定する
      • tはSRV、bはCBV、uはUAV、sはサンプラを示す
      • 後ろには0以上の番号をつける
    • 第二引数は識別用番号を示す
      • spaceが異なれば第一引数は重複しても良い
      • 省略すればspace0とみなす

Annotations

フロー制御

  • C言語のものをそのままの形で利用できる
  • discard文:出力を行わない。ピクセルシェーダで利用できる。
  • forやwhileで使える属性:
    • [unroll(X)]:ループを展開する。Xは打ち切る回数、省略可。
    • [loop]:ループを展開しない。
    • [fastopt]:コンパイル時間を減らすように最適化を抑制する。
    • [allow_uav_condition]:UAVから読み出した値を条件式に使えるようにする。

ifやswitchで使える属性

  • [branch]:CPUと同等の分岐処理。条件式によっていずれかのブロックのみを実行する。
  • [flatten]:両方のブロックを実行して、計算結果を条件式によって選択する。

switchで使える属性

  • [forcecase]:Force a switch statement in the hardware.
    • 意味がわからん
  • [call]:各caseをサブルーチンにする

関数

参考:https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/d3d11-graphics-reference-sm5-attributes

属性

  • earlydepthstencil:シェーダ実行前にデプスステンシルテストを行う
    • ピクセルシェーダ。SM5.0から
  • RootSignature(string):stringで定義されるRoot Signatureを組み込む

クラス

  • クラスというより集成体とった趣のもの
    • T v = {...}で宣言時に中身を初期化する
    • メンバー関数は問題なく定義できる
    • 2022/05/11時点のコンパイラでは以下は使用できなかった
      • コンストラクタやデストラクタ
      • publicやprivate

DXCで使える機能

  • HLSL 2017から
    • enumおよびenum class
  • HLSL 2018から
    • ビット数指定型
  • HLSL 2021から
    • template関数
    • templateクラス
    • ビットフィールド
    • 演算子オーバーロード
    • C++相当の関数オーバーロード

Root Signatureの記法

  • [RootSignature(”string”)]属性を関数にアタッチする
    • コンパイラオプションによって、シェーダバイナリに含めたり、単体のバイナリにしたりできる
    • シェーダバイナリに含まれる場合、そのBlobはシェーダとしてもRootSigとしても渡すことができる
  • Root Signatureの構成はコンマ区切りの文字列として定義される
    • RootFlags(flags)
      • フラグを指定する。省略可
      • flagsには0またはD3D12_ROOT_SIGNATURE_FLAGSの値をOR演算子で連結して指定する
        • D3D12_ROOT_SIGNATURE_FLAG_以降を使う
    • RootConstants(num32BitConstants=#, b# [, space=0, visibility=SHADER_VISIBILITY_ALL])
      • ルート定数
      • visibilityD3D12_SHADER_VISIBILITYの値を指定する
        • D3D12_以降を使う
    • CBV(b# [, space=0, visibility=SHADER_VISIBILITY_ALL, flags=DATA_VOLATILE])
      • ルートレベルCBV
    • SRV(t# [, space=0, visibility=SHADER_VISIBILITY_ALL, flags=DATA_STATIC_WHILE_SET_AT_EXECUTE])
      • ルートレベルSRV
    • UAV(u# [, space=0, visibility=SHADER_VISIBILITY_ALL, flags=DATA_VOLATILE])
      • ルートレベルUAV
    • DescriptorTable(... [, visibility=SHADER_VISIBILITY_ALL])
      • ...には以下が記述できる
        • CBV(b# [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, flags=DATA_STATIC_WHILE_SET_AT_EXECUTE])
        • SRV(t# [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, flags=DATA_STATIC_WHILE_SET_AT_EXECUTE])
        • UAV(u# [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, flags=DATA_VOLATILE])
        • Sampler(s# [, numDescriptors=1, space=0, offset=DESCRIPTOR_RANGE_OFFSET_APPEND, flags=0])
      • numDescriptors=unboundedで要素数を不問にできるが、範囲外チェックが省略される
    • StaticSampler(s# [, filter=, addressU=, addressV=, addressW=, mipLODBias=0.f, maxAnisotropy=16, comparisonFunc=, borderColor=, minLOD=0.f, maxLOD=, space=0, visibility=SHADER_VISIBILITY_ALL])
      • 静的サンプラ