引き続き DirectX SDK Novemver 2008 より、Direct3D 11 の Technical Preview です。
今まで取り上げたことがないもの中心。
●リソースサイズ
仕様として扱えるリソースの上限が拡張されています。
4GByte (32bit) を超えるリソースも扱えるらしく、内部的には 64bit で管理されて
いるようです。すでに VRAM 2GB の製品は存在しているので、4GB を超えるのも
時間の問題と思われます。
リソースサイズが 32bit を超えていても、データアクセス時の index は 32bit までに
制限されます。shader に double は追加されたものの 64bit int 型はまだ無いので
当然かもしれません。
●64bit 整数
HLSL では long/ulong 型が 64bit 整数となるようです。
double 対応前の HLSL コンパイラでは double 型を使うと float 相当の扱いでした。
(D3D10/DX10 シェーダーと64bit浮動少数)
新しい fxc で long/ulong を使うと未サポートエラーになります。
: error X3653: ‘v’: ps_5_0 does not support 64-bit integers
: error X3653: ‘v’: cs_5_0 does not support 64-bit integers
●fxc プロファイル
付属の fxc.exe は単一で、d3d9/d3d10/d3d11 共通になっています。
fxc の対応プロファイルを見ると、ComputeShader は ShaderModel 4.0/4.1 でも
使えそうです。
fx_2_0 fx_4_0 fx_4_1 cs_4_0 // ← ComputeShader 4.0? cs_4_1 // ← ComputeShader 4.1? cs_5_0 gs_4_0 gs_4_1 gs_5_0 ds_5_0 // DomainShader hs_5_0 // HullShader ps_2_0 ps_2_a // NVIDIA拡張 ps_2_b // ATI拡張 ps_2_sw ps_3_0 ps_3_sw ps_4_0 ps_4_0_level_9_1 // D3D11 の ShaderModel2.0 ps_4_0_level_9_3 // D3D11 の ShaderModel3.0 ps_4_1 ps_5_0 vs_1_1 vs_2_0 vs_2_a // NVIDIA拡張 vs_2_sw vs_3_0 vs_3_sw vs_4_0 vs_4_0_level_9_1 // D3D11 の ShaderModel2.0 vs_4_0_level_9_3 // D3D11 の ShaderModel3.0 vs_4_1 vs_5_0 tx_1_0
前前回 FeatureLevel 9.1 と 9.2 の違いがわからないと書いたけど、これを見ると
本当にわかりません。
● RW Buffer
読み書き可能リソースが追加されています。
ついに、シェーダーが直接リソースに書き込みできるようになりました。
ストリーム以外の出力ができます。
RWBuffer
RWByteAddressBuffer
RWStructuredBuffer
RWTexture1D
RWTexture1DArray
RWTexture2D
RWTexture2DArray
RWTexture3D
書き込みできるのは PixelShader と ComputeShader のみ。
Load() メソッドではなく基本的に operator[] を使用します。
例えば Buffer では Load() と両方使えるものの RWBuffer は必ず operator[] を
使う必要があります。
Atomic 命令が使えるのは RWByteAddressBuffer だけで、こちらは逆に operator[] が
使えません。Load()/Store() や Interlocked 命令を使用します。
RWBuffera; RWByteAddressBuffer b; Buffer c; float4 main() : SV_Target { a[1]= 3; b.Store( 0, 4 ); b.InterlockedAdd( 0, 1 ); return a[0]+ c.Load( 0 ); }
下記のようにコンパイルされました。(fxc /Tps_5_0)
ps_5_0 dcl_globalFlags refactoringAllowed dcl_resource_buffer (float,float,float,float) t0 dcl_uav_typed_buffer (float,float,float,float) u1 dcl_uav_raw u2 dcl_output o0.xyzw dcl_temps 2 store_uav_typed u1.xyzw, l(1, 1, 1, 1), l(0x40400000, 0x40400000, 0x40400000, 0x40400000) store_raw u2.x, l(0), l(4) atomic_iadd u2, l(0), l(1) ld_uav_typed r0.xyzw, l(0, 0, 0, 0), u1.xyzw ld_indexable(buffer)(float,float,float,float) r1.xyzw, l(0, 0, 0, 0), t0.xyzw add o0.xyzw, r0.xyzw, r1.xyzw ret
store_ 、atomic_ 命令が存在しておりやっと実感がわきます。
シェーダーが本当に書き込んでいます。
dcl_uav や ld_uav など、uav と付くのが読み書き可能な RW リソースを指している
ようです。t レジスタではなく u レジスタが使われています。
ちなみに 4.0 をターゲットにすると UAV をサポートしていないとのエラーが出ます。
// Resource Bindings: // // Name Type Format Dim Slot Elements // ---------------- ---------- ------- ----------- ---- -------- // c texture float4 buf 0 1 // a UAV float4 buf 1 1 // b UAV byte rw 2 1
UAV は Unordered Access View (ID3D11UnorderedAccessView) の略だそうです。
● Append/Consume Buffer
RW Buffer や Atomic 命令だけでなく、もう少し便利な同期機能も追加されています。
AppendStructuredBuffer
AppendByteAddressBuffer
ConsumeStructuredBuffer
ConsumeByteAddressBuffer
Append がバッファの最後に追加、Consume がバッファの最後から取り出します。
LIFO として機能するようです。
RW Buffer と違い、読み込み専用、書き込み専用とそれぞれ個別に定義します。
送信側と受け側を明確にし、同期を単純化しているものと思われます。
使用可能なのはやはり PixelShader と ComputeShader のみ。
マニュアルでは一部全シェーダーで使えるかのような表記もありますがおそらく間違いでしょう。
使い方がよくわからなかったのでコンパイルのみ試したところ、PixelShader だとたまに
Internal Compiler Error が出るようです。
やはり主な用途は ComputeShader だと思われます。
ConsumeStructuredBufferc; AppendStructuredBuffer a; [numthreads(1,1,1)] void main() { uint t= c.Consume(); a.Append( t ); }
コンパイルした結果は下記の通りです。(fxc /Tcs_5_0)
cs_5_0 dcl_globalFlags refactoringAllowed dcl_uav_structured u0, 4 dcl_uav_structured u1, 4 dcl_temps 1 dcl_thread_group 1, 1, 1 imm_atomic_consume r0.x, u0 imm_atomic_alloc r0.y, u1 ld_structured r0.x, r0.x, l(0), u0.x store_structured u1.x, r0.y, l(0), r0.x ret
imm_atomic_consume / imm_atomic_alloc は、このペアを使って load や store を
行うと、atomic な操作でかつバッファサイズも増減することを意味しているようです。
例えば uint を float4 に変更すると次の通り。
ConsumeStructuredBufferc; AppendStructuredBuffer a; [numthreads(1,1,1)] void main() { float4 t= c.Consume(); a.Append( t ); } cs_5_0 dcl_globalFlags refactoringAllowed dcl_uav_structured u0, 16 dcl_uav_structured u1, 16 dcl_temps 2 dcl_thread_group 1, 1, 1 imm_atomic_consume r0.x, u0 ld_structured r0.y, r0.x, l(0), u0.x ld_structured r0.z, r0.x, l(4), u0.x ld_structured r0.w, r0.x, l(8), u0.x ld_structured r0.x, r0.x, l(12), u0.x imm_atomic_alloc r1.x, u1 store_structured u1.x, r1.x, l(0), r0.y store_structured u1.x, r1.x, l(4), r0.z store_structured u1.x, r1.x, l(8), r0.w store_structured u1.x, r1.x, l(12), r0.x ret
Append / Consume 操作は必ずスカラー単位で行われているようです。
これだけだと、float4 の間に他の Append/Consume が割り込んでしまいそうな
気がしますが、offset も同時に指定しているし、まだよくわかりません。
// Name Type Format Dim Slot Elements // ---------------- ---------- ------- ----------- ---- -------- // c UAV struct consume 0 1 // a UAV struct append 1 1
バッファとしては UAV の一種で、Dim が consume 及び append となっています。
関連エントリ
・Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
・Direct3D11 Technical Preview D3D11の互換性、WARP Driver
・Direct3D11 シェーダーの動的リンクやテクスチャ
・Direct3D11 マルチスレッドのための機能
・Direct3D11 テセレータとシェーダー
・Direct3D11 のパイプライン
・Direct3D11 Compute Shader など
・Gamefest2008 と Direct3D 11