Связь между шейдерами и графическим процессором для DirectX 12 осуществляется через корневые подписи.Для двух текстур у вас есть два варианта, как связать их.
Две текстуры в одной таблице дескрипторов
Первая - это связать их вместе, но это требует, чтобы целевые дескрипторы были непрерывными.Это то, с чего вы начали.
// HLSL syntax
#define DualTextureRS \
"RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
" DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
" DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
" DENY_HULL_SHADER_ROOT_ACCESS )," \
"DescriptorTable ( SRV(t0, numDescriptors = 2), visibility = SHADER_VISIBILITY_PIXEL )," \
"DescriptorTable ( Sampler(s0, numDescriptors = 2), visibility = SHADER_VISIBILITY_PIXEL )," \
"CBV(b0)"
// C++ code built root-signature
enum RootParameterIndex
{
TextureSRVBase,
TextureSamplerBase,
ConstantBuffer,
RootParameterCount
};
{
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS;
CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount] = {};
rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL);
// Textures
CD3DX12_DESCRIPTOR_RANGE textureRange(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0);
CD3DX12_DESCRIPTOR_RANGE textureSamplerRange(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 2, 0);
rootParameters[RootParameterIndex::TextureSRVBase].InitAsDescriptorTable(1, &textureRange, D3D12_SHADER_VISIBILITY_PIXEL);
rootParameters[RootParameterIndex::TextureSamplerBase].InitAsDescriptorTable(1, &textureSamplerRange, D3D12_SHADER_VISIBILITY_PIXEL);
// Create the root signature
CD3DX12_ROOT_SIGNATURE_DESC rsigDesc = {};
rsigDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr, rootSignatureFlags);
ComPtr<ID3D12RootSignature> rootSignature;
ComPtr<ID3DBlob> pSignature;
ComPtr<ID3DBlob> pError;
HRESULT hr = D3D12SerializeRootSignature(&rsigDesc, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf());
if (SUCCEEDED(hr))
{
hr = device->CreateRootSignature(0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(),
IID_PPV_ARGS(&rootSignature)
);
}
}
И затем вы должны связать это:
commandList->SetGraphicsRootSignature(rootSignature.Get());
commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSRVBase, texture1); // Second texture will be (texture1+1)
commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::TextureSamplerBase, texture1Sampler); // Second sampler will be (texture1Sampler+1)
Две таблицы дескрипторов
Второе - этосвяжите их как два разных диапазона дескрипторов, чтобы вы могли связать две произвольные текстуры:
// HLSL syntax
#define DualTextureRS \
"RootFlags ( ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |" \
" DENY_DOMAIN_SHADER_ROOT_ACCESS |" \
" DENY_GEOMETRY_SHADER_ROOT_ACCESS |" \
" DENY_HULL_SHADER_ROOT_ACCESS )," \
"DescriptorTable ( SRV(t0), visibility = SHADER_VISIBILITY_PIXEL )," \
"DescriptorTable ( Sampler(s0), visibility = SHADER_VISIBILITY_PIXEL )," \
"DescriptorTable ( SRV(t1), visibility = SHADER_VISIBILITY_PIXEL )," \
"DescriptorTable ( Sampler(s1), visibility = SHADER_VISIBILITY_PIXEL )," \
"CBV(b0)"
// C++ code built root-signature
enum RootParameterIndex
{
Texture1SRV,
Texture1Sampler,
Texture2SRV,
Texture2Sampler,
ConstantBuffer,
RootParameterCount
};
{
D3D12_ROOT_SIGNATURE_FLAGS rootSignatureFlags =
D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT |
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS;
CD3DX12_ROOT_PARAMETER rootParameters[RootParameterIndex::RootParameterCount] = {};
rootParameters[RootParameterIndex::ConstantBuffer].InitAsConstantBufferView(0, 0, D3D12_SHADER_VISIBILITY_ALL);
// Texture 1
CD3DX12_DESCRIPTOR_RANGE texture1Range(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
CD3DX12_DESCRIPTOR_RANGE texture1SamplerRange(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 0);
rootParameters[RootParameterIndex::Texture1SRV].InitAsDescriptorTable(1, &texture1Range, D3D12_SHADER_VISIBILITY_PIXEL);
rootParameters[RootParameterIndex::Texture1Sampler].InitAsDescriptorTable(1, &texture1SamplerRange, D3D12_SHADER_VISIBILITY_PIXEL);
// Texture 2
CD3DX12_DESCRIPTOR_RANGE texture2Range(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 1);
CD3DX12_DESCRIPTOR_RANGE texture2SamplerRange(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, 1, 1);
rootParameters[RootParameterIndex::Texture2SRV].InitAsDescriptorTable(1, &texture2Range, D3D12_SHADER_VISIBILITY_PIXEL);
rootParameters[RootParameterIndex::Texture2Sampler].InitAsDescriptorTable(1, &texture2SamplerRange, D3D12_SHADER_VISIBILITY_PIXEL);
// Create the root signature
CD3DX12_ROOT_SIGNATURE_DESC rsigDesc = {};
rsigDesc.Init(_countof(rootParameters), rootParameters, 0, nullptr, rootSignatureFlags);
ComPtr<ID3D12RootSignature> rootSignature;
ComPtr<ID3DBlob> pSignature;
ComPtr<ID3DBlob> pError;
HRESULT hr = D3D12SerializeRootSignature(&rsigDesc, D3D_ROOT_SIGNATURE_VERSION_1, pSignature.GetAddressOf(), pError.GetAddressOf());
if (SUCCEEDED(hr))
{
hr = device->CreateRootSignature(0, pSignature->GetBufferPointer(), pSignature->GetBufferSize(),
IID_PPV_ARGS(&rootSignature)
);
}
}
И затем вы бы связали это:
commandList->SetGraphicsRootSignature(rootSignature.Get());
commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::Texture1SRV, texture1);
commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::Texture1Sampler, texture1Sampler);
commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::Texture2SRV, texture2);
commandList->SetGraphicsRootDescriptorTable(RootParameterIndex::Texture2Sampler, texture2Sampler);
Вторая форма - та, которую я использую в Набор инструментов DirectX , потому что он более гибкий.