shadermodel
目次
シェーダーの世代ごとの違い
DirectX8
ShaderModel 1
- 補間レジスタ 2 + 4~6。v0/v1 = color diffuse + speculr 用で clamp される 。+ texcoord (汎用でない)
VertexShader 1.0~1.1
- 32bit 浮動少数演算
- 96 constants
- index レジスタあり
- 12 temp registers
- 128命令
PixelShader 1.0~1.3
- 9~12bit程度の固定少数演算。GPU依存
- 演算範囲は -1.0~+1.0 (GPU依存)
- 4 テクスチャ命令
- 8 演算命令
- 8 constants
- 2 temp reigisters
- swizzle (.xyzw .w .z )
PixelShader 1.4
- ATI 拡張
- 6テクスチャ命令
- 6テクスチャ
- pahse 命令
- 6 temp registers
- 192 constants
- swizzle (.xyzw .w .x .y .z )
- 演算範囲は -8~+8
DirectX9
ShaderModel2.0
- 補間レジスタ 8+2= 10個。color v0/v1 = zero clamp される、t0~t7 = 任意
- それ以外に oFog、oPts 等の専用変数あり
VertexShader 2.0
- 32bit 浮動少数演算
- 256 constants
- 12~ temp
- 1024命令実行
VertexShader 2.0a
- nVIDIA 拡張
- 65536命令実行
- temp 16
- Dynamic Flow Control
- ATI 拡張
- Vertex 65280命令実行
PixelShader 2.0
- ATI 24bit 浮動少数演算
- nVIDIA 16 or 32bit 浮動少数演算
- 32 constants
- 12 temp registers
- 32テクスチャ命令 + 64演算命令 = 96命令slot
- 8テクスチャ、サンプリング 16
- MRT x4
- swizzle 制限 (.x .y .z .w .xyzw .yzxw .zxyw .wzyx )
PixelShader 2.0a
- nVIDIA 拡張
- 512命令 slot
- 1024テクスチャ命令実行
- 1024演算命令実行
- temp 64
- 16 texture
- 依存テクスチャ制限なし
- 動的分岐
- 自由な Swizzle (制限なし)
- MRT x1
PixelShader 2.0b
- ATI 拡張
- 3Dc
- 16テクスチャ対応
- 96(32+64)命令slot / 1536命令実行
- 32 temp registers
- 32 constants
- MRT x4
- 512 slot?
ShaderModel3.0
- 補間レジスタ = 任意の 12個 (color,texcoord だけでなく fog, pointsprite 相当も含まれる)
VertexShader 3.0
- 32bit 浮動少数演算
- 256 constants
- 32 temp
- 544命令 slot(NVIDIA)
- 1024命令 slot(ATI)
- 65535命令実行
- 動的分岐
- Texture 対応 (nVIDIAのみ)
- Geometry Instancing
PixelShader 3.0
- 32bit 浮動少数演算
- 224 constants
- 32 temp
- 512 命令 slot / 命令実行 (ATI)
- 4096命令 slot / 65535 実行(NVIDIA)
- 動的分岐
- MRT x4
DirectX10(Direct3D10) / DirectX10.1(Direct3D10.1)
ShaderModel 4
- constant は 1buffer あたり 4096 までだが、texture 等のりソースを buffer として直接アドレッシング読み出しできる。(sampler を通さない)
- constant との違いは、constant = xyzw 個別に読み出せる、buffer = 4ch 単位で load 命令を呼び出す
- プログラムサイズの上限は不明。無い?
- 動的分岐あり。
ShaderModel 4.0 (Vertex/Geometry/Pixel)
- 4096 constants × 16
- 32bit 浮動少数演算 + 32bit 整数演算
- 128 ShaderResources(Texture)
- 16 samplers
- MRT x8
- 補間レジスタ = 任意の 16個。補間手段を指定可能。整数を渡す場合は補間無し限定。
ShaderModel 4.1 (Vertex/Geometry/Pixel)
- 4096 constants × 16
- 32bit 浮動少数演算 + 32bit 整数演算
- 128 ShaderResources(Texture)
- 16 samplers
- MRT x8
- Gather4 sampler, CubeArray sampler 追加
- 補間レジスタ = 任意の 32個。補間手段を指定可能。整数を渡す場合は補間無し限定。
DirectX11 (Direct3D11) / 11.1 / 11.2
ShaderModel 5
- シェーダーステージの増加 (Hull, Domain)
- テセレータの追加 (Hull → Tessellator → Domain)
- シェーダーから任意のデータを書き込み可能になった (Unordered Access)
- シェーダー内のポインタ分岐 (Setup 時に選択) (Dynamic Shader Linkage)
- Vertex Pipe, Rasterizer を通らないシェーダー実行 (Compute Shader)
- 共有メモリへのデータロード
ShaderModel 5.0 (Vertex / Hull / Domain / Geometry / Pixel / Compute )
- 32bit 浮動小数演算
- 64bit 浮動小数演算
- 32bit 整数演算
- 64bit 整数演算 (要確認)
- 書き込み可能テクスチャあり (Pixel / Compute のみ)
- スレッド間の同期命令あり (Compute のみ)
DirectX12 (Direct3D12)
ShaderModel 5.1 (Vertex / Hull / Domain / Geometry / Pixel / Compute )
- ShaderModel 5.0 の拡張で、Windows 10 以降に導入。D3D12 だけでなく D3D11.3/11.4 でも利用可能。
- Rasterizer Order Views (ROV) 対応。同一パスで同じメモリの読み書きが実行順通りになる。
- Steancil Reference Value の出力
- UAV で access 可能な型の拡張
- Conservative rasterization
ShaderModel 6
- Direct3D 12 だけで使える新しい ShaderModel
- ShaderCompiler を LLVM ベースへ変更 (Bytecode も一新)
- Stage の追加は特になし
ShaderModel 6.0 (Vertex / Hull / Domain / Geometry / Pixel / Compute )
- Wave 命令の導入。同じ Wave 内で別スレッドのデータのアクセスが可能。
- 64bit 整数型の追加。
ShaderModel 6.1 (Vertex / Hull / Domain / Geometry / Pixel / Compute )
ShaderModel 6.2 (Vertex / Hull / Domain / Geometry / Pixel / Compute )
- 真の 16bit 型の導入。従来の min~ や half は HW 依存だった。
補足説明
命令slot と実行命令数
- 命令slot数
- プログラムの最大長、何ステップまでのプログラムを格納できるかを表します。
- Loop 命令が追加されるまでは、slot 数 = 最大実行可能な命令数でした。
- ShaderModel 1.0~2.0/2.0b までは Texture 命令とカラー演算命令が分かれていました。テクスチャサンプリングが専用ユニットで実行され、時間がかかる処理だったこと。また ShaderModel1 では Color は 8~9bit 整数演算で済むのに対して、Texcoord は 12bit 程度 (4096×4096 dot) 必要で演算精度が異なっていることが理由として考えられます。
- 実行命令数
- 静的/動的 loop 命令が登場してから、実行可能命令数という概念が登場しました。
- loop命令を使うことで一見無限数の命令実行が可能なように見えますが、実際は上限があるということです。
- 命令 slot 数よりも実行可能命令数の方が通常は大きいので、GPU 性能を発表する場合にメーカーはこちらの数値を大きく取り上げることがあります。
- ところが実際に走らせることが出来る shader のサイズは、slot数によって上限が決まってしまうので、結局宣伝された性能を発揮できることは多くありません。
- 特に 3.0 までの PixelShader は、constant レジスタの参照に loop index を使うことが出来ないため、constant 参照を行う場合は必ずループ展開されます。テクスチャのサンプリングだけなら loop 可能です。
- また loop は実行性能に影響を与えるので、速度を考えると loop 展開した方が有利です。
- ちなみに Windows の driver は、一定期間 GPU から応答がないとハングアップとみなしてデバイスをリセットする機能がついています。
- あまりに長いシェーダーを走らせているとハングアップと勘違いされてしまい、せっかくの実行も途中でとめられてしまうことがあります。
ペアリングと 0slot 命令
- 演算命令が .xyz と .w に分かれている場合、異なる演算命令でもペアリングされて 1 slot に融合できることがあります。
- 当初の Shader Unit が VLIW に近い構造をしており、存在する複数の演算 Unit 分の命令を1命令に格納することが出来たためです。
- この場合融合された命令は 0slot 命令となり、実行サイクルも slot 数も消費しません。
- 通常アセンブラによって自動で最適化されますが、自分で + 記号を使って明示的に融合命令を記述することも出来ました。
- また PixelShader 1.x では、各命令ごとに、またはオペランドごとに clamp や 2倍化、4倍化、符号反転、1から減算、0~1.0 を -1.0~1.0 にマッピング(_bx2)、等の付加機能をノーコストで追加できました。
- PixelShader 1.0~1.3 がわずか 8slot しかないのに複雑な処理が出来たのは、このような slot も cycle も食わない特殊な機能があったからです。
temp レジスタ
- v0/v1, t0~t3 等の入力レジスタも書き換え可能で、実際は temp レジスタ代わりに使えることがあります。そのためspec上の上限よりもプログラミング時の制約は少なくなります。
- ShaderModel 2.0 以降は temp レジスタの数がシェーダーの実行速度に対して多大なインパクトを与えるようになったため、HLSL コンパイラなどは上限までレジスタを使うことがありません。
- ShaderModel 1.x では演算可能な数値範囲とレジスタのサイズが異なっており、temp レジスタに代入するだけで精度が落ちることがありました。
texture 数
- 1つのシェーダーにパラメータとして渡せるテクスチャ数と、1つのシェーダーが一度に読み込めるテクスチャ数は異なっています。
- 例えば PixelShader 2.0 では 8枚のテクスチャを一度に設定できますが、同じテクスチャを uv を変えて何度も読み込めるので最大 16回サンプリングすることが出来ます。
- PixelShader 2.0a 以降は、サンプリング回数に制限がなくなりました。1枚のテクスチャを何回も何回も読み出すことが出来ます。
- つまり、下記3つの「利用可能テクスチャ数」が存在しています。
- 一度にShaderに渡せる Texture 数 (APIで渡せる個数)
- Shader がサンプリングできる回数 (uvを演算で求めれば何回でもいけることが多い)
- Sampler State の数
- ShaderModel 1.x では 1~3 は同値でした。
- ShaderModel 2~3 では 1/3 と 2 が分離されました。
- ShaderModel 4.0 では 1, 2, 3 すべて別の概念として分離されました。
ハードの制約と Direct3D 仕様の制約
- GPU スペック的には事実上上限が無かったとしても、Direct3D の ShaderModel の仕様上制約がついていることがあります。
- 上記比較表を作るための参考資料として、メーカーページの spec や Direct3D マニュアルを利用しています。このどちらを参照したかによって性能が異なっていることがあるので注意してください。
- 例えば GPU spec 上 512 命令が上限としても、API 上 256命令になっていることもあります。
shadermodel.txt · 最終更新: 2018/06/20 23:35 by oga