D3D12でHLSL内にRootSignatureを定義してフェッチしてみる

#概要
HLSL内にルートシグネチャを定義してCpp側からフェッチしてみるだけ。半分備忘録。

#RootSignatureの定義
```shader.hlsl
//RootSignatureの定義
#define RS "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),"\
                          "CBV(b0),"\
                          "SRV(t0),"\
                          "DescriptorTable(CBV(b1,numDescriptors = 1,space = 0),visibility = SHADER_VISIBILITY_ALL),"\
                          "DescriptorTable(SRV(t1,numDescriptors = 1,space = 0),visibility = SHADER_VISIBILITY_PIXEL),"\
                          "StaticSampler(s0 ,"\
                                             "filter = FILTER_MIN_MAG_MIP_LINEAR,"\
                                             "addressU = TEXTURE_ADDRESS_WRAP,"\
                                             "addressV = TEXTURE_ADDRESS_WRAP,"\
                                             "addressW = TEXTURE_ADDRESS_WRAP,"\
                                             "mipLodBias = 0.0f,"\
                                             "maxAnisotropy = 16,"\
                                             "comparisonFunc  = COMPARISON_NEVER,"\
                                             "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,"\
                                             "minLOD = 0.0f,"\
                                             "maxLOD = 3.402823466e+38f,"\
                                             "space  =  0,"\
                                             "visibility = SHADER_VISIBILITY_ALL"\
                                            ")"\
//RootSignatureの定義ここまで

//ConstantBuffer (b0)
cbuffer Color : register(b0)
{
 float4 color
}
//ConstantBuffer (b1)
cbuffer Color : register(b0)
{
 float4 color
}

//Texture(t0)
Texture2D<float4>  : register(t0);

//Texture(t1)
Texture2D<float4> SphereTex : register(t1);

//Static Sampler (s0)
SamplerState Sampler : register(s0);



//VertexShader

//ここでシェーダーに使用するRootSignatureをバインド
[RootSignature(RS)]
float4 VSMain(float3 pos : POSITION) : SV_POSITION
{
 return float4 (pos.xyz ,1.0f); 
}

//PixelShader
float4 PSMain(float4 pos : SV_POSITION) : SV_Target
{
 return pos
}
```

このシェーダで注目してほしいのはHLSL内で一番上にあるRootSignatureの定義部分とVertexShaderの定義の上部にある部分です。

```shader.hlsl
#define RS "RootFlags(ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT),"\
                          "CBV(b0),"\
                          "SRV(t0),"\
                          "DescriptorTable(CBV(b1,numDescriptors = 1,space = 0),visibility = SHADER_VISIBILITY_ALL),"\
                          "DescriptorTable(SRV(t1,numDescriptors = 1,space = 0),visibility = SHADER_VISIBILITY_PIXEL),"\
                          "StaticSampler(s0 ,"\
                                             "filter = FILTER_MIN_MAG_MIP_LINEAR,"\
                                             "addressU = TEXTURE_ADDRESS_WRAP,"\
                                             "addressV = TEXTURE_ADDRESS_WRAP,"\
                                             "addressW = TEXTURE_ADDRESS_WRAP,"\
                                             "mipLodBias = 0.0f,"\
                                             "maxAnisotropy = 16,"\
                                             "comparisonFunc  = COMPARISON_NEVER,"\
                                             "borderColor = STATIC_BORDER_COLOR_TRANSPARENT_BLACK,"\
                                             "minLOD = 0.0f,"\
                                             "maxLOD = 3.402823466e+38f,"\
                                             "space  =  0,"\
                                             "visibility = SHADER_VISIBILITY_ALL"\
                                            ")"\

```
上記のコードの部分と

``` shader.hlsl
[RootSignature(RS)]
```

この部分です。

これは*#define*でルートシグネチャを定義して、[*RootSignature*(RootSignature名)]でシェーダーにバインドしています。こうすることでシェーダーバイナリからRootSignatureがフェッチ可能になります。

CBVやSRV等をシェーダに投げるときのインデックス（RootParamaterIndex）はRootFlagsとStaticSamplerを除いて定義した順番になるので注意が必要です。
例えば上記のRootSignatureだと、CBV(b0)がインデックス0番、SRV(t0)がインデックス1番、といった感じになります。

#CPP側からフェッチ

```fetch.cpp
Microsoft::WRL::ComPtr<ID3DBlob> vertexShader;                 //すでにコンパイル済みの頂点シェーダー
Microsoft::WRL::ComPtr<ID3DBlob> signature;                    //シェーダーバイナリからフェッチしたRootSignatureの情報
Microsoft::WRL::ComPtr<ID3D12RootSignature> rootSignature;     //RootSignature本体
Microsoft::WRL::ComPtr<ID3D12Device> d3d12Device;              //作成済みのデバイス

//シェーダーバイナリからRootSignatureの部分をフェッチ
auto hr = D3DGetBlobPart(vertexShader->GetBufferPointer(), vertexShader->GetBufferSize(), D3D_BLOB_ROOT_SIGNATURE, 0, &signature);
if (FAILED(hr))
{
	return hr;
}
//RootSignatureの作成
hr = d3d12Device->CreateRootSignature(0, signature->GetBufferPointer(), signature->GetBufferSize(), IID_PPV_ARGS(&rootSignature));
if (FAILED(hr)) {
	return hr;
};
```

こんな感じです。

#参考資料

[Specifying Root Signatures in HLSL](https://docs.microsoft.com/ja-jp/windows/desktop/direct3d12/specifying-root-signatures-in-hlsl#root-signature-version-10)
[[DX12] HLSLにRoot Signatureを定義する](https://glhub.blogspot.com/2016/08/dx12-hlslroot-signature.html)

上記の記事はとても参考になりました。