You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
628 lines
26 KiB
C++
628 lines
26 KiB
C++
/*
|
|
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
|
* its licensors.
|
|
*
|
|
* For complete copyright and license terms please see the LICENSE at the root of this
|
|
* distribution (the "License"). All use of this software is governed by the License,
|
|
* or, if provided, by the license below or the license accompanying this file. Do not
|
|
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
*
|
|
*/
|
|
// Original file Copyright Crytek GMBH or its affiliates, used under license.
|
|
#include "RenderDll_precompiled.h"
|
|
#include "DX12RootSignature.hpp"
|
|
|
|
#define DX12_DESCRIPTORTABLE_MERGERANGES_CBV 1
|
|
#define DX12_DESCRIPTORTABLE_MERGERANGES_SRV 2
|
|
#define DX12_DESCRIPTORTABLE_MERGERANGES_UAV 4
|
|
#define DX12_DESCRIPTORTABLE_MERGERANGES_SMP 8
|
|
#define DX12_DESCRIPTORTABLE_MERGERANGES_ALL (DX12_DESCRIPTORTABLE_MERGERANGES_SRV | DX12_DESCRIPTORTABLE_MERGERANGES_UAV | DX12_DESCRIPTORTABLE_MERGERANGES_SMP)
|
|
#define DX12_DESCRIPTORTABLE_MERGERANGES_MODE DX12_DESCRIPTORTABLE_MERGERANGES_ALL
|
|
|
|
namespace DX12
|
|
{
|
|
PipelineLayout::PipelineLayout()
|
|
{
|
|
Clear();
|
|
}
|
|
|
|
void PipelineLayout::Build(Shader* vs, Shader* hs, Shader* ds, Shader* gs, Shader* ps)
|
|
{
|
|
Clear();
|
|
|
|
Shader* shaders[] = { ps, vs, hs, ds, gs };
|
|
EShaderStage shaderStages[] = { ESS_Pixel, ESS_Vertex, ESS_Hull, ESS_Domain, ESS_Geometry };
|
|
|
|
for (size_t stageIdx = 0; stageIdx < AZ_ARRAY_SIZE(shaders); ++stageIdx)
|
|
{
|
|
if (shaders[stageIdx])
|
|
{
|
|
AZ::u32 parameterCount = m_NumRootParameters;
|
|
AppendRootConstantBuffers(shaders[stageIdx], shaderStages[stageIdx]);
|
|
if (parameterCount != m_NumRootParameters)
|
|
{
|
|
m_ShaderStageAccess |= BIT(shaderStages[stageIdx]);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (size_t stageIdx = 0; stageIdx < AZ_ARRAY_SIZE(shaders); ++stageIdx)
|
|
{
|
|
if (shaders[stageIdx])
|
|
{
|
|
AZ::u32 parameterCount = m_NumRootParameters;
|
|
AppendDescriptorTables(shaders[stageIdx], shaderStages[stageIdx]);
|
|
if (parameterCount != m_NumRootParameters)
|
|
{
|
|
m_ShaderStageAccess |= BIT(shaderStages[stageIdx]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PipelineLayout::Build(Shader* cs)
|
|
{
|
|
Clear();
|
|
|
|
if (cs)
|
|
{
|
|
AppendRootConstantBuffers(cs, ESS_Compute);
|
|
AppendDescriptorTables(cs, ESS_Compute);
|
|
m_ShaderStageAccess |= ESS_Compute;
|
|
}
|
|
}
|
|
|
|
void PipelineLayout::Clear()
|
|
{
|
|
m_ConstantViews.clear();
|
|
m_TableResources.clear();
|
|
m_Samplers.clear();
|
|
|
|
m_DescRangeCursor = 0;
|
|
m_NumDescriptors = 0;
|
|
m_NumDynamicSamplers = 0;
|
|
m_NumDescriptorTables = 0;
|
|
m_NumRootParameters = 0;
|
|
m_NumStaticSamplers = 0;
|
|
|
|
m_ShaderStageAccess = ESS_None;
|
|
}
|
|
|
|
void PipelineLayout::MakeDescriptorTable(
|
|
AZ::u32 rangeCursorEnd,
|
|
AZ::u32& rangeCursorBegin,
|
|
AZ::u32 offsetEnd,
|
|
AZ::u32& offsetBegin,
|
|
D3D12_DESCRIPTOR_HEAP_TYPE eHeap,
|
|
D3D12_SHADER_VISIBILITY visibility)
|
|
{
|
|
const AZ::u32 numRanges = rangeCursorEnd - rangeCursorBegin;
|
|
if (numRanges > 0)
|
|
{
|
|
PipelineLayout::DescriptorTableInfo tableInfo;
|
|
tableInfo.m_Type = eHeap;
|
|
tableInfo.m_Offset = offsetBegin;
|
|
m_DescriptorTables[m_NumDescriptorTables++] = tableInfo;
|
|
|
|
// Setup the configuration of the root signature entry (a descriptor table range in this case)
|
|
m_RootParameters[m_NumRootParameters++].InitAsDescriptorTable(numRanges, m_DescRanges + rangeCursorBegin, visibility);
|
|
|
|
rangeCursorBegin = rangeCursorEnd;
|
|
offsetBegin = offsetEnd;
|
|
}
|
|
}
|
|
|
|
static D3D12_SHADER_VISIBILITY ToShaderVisibility(EShaderStage stage)
|
|
{
|
|
static const D3D12_SHADER_VISIBILITY visibility[] =
|
|
{
|
|
D3D12_SHADER_VISIBILITY_VERTEX,
|
|
D3D12_SHADER_VISIBILITY_HULL,
|
|
D3D12_SHADER_VISIBILITY_DOMAIN,
|
|
D3D12_SHADER_VISIBILITY_GEOMETRY,
|
|
D3D12_SHADER_VISIBILITY_PIXEL,
|
|
D3D12_SHADER_VISIBILITY_ALL
|
|
};
|
|
|
|
return visibility[stage];
|
|
}
|
|
|
|
static bool IsRootConstantBuffer(const ReflectedBindingRange& range)
|
|
{
|
|
return !range.m_bUsed || range.m_Count == 1;
|
|
}
|
|
|
|
void PipelineLayout::AppendRootConstantBuffers(Shader* shader, EShaderStage shaderStage)
|
|
{
|
|
const D3D12_SHADER_VISIBILITY visibility = ToShaderVisibility(shaderStage);
|
|
|
|
const ReflectedBindings& bindings = shader->GetReflectedBindings();
|
|
|
|
if (bindings.m_ConstantBuffers.m_DescriptorCount)
|
|
{
|
|
auto& ranges = bindings.m_ConstantBuffers.m_Ranges;
|
|
for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx)
|
|
{
|
|
const ReflectedBindingRange range = ranges[rangeIdx];
|
|
|
|
AZ::u32 rangeBegin = range.m_ShaderRegister;
|
|
AZ::u32 rangeEnd = range.m_ShaderRegister + range.m_Count;
|
|
|
|
if (!IsRootConstantBuffer(range))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (range.m_bShared)
|
|
{
|
|
bool bFound = false;
|
|
|
|
// only pick up the first occurrence
|
|
for (const ConstantBufferLayoutBinding& binding : m_ConstantViews)
|
|
{
|
|
if (binding.ShaderSlot == rangeBegin)
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!bFound)
|
|
{
|
|
ConstantBufferLayoutBinding constant;
|
|
constant.ShaderStage = shaderStage;
|
|
constant.ShaderSlot = rangeBegin;
|
|
constant.RootParameterIndex = m_NumRootParameters;
|
|
m_ConstantViews.push_back(constant);
|
|
|
|
m_RootParameters[m_NumRootParameters++].InitAsConstantBufferView(rangeBegin, 0, D3D12_SHADER_VISIBILITY_ALL);
|
|
}
|
|
}
|
|
else if (!range.m_bUsed)
|
|
{
|
|
// Setup the configuration of the root signature entry (a constant dummy CBV in this case)
|
|
for (AZ::u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx)
|
|
{
|
|
m_RootParameters[m_NumRootParameters++].InitAsConstantBufferView(rootParameterIdx, 0, visibility);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ConstantBufferLayoutBinding constant;
|
|
constant.ShaderStage = shaderStage;
|
|
constant.ShaderSlot = rangeBegin;
|
|
constant.RootParameterIndex = m_NumRootParameters;
|
|
m_ConstantViews.push_back(constant);
|
|
|
|
m_RootParameters[m_NumRootParameters++].InitAsConstantBufferView(rangeBegin, 0, visibility);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PipelineLayout::AppendDescriptorTables(Shader* pShader, EShaderStage shaderStage)
|
|
{
|
|
const D3D12_SHADER_VISIBILITY visibility = ToShaderVisibility(shaderStage);
|
|
|
|
const ReflectedBindings& bindings = pShader->GetReflectedBindings();
|
|
|
|
AZ::u32 rangeCursorBegin = m_DescRangeCursor;
|
|
AZ::u32 rangeCursorEnd = m_DescRangeCursor;
|
|
AZ::u32 descriptorBegin = m_NumDescriptors;
|
|
AZ::u32 descriptorEnd = m_NumDescriptors;
|
|
|
|
if (bindings.m_ConstantBuffers.m_DescriptorCount)
|
|
{
|
|
auto& ranges = bindings.m_ConstantBuffers.m_Ranges;
|
|
for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx)
|
|
{
|
|
const ReflectedBindingRange range = ranges[rangeIdx];
|
|
|
|
AZ::u32 rangeBegin = range.m_ShaderRegister;
|
|
AZ::u32 rangeEnd = range.m_ShaderRegister + range.m_Count;
|
|
|
|
if (IsRootConstantBuffer(range))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Setup the configuration of the descriptor table range (a number of CBVs in this case)
|
|
m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, range.m_Count, range.m_ShaderRegister);
|
|
|
|
for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister)
|
|
{
|
|
ResourceLayoutBinding bindingLayout;
|
|
ZeroStruct(bindingLayout);
|
|
|
|
bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_CBV;
|
|
bindingLayout.ShaderStage = shaderStage;
|
|
bindingLayout.ShaderSlot = shaderRegister;
|
|
|
|
#ifdef GFX_DEBUG
|
|
bindingLayout.DescriptorOffset = descriptorEnd;
|
|
#endif
|
|
|
|
m_TableResources.push_back(bindingLayout);
|
|
++descriptorEnd;
|
|
}
|
|
|
|
if constexpr (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_CBV))
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility);
|
|
}
|
|
}
|
|
}
|
|
|
|
if constexpr (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SRV))
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility);
|
|
}
|
|
|
|
if (bindings.m_InputResources.m_DescriptorCount)
|
|
{
|
|
auto& ranges = bindings.m_InputResources.m_Ranges;
|
|
for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx)
|
|
{
|
|
const ReflectedBindingRange range = ranges[rangeIdx];
|
|
AZ::u32 rangeBegin = range.m_ShaderRegister;
|
|
AZ::u32 rangeEnd = range.m_ShaderRegister + range.m_Count;
|
|
|
|
if (!range.m_bUsed)
|
|
{
|
|
// Setup the configuration of the root signature entry (a constant dummy SRV in this case)
|
|
for (AZ::u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx)
|
|
{
|
|
m_RootParameters[m_NumRootParameters++].InitAsShaderResourceView(rootParameterIdx, 0, visibility);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// Setup the configuration of the descriptor table range (a number of SRVs in this case)
|
|
m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, range.m_Count, range.m_ShaderRegister);
|
|
|
|
for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister)
|
|
{
|
|
ResourceLayoutBinding bindingLayout;
|
|
ZeroStruct(bindingLayout);
|
|
|
|
bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_SRV;
|
|
bindingLayout.ShaderStage = shaderStage;
|
|
bindingLayout.ShaderSlot = shaderRegister;
|
|
#ifdef GFX_DEBUG
|
|
bindingLayout.DescriptorOffset = descriptorEnd;
|
|
#endif
|
|
m_TableResources.push_back(bindingLayout);
|
|
++descriptorEnd;
|
|
}
|
|
|
|
if constexpr (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SRV))
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility);
|
|
}
|
|
}
|
|
}
|
|
|
|
if constexpr (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_UAV))
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility);
|
|
}
|
|
|
|
if (bindings.m_OutputResources.m_DescriptorCount)
|
|
{
|
|
auto& ranges = bindings.m_OutputResources.m_Ranges;
|
|
for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx)
|
|
{
|
|
const ReflectedBindingRange range = ranges[rangeIdx];
|
|
AZ::u32 rangeBegin = range.m_ShaderRegister;
|
|
AZ::u32 rangeEnd = range.m_ShaderRegister + range.m_Count;
|
|
|
|
if (!range.m_bUsed)
|
|
{
|
|
// Setup the configuration of the root signature entry (a constant dummy UAV in this case)
|
|
for (AZ::u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx)
|
|
{
|
|
m_RootParameters[m_NumRootParameters++].InitAsUnorderedAccessView(rootParameterIdx, 0, visibility);
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// Setup the configuration of the descriptor table range (a number of UAVs in this case)
|
|
m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_UAV, range.m_Count, range.m_ShaderRegister);
|
|
|
|
for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister)
|
|
{
|
|
ResourceLayoutBinding bindingLayout;
|
|
ZeroStruct(bindingLayout);
|
|
|
|
bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_UAV;
|
|
bindingLayout.ShaderStage = shaderStage;
|
|
bindingLayout.ShaderSlot = shaderRegister;
|
|
#ifdef GFX_DEBUG
|
|
bindingLayout.DescriptorOffset = descriptorEnd;
|
|
#endif
|
|
m_TableResources.push_back(bindingLayout);
|
|
++descriptorEnd;
|
|
}
|
|
|
|
if constexpr (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_UAV))
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility);
|
|
}
|
|
}
|
|
}
|
|
|
|
if constexpr (DX12_DESCRIPTORTABLE_MERGERANGES_MODE != 0)
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, descriptorEnd, descriptorBegin, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, visibility);
|
|
}
|
|
|
|
m_NumDescriptors = descriptorEnd;
|
|
|
|
AZ::u32 lastSamplers = m_NumDynamicSamplers;
|
|
AZ::u32 currentSamplers = m_NumDynamicSamplers;
|
|
|
|
if (bindings.m_Samplers.m_DescriptorCount)
|
|
{
|
|
auto& ranges = bindings.m_Samplers.m_Ranges;
|
|
for (size_t rangeIdx = 0; rangeIdx < ranges.size(); ++rangeIdx)
|
|
{
|
|
const ReflectedBindingRange range = ranges[rangeIdx];
|
|
AZ::u32 rangeBegin = range.m_ShaderRegister;
|
|
AZ::u32 rangeEnd = range.m_ShaderRegister + range.m_Count;
|
|
|
|
if (!range.m_bUsed)
|
|
{
|
|
// Setup the configuration of the root signature entry (a constant dummy UAV in this case)
|
|
for (AZ::u32 rootParameterIdx = rangeBegin; rootParameterIdx < rangeEnd; ++rootParameterIdx)
|
|
{
|
|
__debugbreak();
|
|
// m_StaticSamplers[m_NumStaticSamplers++].Init(rj, 0, ..., static_cast<D3D12_SHADER_VISIBILITY>((stage + 1) % (D3D12_SHADER_VISIBILITY_PIXEL + 1)));
|
|
}
|
|
|
|
continue;
|
|
}
|
|
|
|
// Setup the configuration of the descriptor table range (a number of Samplers in this case)
|
|
m_DescRanges[rangeCursorEnd++].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, range.m_Count, range.m_ShaderRegister);
|
|
|
|
for (size_t shaderRegister = rangeBegin; shaderRegister < rangeEnd; ++shaderRegister)
|
|
{
|
|
ResourceLayoutBinding bindingLayout;
|
|
ZeroStruct(bindingLayout);
|
|
|
|
bindingLayout.ViewType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER;
|
|
bindingLayout.ShaderStage = shaderStage;
|
|
bindingLayout.ShaderSlot = shaderRegister;
|
|
#ifdef GFX_DEBUG
|
|
bindingLayout.DescriptorOffset = currentSamplers;
|
|
#endif
|
|
m_Samplers.push_back(bindingLayout);
|
|
++currentSamplers;
|
|
}
|
|
|
|
if constexpr (!(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SMP))
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, currentSamplers, lastSamplers, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, visibility);
|
|
}
|
|
}
|
|
}
|
|
|
|
if constexpr (bool(DX12_DESCRIPTORTABLE_MERGERANGES_MODE & DX12_DESCRIPTORTABLE_MERGERANGES_SMP))
|
|
{
|
|
MakeDescriptorTable(rangeCursorEnd, rangeCursorBegin, currentSamplers, lastSamplers, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, visibility);
|
|
}
|
|
|
|
m_NumDynamicSamplers = currentSamplers;
|
|
m_DescRangeCursor = rangeCursorEnd;
|
|
}
|
|
|
|
void PipelineLayout::DebugPrint() const
|
|
{
|
|
DX12_LOG("Root Signature:");
|
|
for (AZ::u32 p = 0, r = 0; p < m_NumRootParameters; ++p)
|
|
{
|
|
DX12_LOG(" %s: %c [%2d to %2d] -> %s [%2d to %2d]",
|
|
m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_ALL ? "Every shader stage" :
|
|
m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_VERTEX ? "Vertex shader stage" :
|
|
m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_HULL ? "Hull shader stage" :
|
|
m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_DOMAIN ? "Domain shader stage" :
|
|
m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_GEOMETRY ? "Geometry shader stage" :
|
|
m_RootParameters[p].ShaderVisibility == D3D12_SHADER_VISIBILITY_PIXEL ? "Pixel shader stage" : "Unknown shader stage",
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_CBV ? 'C' :
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SRV ? 'T' :
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_UAV ? 'U' :
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && m_RootParameters[p].DescriptorTable.pDescriptorRanges->RangeType == D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER ? 'S' :
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV ? 'c' :
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_SRV ? 't' :
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_UAV ? 'u' : '?',
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_RootParameters[p].DescriptorTable.pDescriptorRanges->BaseShaderRegister : m_RootParameters[p].Descriptor.ShaderRegister,
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_RootParameters[p].DescriptorTable.pDescriptorRanges->BaseShaderRegister + m_RootParameters[p].DescriptorTable.pDescriptorRanges->NumDescriptors : 1,
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? "descriptor table" :
|
|
m_RootParameters[p].ParameterType != D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS ? "descriptor" : "32bit constant",
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_DescriptorTables[r].m_Offset : -1,
|
|
m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE ? m_DescriptorTables[r].m_Offset + m_RootParameters[p].DescriptorTable.pDescriptorRanges->NumDescriptors : -1);
|
|
|
|
r += m_RootParameters[p].ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE;
|
|
}
|
|
}
|
|
|
|
RootSignature::RootSignature(Device* device)
|
|
: DeviceObject(device)
|
|
, m_nodeMask(0)
|
|
{
|
|
}
|
|
|
|
RootSignature::~RootSignature()
|
|
{
|
|
}
|
|
|
|
bool RootSignature::Init(const ComputeInitParams& params)
|
|
{
|
|
m_PipelineLayout.Build(params.m_ComputeShader);
|
|
return Init(CommandModeCompute);
|
|
}
|
|
|
|
bool RootSignature::Init(const GraphicsInitParams& params)
|
|
{
|
|
m_PipelineLayout.Build(
|
|
params.m_VertexShader,
|
|
params.m_HullShader ,
|
|
params.m_DomainShader,
|
|
params.m_GeometryShader,
|
|
params.m_PixelShader);
|
|
|
|
return Init(CommandModeGraphics);
|
|
}
|
|
|
|
bool RootSignature::Init(PipelineLayout& pipelineLayout, CommandMode commandType)
|
|
{
|
|
m_PipelineLayout = pipelineLayout;
|
|
return Init(commandType);
|
|
}
|
|
|
|
bool RootSignature::Init(CommandMode commandType)
|
|
{
|
|
ID3D12RootSignature* rootSign = NULL;
|
|
CD3DX12_ROOT_SIGNATURE_DESC descRootSignature;
|
|
|
|
if (commandType == CommandModeGraphics)
|
|
{
|
|
D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
|
|
flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Vertex)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE;
|
|
flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Hull)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE;
|
|
flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Domain)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE;
|
|
flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Geometry)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE;
|
|
flags |= (m_PipelineLayout.m_ShaderStageAccess & BIT(ESS_Pixel)) == 0 ? D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS : D3D12_ROOT_SIGNATURE_FLAG_NONE;
|
|
|
|
descRootSignature.Init(
|
|
m_PipelineLayout.m_NumRootParameters,
|
|
m_PipelineLayout.m_RootParameters,
|
|
m_PipelineLayout.m_NumStaticSamplers,
|
|
m_PipelineLayout.m_StaticSamplers,
|
|
flags);
|
|
}
|
|
else
|
|
{
|
|
descRootSignature.Init(
|
|
m_PipelineLayout.m_NumRootParameters,
|
|
m_PipelineLayout.m_RootParameters,
|
|
0, NULL,
|
|
D3D12_ROOT_SIGNATURE_FLAG_DENY_VERTEX_SHADER_ROOT_ACCESS |
|
|
D3D12_ROOT_SIGNATURE_FLAG_DENY_HULL_SHADER_ROOT_ACCESS |
|
|
D3D12_ROOT_SIGNATURE_FLAG_DENY_DOMAIN_SHADER_ROOT_ACCESS |
|
|
D3D12_ROOT_SIGNATURE_FLAG_DENY_GEOMETRY_SHADER_ROOT_ACCESS |
|
|
D3D12_ROOT_SIGNATURE_FLAG_DENY_PIXEL_SHADER_ROOT_ACCESS);
|
|
}
|
|
|
|
{
|
|
ID3DBlob* pOutBlob = NULL;
|
|
ID3DBlob* pErrorBlob = NULL;
|
|
|
|
if (S_OK != D3D12SerializeRootSignature(&descRootSignature, D3D_ROOT_SIGNATURE_VERSION_1, &pOutBlob, &pErrorBlob))
|
|
{
|
|
DX12_ERROR("Could not serialize root signature!");
|
|
return false;
|
|
}
|
|
|
|
if (S_OK != GetDevice()->GetD3D12Device()->CreateRootSignature(m_nodeMask, pOutBlob->GetBufferPointer(), pOutBlob->GetBufferSize(), IID_GRAPHICS_PPV_ARGS(&rootSign)))
|
|
{
|
|
DX12_ERROR("Could not create root signature!");
|
|
return false;
|
|
}
|
|
|
|
if (pOutBlob)
|
|
{
|
|
pOutBlob->Release();
|
|
}
|
|
|
|
if (pErrorBlob)
|
|
{
|
|
pErrorBlob->Release();
|
|
}
|
|
}
|
|
|
|
m_pRootSignature = rootSign;
|
|
rootSign->Release();
|
|
return true;
|
|
}
|
|
|
|
RootSignatureCache::RootSignatureCache()
|
|
{
|
|
}
|
|
|
|
RootSignatureCache::~RootSignatureCache()
|
|
{
|
|
}
|
|
|
|
bool RootSignatureCache::Init(Device* device)
|
|
{
|
|
m_pDevice = device;
|
|
return true;
|
|
}
|
|
|
|
static const THash ComputeBit = 1;
|
|
|
|
RootSignature* RootSignatureCache::AcquireRootSignature(const RootSignature::GraphicsInitParams& params)
|
|
{
|
|
struct HashKey
|
|
{
|
|
AZ::u32 vs;
|
|
AZ::u32 hs;
|
|
AZ::u32 ds;
|
|
AZ::u32 gs;
|
|
AZ::u32 ps;
|
|
} hashKey;
|
|
|
|
hashKey.vs = params.m_VertexShader ? params.m_VertexShader->GetReflectedBindingHash() : 0;
|
|
hashKey.hs = params.m_HullShader ? params.m_HullShader->GetReflectedBindingHash() : 0;
|
|
hashKey.ds = params.m_DomainShader ? params.m_DomainShader->GetReflectedBindingHash() : 0;
|
|
hashKey.gs = params.m_GeometryShader ? params.m_GeometryShader->GetReflectedBindingHash() : 0;
|
|
hashKey.ps = params.m_PixelShader ? params.m_PixelShader->GetReflectedBindingHash() : 0;
|
|
|
|
// LSB filled marks compute pipeline states, in case graphics and compute hashes collide
|
|
THash hash = ~ComputeBit & ComputeSmallHash<sizeof(HashKey)>(&hashKey);
|
|
{
|
|
auto iter = m_RootSignatureMap.find(hash);
|
|
if (iter != m_RootSignatureMap.end())
|
|
{
|
|
return iter->second.get();
|
|
}
|
|
}
|
|
|
|
RootSignature* result = new RootSignature(m_pDevice);
|
|
if (!result->Init(params))
|
|
{
|
|
DX12_ERROR("Could not create root signature!");
|
|
return nullptr;
|
|
}
|
|
|
|
m_RootSignatureMap[hash] = result;
|
|
return result;
|
|
}
|
|
|
|
RootSignature* RootSignatureCache::AcquireRootSignature(const RootSignature::ComputeInitParams& params)
|
|
{
|
|
THash hash = ComputeBit | params.m_ComputeShader->GetReflectedBindingHash();
|
|
{
|
|
auto iter = m_RootSignatureMap.find(hash);
|
|
if (iter != m_RootSignatureMap.end())
|
|
{
|
|
return iter->second;
|
|
}
|
|
}
|
|
|
|
RootSignature* result = new RootSignature(m_pDevice);
|
|
if (!result->Init(params))
|
|
{
|
|
DX12_ERROR("Could not create root signature!");
|
|
return nullptr;
|
|
}
|
|
|
|
m_RootSignatureMap[hash] = result;
|
|
return result;
|
|
}
|
|
}
|