From 2d68a6e0686f2931a5047430e4085b2710bb1098 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 14 Feb 2021 19:08:26 -0800 Subject: Reworked D3D12 resource signatures to not rely on fixed MAX_SPACES_PER_SIGNATURE; reworked handling of immutable samplers --- .../include/PipelineResourceSignatureD3D12Impl.hpp | 67 ++++---- .../GraphicsEngineD3D12/include/RootSignature.hpp | 22 ++- .../src/D3D12TypeConversions.cpp | 39 +---- .../src/PipelineResourceSignatureD3D12Impl.cpp | 191 +++++++++++++-------- .../src/PipelineStateD3D12Impl.cpp | 24 ++- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 178 +++++++++++-------- 6 files changed, 296 insertions(+), 225 deletions(-) (limited to 'Graphics/GraphicsEngineD3D12') diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp index 9f0fda98..8fd7ee7d 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineResourceSignatureD3D12Impl.hpp @@ -53,8 +53,6 @@ class PipelineResourceSignatureD3D12Impl final : public PipelineResourceSignatur public: using TPipelineResourceSignatureBase = PipelineResourceSignatureBase; - static constexpr Uint32 MAX_SPACES_PER_SIGNATURE = 128; - PipelineResourceSignatureD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDevice, const PipelineResourceSignatureDesc& Desc, @@ -77,10 +75,11 @@ public: static constexpr Uint32 _SpaceBits = 8; static constexpr Uint32 _SigRootIndexBits = 3; static constexpr Uint32 _SamplerAssignedBits = 1; - static constexpr Uint32 _RootViewFlagBits = 1; + static constexpr Uint32 _RootParamTypeBits = 3; static_assert((1u << _RegisterBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store sahder register"); static_assert((1u << _SamplerIndBits) >= MAX_RESOURCES_IN_SIGNATURE, "Not enough bits to store sampler resource index"); + static_assert((1u << _RootParamTypeBits) > D3D12_ROOT_PARAMETER_TYPE_UAV + 1, "Not enough bits to store D3D12_ROOT_PARAMETER_TYPE"); public: static constexpr Uint32 InvalidSamplerInd = (1u << _SamplerIndBits) - 1; @@ -93,41 +92,42 @@ public: /* 0 */const Uint32 Register : _RegisterBits; // Shader register /* 2 */const Uint32 SRBRootIndex : _SRBRootIndexBits; // Root view/table index in the SRB /* 4 */const Uint32 SamplerInd : _SamplerIndBits; // Index in m_Desc.Resources and m_pResourceAttribs -/* 6 */const Uint32 Space : _SpaceBits; // Shader register space (local space in range 0..MAX_SPACES_PER_SIGNATURE) +/* 6 */const Uint32 Space : _SpaceBits; // Shader register space /* 7.0*/const Uint32 SigRootIndex : _SigRootIndexBits; // Root table index for signature (static only) /* 7.3*/const Uint32 ImtblSamplerAssigned : _SamplerAssignedBits; // Immutable sampler flag -/* 7.4*/const Uint32 IsRootView : _RootViewFlagBits; // Is root view (for debugging) +/* 7.4*/const Uint32 RootParamType : _RootParamTypeBits; // Root parameter type (for debugging) /* 8 */const Uint32 SigOffsetFromTableStart; // Offset in the root table for signature (static only) /* 12 */const Uint32 SRBOffsetFromTableStart; // Offset in the root table for SRB /* 16 */ // clang-format on - ResourceAttribs(Uint32 _Register, - Uint32 _Space, - Uint32 _SamplerInd, - Uint32 _SRBRootIndex, - Uint32 _SRBOffsetFromTableStart, - Uint32 _SigRootIndex, - Uint32 _SigOffsetFromTableStart, - bool _ImtblSamplerAssigned, - bool _IsRootView) noexcept : + ResourceAttribs(Uint32 _Register, + Uint32 _Space, + Uint32 _SamplerInd, + Uint32 _SRBRootIndex, + Uint32 _SRBOffsetFromTableStart, + Uint32 _SigRootIndex, + Uint32 _SigOffsetFromTableStart, + bool _ImtblSamplerAssigned, + D3D12_ROOT_PARAMETER_TYPE _RootParamType) noexcept : // clang-format off - Register {_Register }, - SRBRootIndex {_SRBRootIndex }, - SamplerInd {_SamplerInd }, - SigRootIndex {_SigRootIndex }, - Space {_Space }, - ImtblSamplerAssigned {_ImtblSamplerAssigned ? 1u : 0u}, - IsRootView {_IsRootView ? 1u : 0u }, - SigOffsetFromTableStart{_SigOffsetFromTableStart }, - SRBOffsetFromTableStart{_SRBOffsetFromTableStart } + Register {_Register }, + SRBRootIndex {_SRBRootIndex }, + SamplerInd {_SamplerInd }, + SigRootIndex {_SigRootIndex }, + Space {_Space }, + ImtblSamplerAssigned {_ImtblSamplerAssigned ? 1u : 0u }, + RootParamType {static_cast(_RootParamType)}, + SigOffsetFromTableStart{_SigOffsetFromTableStart }, + SRBOffsetFromTableStart{_SRBOffsetFromTableStart } // clang-format on { VERIFY(Register == _Register, "Shader register (", _Register, ") exceeds maximum representable value"); VERIFY(SRBRootIndex == _SRBRootIndex, "SRB Root index (", _SRBRootIndex, ") exceeds maximum representable value"); - VERIFY(SigRootIndex == _SigRootIndex, "Signature Root index (", SigRootIndex, ") exceeds maximum representable value"); + VERIFY(SigRootIndex == _SigRootIndex, "Signature Root index (", _SigRootIndex, ") exceeds maximum representable value"); VERIFY(SamplerInd == _SamplerInd, "Sampler index (", _SamplerInd, ") exceeds maximum representable value"); - VERIFY(Space == _Space, "Space (", Space, ") exceeds maximum representable value"); + VERIFY(Space == _Space, "Space (", _Space, ") exceeds maximum representable value"); + VERIFY(GetD3D12RootParamType() == _RootParamType, "Not enough bits to represent root parameter type"); } bool IsImmutableSamplerAssigned() const { return ImtblSamplerAssigned != 0; } @@ -135,6 +135,8 @@ public: Uint32 RootIndex(CacheContentType Type) const { return Type == CacheContentType::SRB ? SRBRootIndex : SigRootIndex; } Uint32 OffsetFromTableStart(CacheContentType Type) const { return Type == CacheContentType::SRB ? SRBOffsetFromTableStart : SigOffsetFromTableStart; } + + D3D12_ROOT_PARAMETER_TYPE GetD3D12RootParamType() const { return static_cast(RootParamType); } }; const ResourceAttribs& GetResourceAttribs(Uint32 ResIndex) const @@ -160,7 +162,7 @@ public: public: Uint32 ArraySize = 1; Uint32 ShaderRegister : _ShaderRegisterBits; - Uint32 RegisterSpace : _RegisterSpaceBits; // (local space in range 0..MAX_SPACES_PER_SIGNATURE) + Uint32 RegisterSpace : _RegisterSpaceBits; ImmutableSamplerAttribs() : ShaderRegister{_InvalidShaderRegister}, @@ -180,7 +182,11 @@ public: VERIFY(RegisterSpace == _RegisterSpace, "Shader register space (", _RegisterSpace, ") exceeds maximum representable value"); } - bool IsAssigned() const { return ShaderRegister != _InvalidShaderRegister; } + bool IsValid() const + { + return ShaderRegister != _InvalidShaderRegister && + RegisterSpace != _InvalidRegisterSpace; + } }; const ImmutableSamplerAttribs& GetImmutableSamplerAttribs(Uint32 SampIndex) const @@ -210,11 +216,6 @@ public: return m_RootParams.GetNumRootViews(); } - Uint32 GetBaseRegisterSpace() const - { - return m_Desc.BindingIndex * MAX_SPACES_PER_SIGNATURE; - } - virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) override final; @@ -296,8 +297,6 @@ private: std::array m_StaticVarIndex = {-1, -1, -1, -1, -1, -1}; static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); - Uint32 m_NumSpaces = 0; - ShaderResourceCacheD3D12* m_pStaticResCache = nullptr; ShaderVariableManagerD3D12* m_StaticVarsMgrs = nullptr; // [m_NumShaderStages] diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp index 7e1817ea..a2ef646c 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp @@ -79,11 +79,24 @@ public: return m_FirstRootIndex[BindingIndex]; } + Uint32 GetFirstRegisterSpace(Uint32 BindingIndex) const + { + VERIFY_EXPR(BindingIndex <= m_SignatureCount); + return m_FirstRegisterSpace[BindingIndex]; + } + + Uint32 GetTotalSpaces() const + { + return m_TotalSpacesUsed; + } + using SignatureArrayType = std::array, MAX_RESOURCE_SIGNATURES>; private: - using FirstRootIndexArrayType = std::array; // AZ TODO: use 8 or 16 bit int - FirstRootIndexArrayType m_FirstRootIndex = {}; + std::array m_FirstRootIndex = {}; + std::array m_FirstRegisterSpace = {}; + + Uint32 m_TotalSpacesUsed = 0; size_t m_Hash = 0; CComPtr m_pd3d12RootSignature; @@ -105,16 +118,17 @@ public: bool IsShaderRecord(const D3DShaderResourceAttribs& CB); - ID3D12RootSignature* Create(ID3D12Device* pDevice); + ID3D12RootSignature* Create(ID3D12Device* pDevice, Uint32 RegisterSpace); bool IsDefined() const { return m_ShaderRecordSize > 0 && m_pName != nullptr; } const char* GetName() const { return m_pName; } - Uint32 GetRegisterSpace() const { return PipelineResourceSignatureD3D12Impl::MAX_SPACES_PER_SIGNATURE * MAX_RESOURCE_SIGNATURES; } Uint32 GetShaderRegister() const { return 0; } + Uint32 GetRegisterSpace() const { return m_RegisterSpace; } private: const char* m_pName = nullptr; const Uint32 m_ShaderRecordSize = 0; + Uint32 m_RegisterSpace = 0; CComPtr m_pd3d12RootSignature; }; diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp index 5ea9ed01..66edc30d 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp @@ -543,6 +543,8 @@ D3D12_RENDER_PASS_ENDING_ACCESS_TYPE AttachmentStoreOpToD3D12EndingAccessType(AT D3D12_SHADER_VISIBILITY ShaderTypeToD3D12ShaderVisibility(SHADER_TYPE ShaderType) { + VERIFY(IsPowerOfTwo(ShaderType), "Only single shader stage should be provided"); + static_assert(SHADER_TYPE_LAST == 0x2000, "Please update the switch below to handle the new shader type"); switch (ShaderType) { @@ -793,40 +795,9 @@ D3D12_DESCRIPTOR_HEAP_TYPE D3D12DescriptorRangeTypeToD3D12HeapType(D3D12_DESCRIP D3D12_SHADER_VISIBILITY ShaderStagesToD3D12ShaderVisibility(SHADER_TYPE Stages) { - if (!IsPowerOfTwo(Stages)) - { - return D3D12_SHADER_VISIBILITY_ALL; - } - - static_assert(SHADER_TYPE_LAST == 0x2000, "Please update the switch below to handle the new shader type"); - switch (Stages) - { - // clang-format off - case SHADER_TYPE_PIXEL: return D3D12_SHADER_VISIBILITY_PIXEL; - case SHADER_TYPE_VERTEX: return D3D12_SHADER_VISIBILITY_VERTEX; - case SHADER_TYPE_GEOMETRY: return D3D12_SHADER_VISIBILITY_GEOMETRY; - case SHADER_TYPE_HULL: return D3D12_SHADER_VISIBILITY_HULL; - case SHADER_TYPE_DOMAIN: return D3D12_SHADER_VISIBILITY_DOMAIN; - -#ifdef D3D12_H_HAS_MESH_SHADER - case SHADER_TYPE_AMPLIFICATION: return D3D12_SHADER_VISIBILITY_AMPLIFICATION; - case SHADER_TYPE_MESH: return D3D12_SHADER_VISIBILITY_MESH; -#endif - // clang-format on - - case SHADER_TYPE_COMPUTE: - case SHADER_TYPE_RAY_GEN: - case SHADER_TYPE_RAY_MISS: - case SHADER_TYPE_RAY_CLOSEST_HIT: - case SHADER_TYPE_RAY_ANY_HIT: - case SHADER_TYPE_RAY_INTERSECTION: - case SHADER_TYPE_CALLABLE: - return D3D12_SHADER_VISIBILITY_ALL; - - default: - UNEXPECTED("Unknown shader type"); - return D3D12_SHADER_VISIBILITY_ALL; - } + return IsPowerOfTwo(Stages) ? + ShaderTypeToD3D12ShaderVisibility(Stages) : + D3D12_SHADER_VISIBILITY_ALL; } } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp index dd257c2e..fe9f17f5 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineResourceSignatureD3D12Impl.cpp @@ -190,26 +190,99 @@ PipelineResourceSignatureD3D12Impl::PipelineResourceSignatureD3D12Impl(IReferenc void PipelineResourceSignatureD3D12Impl::CreateLayout() { - const Uint32 FirstSpace = GetBaseRegisterSpace(); + // Index of the assigned sampler, for every texture SRV in m_Desc.Resources, or InvalidSamplerInd. + std::vector TextureSrvToAssignedSamplerInd(m_Desc.NumResources, ResourceAttribs::InvalidSamplerInd); + // Index of the immutable sampler for every sampler in m_Desc.Resources, or -1. + std::vector ResourceToImmutableSamplerInd(m_Desc.NumResources, -1); + for (Uint32 i = 0; i < m_Desc.NumResources; ++i) + { + const auto& ResDesc = m_Desc.Resources[i]; + + if (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER) + { + // We only need to search for immutable samplers for SHADER_RESOURCE_TYPE_SAMPLER. + // For SHADER_RESOURCE_TYPE_TEXTURE_SRV, we will look for the assigned sampler and check if it is immutable. + + // Note that FindImmutableSampler() below will work properly both when combined texture samplers are used and when not: + // - When combined texture samplers are used, sampler suffix will not be null, + // and we will be looking for the 'Texture_sampler' name. + // - When combined texture samplers are not used, sampler suffix will be null, + // and we will be looking for the sampler name itself. + const auto SrcImmutableSamplerInd = FindImmutableSampler(m_Desc.ImmutableSamplers, m_Desc.NumImmutableSamplers, ResDesc.ShaderStages, + ResDesc.Name, GetCombinedSamplerSuffix()); + if (SrcImmutableSamplerInd >= 0) + { + ResourceToImmutableSamplerInd[i] = SrcImmutableSamplerInd; + // Set the immutable sampler array size to match the resource array size + auto& DstImtblSampAttribs = m_ImmutableSamplers[SrcImmutableSamplerInd]; + // One immutable sampler may be used by different arrays in different shader stages - use the maximum array size + DstImtblSampAttribs.ArraySize = std::max(DstImtblSampAttribs.ArraySize, ResDesc.ArraySize); + } + } - std::array NumResources = {}; + if (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV) + { + TextureSrvToAssignedSamplerInd[i] = FindAssignedSampler(ResDesc); + } + } + + // The total number of resources (counting array size), for every descriptor range type + std::array NumResources = {}; + // Static resource cache table sizes std::array StaticResCacheTblSizes = {}; + // Allocate registers for immutable samplers first + for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i) + { + auto& ImmutableSampler = m_ImmutableSamplers[i]; + + constexpr auto DescriptorRangeType = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; + + ImmutableSampler.RegisterSpace = 0; + ImmutableSampler.ShaderRegister = NumResources[DescriptorRangeType]; + NumResources[DescriptorRangeType] += ImmutableSampler.ArraySize; + } + + RootParamsBuilder ParamsBuilder; + + Uint32 NextRTSizedArraySpace = 1; for (Uint32 i = 0; i < m_Desc.NumResources; ++i) { const auto& ResDesc = m_Desc.Resources[i]; - VERIFY(i == 0 || ResDesc.VarType >= m_Desc.Resources[i - 1].VarType, "Resources must be sorted by variable type"); - const bool IsRuntimeSizedArray = (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0; - const auto DescriptorRangeType = ResourceTypeToD3D12DescriptorRangeType(ResDesc.ResourceType); - Uint32 Register = IsRuntimeSizedArray ? 0 : NumResources[DescriptorRangeType]; - Uint32 Space = (IsRuntimeSizedArray ? m_NumSpaces++ : 0); - Uint32 SRBRootIndex = ResourceAttribs::InvalidSRBRootIndex; - Uint32 SRBOffsetFromTableStart = ResourceAttribs::InvalidOffset; - Uint32 SigRootIndex = ResourceAttribs::InvalidSigRootIndex; - Uint32 SigOffsetFromTableStart = ResourceAttribs::InvalidOffset; + auto AssignedSamplerInd = TextureSrvToAssignedSamplerInd[i]; + auto SrcImmutableSamplerInd = ResourceToImmutableSamplerInd[i]; + if (AssignedSamplerInd != ResourceAttribs::InvalidSamplerInd) + { + VERIFY_EXPR(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV); + SrcImmutableSamplerInd = ResourceToImmutableSamplerInd[AssignedSamplerInd]; + if (SrcImmutableSamplerInd >= 0) + AssignedSamplerInd = ResourceAttribs::InvalidSamplerInd; + } + + const auto DescriptorRangeType = ResourceTypeToD3D12DescriptorRangeType(ResDesc.ResourceType); + Uint32 Register = 0; + Uint32 Space = 0; + if ((ResDesc.Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) != 0) + { + // All run-time sized arrays are allocated in separate spaces. + Space = NextRTSizedArraySpace++; + Register = 0; + } + else + { + // Normal resources go into space 0. + Space = 0; + Register = NumResources[DescriptorRangeType]; + NumResources[DescriptorRangeType] += ResDesc.ArraySize; + } + + Uint32 SRBRootIndex = ResourceAttribs::InvalidSRBRootIndex; + Uint32 SRBOffsetFromTableStart = ResourceAttribs::InvalidOffset; + Uint32 SigRootIndex = ResourceAttribs::InvalidSigRootIndex; + Uint32 SigOffsetFromTableStart = ResourceAttribs::InvalidOffset; if (ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC) { @@ -218,59 +291,49 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() // UAVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_UAV (1) // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV (2) // Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER (3) - SigRootIndex = ResourceTypeToD3D12DescriptorRangeType(ResDesc.ResourceType); + SigRootIndex = DescriptorRangeType; SigOffsetFromTableStart = StaticResCacheTblSizes[SigRootIndex]; StaticResCacheTblSizes[SigRootIndex] += ResDesc.ArraySize; } - const bool IsBuffer = - ResDesc.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER || - ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV || - ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV; - const bool UseDynamicOffset = (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS) == 0; - const bool IsFormattedBuffer = (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != 0; - const bool IsRootView = IsBuffer && UseDynamicOffset && !IsFormattedBuffer; - - // runtime sized array must be in separate space - if (!IsRuntimeSizedArray) - NumResources[DescriptorRangeType] += ResDesc.ArraySize; - - const Int32 SrcImmutableSamplerInd = ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER ? - FindImmutableSampler(m_Desc.ImmutableSamplers, m_Desc.NumImmutableSamplers, ResDesc.ShaderStages, ResDesc.Name, GetCombinedSamplerSuffix()) : - -1; - - const auto AssignedSamplerInd = (SrcImmutableSamplerInd == -1 && ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV) ? - FindAssignedSampler(ResDesc) : - ResourceAttribs::InvalidSamplerInd; - - if (SrcImmutableSamplerInd >= 0) + auto d3d12RootParamType = static_cast(D3D12_ROOT_PARAMETER_TYPE_UAV + 1); + // Do not allocate resource slot for immutable samplers that are also defined as resource + if (!(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER && SrcImmutableSamplerInd >= 0)) { - auto& ImmutableSampler = m_ImmutableSamplers[SrcImmutableSamplerInd]; + const auto UseDynamicOffset = (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_NO_DYNAMIC_BUFFERS) == 0; + const auto IsFormattedBuffer = (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != 0; - if (!ImmutableSampler.IsAssigned()) - { - ImmutableSampler.ShaderRegister = Register; - ImmutableSampler.RegisterSpace = Space; - ImmutableSampler.ArraySize = ResDesc.ArraySize; - } - else + d3d12RootParamType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + switch (ResDesc.ResourceType) { - Register = ImmutableSampler.ShaderRegister; - Space = ImmutableSampler.RegisterSpace; + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: + VERIFY(!IsFormattedBuffer, "Constant buffers can't be labeled as formatted. This error should've been cuaght by ValidatePipelineResourceSignatureDesc()."); + d3d12RootParamType = UseDynamicOffset ? D3D12_ROOT_PARAMETER_TYPE_CBV : D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + break; - VERIFY_EXPR(ResDesc.ArraySize == ImmutableSampler.ArraySize); + case SHADER_RESOURCE_TYPE_BUFFER_SRV: + d3d12RootParamType = UseDynamicOffset && !IsFormattedBuffer ? D3D12_ROOT_PARAMETER_TYPE_SRV : D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + break; - // Use previous bind point and decrease resource counter - if (!IsRuntimeSizedArray) - NumResources[DescriptorRangeType] -= ResDesc.ArraySize; + case SHADER_RESOURCE_TYPE_BUFFER_UAV: + d3d12RootParamType = UseDynamicOffset && !IsFormattedBuffer ? D3D12_ROOT_PARAMETER_TYPE_UAV : D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; + break; + + default: + d3d12RootParamType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; } + + ParamsBuilder.AllocateResourceSlot(ResDesc.ShaderStages, ResDesc.VarType, d3d12RootParamType, + DescriptorRangeType, ResDesc.ArraySize, Register, Space, SRBRootIndex, + SRBOffsetFromTableStart); } else { - ParamsBuilder.AllocateResourceSlot(ResDesc.ShaderStages, ResDesc.VarType, - IsRootView ? D3D12_ROOT_PARAMETER_TYPE_CBV : D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE, - DescriptorRangeType, ResDesc.ArraySize, Register, FirstSpace + Space, SRBRootIndex, - SRBOffsetFromTableStart); + const auto& ImtblSamAttribs = GetImmutableSamplerAttribs(SrcImmutableSamplerInd); + VERIFY_EXPR(ImtblSamAttribs.IsValid()); + // Initialize space and register, which are required for register remapping + Space = ImtblSamAttribs.RegisterSpace; + Register = ImtblSamAttribs.ShaderRegister; } new (m_pResourceAttribs + i) ResourceAttribs // @@ -283,25 +346,11 @@ void PipelineResourceSignatureD3D12Impl::CreateLayout() SigRootIndex, SigOffsetFromTableStart, SrcImmutableSamplerInd >= 0, - IsRootView // + d3d12RootParamType // }; } ParamsBuilder.InitializeMgr(GetRawAllocator(), m_RootParams); - // Add immutable samplers that do not exist in m_Desc.Resources - for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i) - { - auto& ImmutableSampler = m_ImmutableSamplers[i]; - if (ImmutableSampler.IsAssigned()) - continue; - - const auto DescriptorRangeType = ResourceTypeToD3D12DescriptorRangeType(SHADER_RESOURCE_TYPE_SAMPLER); - - ImmutableSampler.RegisterSpace = 0; - ImmutableSampler.ShaderRegister = NumResources[DescriptorRangeType]; - NumResources[DescriptorRangeType] += 1; - } - if (m_Desc.SRBAllocationGranularity > 1) { std::array ShaderVariableDataSizes = {}; @@ -1199,8 +1248,8 @@ struct BindResourceHelper ShaderResourceCacheD3D12& ResourceCache; #ifdef DILIGENT_DEBUG - bool dbgIsDynamic = false; - bool dbgIsRootView = false; + bool dbgIsDynamic = false; + D3D12_ROOT_PARAMETER_TYPE dbgParamType = D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE; #endif void BindResource(IDeviceObject* pObj) const; @@ -1256,7 +1305,7 @@ void BindResourceHelper::CacheCB(IDeviceObject* pBuffer) const } else { - VERIFY(dbgIsRootView || dbgIsDynamic, "Descriptor in root table can be used only in dynamic tables."); + VERIFY(dbgParamType == D3D12_ROOT_PARAMETER_TYPE_CBV || dbgIsDynamic, "Descriptor in root table can be used only in dynamic tables."); } auto& BoundDynamicCBsCounter = ResourceCache.GetBoundDynamicCBsCounter(); @@ -1587,8 +1636,8 @@ void PipelineResourceSignatureD3D12Impl::BindResource(IDeviceObject* ResourceCache}; #ifdef DILIGENT_DEBUG - Helper.dbgIsDynamic = RootTable.IsDynamic(); - Helper.dbgIsRootView = Attribs.IsRootView != 0; + Helper.dbgIsDynamic = RootTable.IsDynamic(); + Helper.dbgParamType = Attribs.GetD3D12RootParamType(); #endif Helper.BindResource(pObj); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index ca0d0fb8..149b0678 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -527,6 +527,7 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr } else { + // TODO: move to base class const auto PipelineType = CreateInfo.PSODesc.PipelineType; for (Uint32 i = 0; i < SignatureCount; ++i) { @@ -581,7 +582,7 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr auto* pSignature = GetSignature(Sig); if (pSignature != nullptr) { - const Uint32 FirstSpace = pSignature->GetBaseRegisterSpace(); + const Uint32 FirstSpace = m_RootSig->GetFirstRegisterSpace(Sig); for (Uint32 r = 0, ResCount = pSignature->GetTotalResourceCount(); r < ResCount; ++r) { @@ -605,14 +606,21 @@ void PipelineStateD3D12Impl::InitRootSignature(const PipelineStateCreateInfo& Cr { HasImtblSampArray = HasImtblSampArray || (SampAttr.ArraySize > 1); - auto IsUnique = ResourceMap.emplace(HashMapStringKey{ImtblSam.SamplerOrTextureName}, BindInfo).second; - if (!IsUnique && pSignature->IsUsingCombinedSamplers()) - { - // add sampler with suffix - String SampName{ImtblSam.SamplerOrTextureName}; + String SampName{ImtblSam.SamplerOrTextureName}; + if (pSignature->IsUsingCombinedSamplers()) SampName += pSignature->GetCombinedSamplerSuffix(); - ResourceMap.emplace(HashMapStringKey{SampName}, BindInfo); + + auto it_inserted = ResourceMap.emplace(HashMapStringKey{SampName}, BindInfo); +#ifdef DILIGENT_DEBUG + if (!it_inserted.second) + { + const auto& ExistingBindInfo = it_inserted.first->second; + VERIFY(ExistingBindInfo.BindPoint == BindInfo.BindPoint, + "Bind point defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource."); + VERIFY(ExistingBindInfo.Space == BindInfo.Space, + "Register space defined by the immutable sampler attribs is inconsistent with the bind point defined by the sampler resource."); } +#endif } } } @@ -980,7 +988,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* D3D12_GLOBAL_ROOT_SIGNATURE GlobalRoot = {m_RootSig->GetD3D12RootSignature()}; Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE, &GlobalRoot}); - D3D12_LOCAL_ROOT_SIGNATURE LocalRoot = {LocalRootSig.Create(pd3d12Device)}; + D3D12_LOCAL_ROOT_SIGNATURE LocalRoot = {LocalRootSig.Create(pd3d12Device, m_RootSig->GetTotalSpaces())}; if (LocalRoot.pLocalRootSignature) Subobjects.push_back({D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE, &LocalRoot}); diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 32a63841..a794f4fe 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -84,104 +84,132 @@ void RootSignatureD3D12::Finalize() rootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT; Uint32 TotalParams = 0; - Uint32 TotalD3D12StaticSamplers = 0; - + Uint32 Totald3d12StaticSamplers = 0; + Uint32 TotalDescriptorRanges = 0; for (Uint32 s = 0; s < m_SignatureCount; ++s) { auto& pSignature = m_Signatures[s]; - if (pSignature != nullptr) - { - auto& RootParams = pSignature->m_RootParams; + if (pSignature == nullptr) + continue; - m_FirstRootIndex[s] = TotalParams; - TotalParams += RootParams.GetNumRootTables() + RootParams.GetNumRootViews(); + auto& RootParams = pSignature->m_RootParams; - for (Uint32 samp = 0, SampCount = pSignature->GetImmutableSamplerCount(); samp < SampCount; ++samp) - { - const auto& ImtblSam = pSignature->GetImmutableSamplerAttribs(samp); - VERIFY_EXPR(ImtblSam.IsAssigned()); + m_FirstRootIndex[s] = static_cast(TotalParams); + TotalParams += RootParams.GetNumRootTables() + RootParams.GetNumRootViews(); - TotalD3D12StaticSamplers += ImtblSam.ArraySize; - } + for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt) + { + const auto& RootTable = RootParams.GetRootTable(rt); + TotalDescriptorRanges += RootTable.d3d12RootParam.DescriptorTable.NumDescriptorRanges; + } + + for (Uint32 samp = 0, SampCount = pSignature->GetImmutableSamplerCount(); samp < SampCount; ++samp) + { + const auto& ImtblSam = pSignature->GetImmutableSamplerAttribs(samp); + VERIFY_EXPR(ImtblSam.IsValid()); + + Totald3d12StaticSamplers += ImtblSam.ArraySize; } } - std::vector> D3D12Parameters(TotalParams, D3D12_ROOT_PARAMETER{}, STD_ALLOCATOR_RAW_MEM(D3D12_ROOT_PARAMETER, GetRawAllocator(), "Allocator for vector")); - std::vector> D3D12StaticSamplers(STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector")); - D3D12StaticSamplers.reserve(TotalD3D12StaticSamplers); + std::vector> d3d12Parameters(TotalParams, D3D12_ROOT_PARAMETER{}, STD_ALLOCATOR_RAW_MEM(D3D12_ROOT_PARAMETER, GetRawAllocator(), "Allocator for vector")); + std::vector> d3d12DescrRanges(TotalDescriptorRanges, D3D12_DESCRIPTOR_RANGE{}, STD_ALLOCATOR_RAW_MEM(D3D12_DESCRIPTOR_RANGE, GetRawAllocator(), "Allocator for vector")); + std::vector> d3d12StaticSamplers(STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector")); + d3d12StaticSamplers.reserve(Totald3d12StaticSamplers); + auto descr_range_it = d3d12DescrRanges.begin(); + + Uint32 BaseRegisterSpace = 0; for (Uint32 sig = 0; sig < m_SignatureCount; ++sig) { - auto& pSignature = m_Signatures[sig]; + m_FirstRegisterSpace[sig] = static_cast(BaseRegisterSpace); - if (pSignature != nullptr) - { - const auto FirstRootIndex = m_FirstRootIndex[sig]; - const Uint32 FirstSpace = pSignature->GetBaseRegisterSpace(); + const auto& pSignature = m_Signatures[sig]; + if (pSignature == nullptr) + continue; - auto& RootParams = pSignature->m_RootParams; - for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt) - { - const auto& RootTable = RootParams.GetRootTable(rt); - const auto& SrcParam = RootTable.d3d12RootParam; - const Uint32 RootIndex = FirstRootIndex + RootTable.RootIndex; - VERIFY(SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && SrcParam.DescriptorTable.NumDescriptorRanges > 0, "Non-empty descriptor table is expected"); - D3D12Parameters[RootIndex] = SrcParam; - } + const auto& RootParams = pSignature->m_RootParams; + const auto FirstRootIndex = m_FirstRootIndex[sig]; - for (Uint32 rv = 0; rv < RootParams.GetNumRootViews(); ++rv) + Uint32 MaxSpaceUsed = 0; + for (Uint32 rt = 0; rt < RootParams.GetNumRootTables(); ++rt) + { + const auto& RootTable = RootParams.GetRootTable(rt); + const auto& d3d12SrcParam = RootTable.d3d12RootParam; + const auto& d3d12SrcTbl = d3d12SrcParam.DescriptorTable; + const Uint32 RootIndex = FirstRootIndex + RootTable.RootIndex; + VERIFY(d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE && d3d12SrcParam.DescriptorTable.NumDescriptorRanges > 0, "Non-empty descriptor table is expected"); + auto& d3d12DstParam = d3d12Parameters[RootIndex]; + auto& d3d12DstTbl = d3d12DstParam.DescriptorTable; + + d3d12DstParam = d3d12SrcParam; + memcpy(&*descr_range_it, d3d12SrcTbl.pDescriptorRanges, d3d12SrcTbl.NumDescriptorRanges * sizeof(D3D12_DESCRIPTOR_RANGE)); + d3d12DstTbl.pDescriptorRanges = &*descr_range_it; + for (Uint32 r = 0; r < d3d12SrcTbl.NumDescriptorRanges; ++r, ++descr_range_it) { - const auto& RootView = RootParams.GetRootView(rv); - const auto& SrcParam = RootView.d3d12RootParam; - const Uint32 RootIndex = FirstRootIndex + RootView.RootIndex; - VERIFY(SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV, "Root CBV is expected"); - D3D12Parameters[RootIndex] = SrcParam; + MaxSpaceUsed = std::max(MaxSpaceUsed, descr_range_it->RegisterSpace); + descr_range_it->RegisterSpace += BaseRegisterSpace; } + } + + for (Uint32 rv = 0; rv < RootParams.GetNumRootViews(); ++rv) + { + const auto& RootView = RootParams.GetRootView(rv); + const auto& d3d12SrcParam = RootView.d3d12RootParam; + const Uint32 RootIndex = FirstRootIndex + RootView.RootIndex; + VERIFY(d3d12SrcParam.ParameterType == D3D12_ROOT_PARAMETER_TYPE_CBV, "Root CBV is expected"); + MaxSpaceUsed = std::max(MaxSpaceUsed, d3d12SrcParam.Descriptor.RegisterSpace); + + d3d12Parameters[RootIndex] = d3d12SrcParam; + d3d12Parameters[RootIndex].Descriptor.RegisterSpace += BaseRegisterSpace; + } + + for (Uint32 samp = 0, SampCount = pSignature->GetImmutableSamplerCount(); samp < SampCount; ++samp) + { + const auto& SampAttr = pSignature->GetImmutableSamplerAttribs(samp); + const auto& ImtblSam = pSignature->GetImmutableSamplerDesc(samp); + const auto& SamDesc = ImtblSam.Desc; - for (Uint32 samp = 0, SampCount = pSignature->GetImmutableSamplerCount(); samp < SampCount; ++samp) + for (UINT ArrInd = 0; ArrInd < SampAttr.ArraySize; ++ArrInd) { - const auto& SampAttr = pSignature->GetImmutableSamplerAttribs(samp); - const auto& ImtblSam = pSignature->GetImmutableSamplerDesc(samp); - const auto& SamDesc = ImtblSam.Desc; - - for (UINT ArrInd = 0; ArrInd < SampAttr.ArraySize; ++ArrInd) - { - D3D12_SHADER_VISIBILITY ShaderVisibility = (ImtblSam.ShaderStages & (ImtblSam.ShaderStages - 1)) == 0 ? - ShaderTypeToD3D12ShaderVisibility(ImtblSam.ShaderStages) : - D3D12_SHADER_VISIBILITY_ALL; - - D3D12StaticSamplers.emplace_back( - D3D12_STATIC_SAMPLER_DESC // - { - FilterTypeToD3D12Filter(SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter), - TexAddressModeToD3D12AddressMode(SamDesc.AddressU), - TexAddressModeToD3D12AddressMode(SamDesc.AddressV), - TexAddressModeToD3D12AddressMode(SamDesc.AddressW), - SamDesc.MipLODBias, - SamDesc.MaxAnisotropy, - ComparisonFuncToD3D12ComparisonFunc(SamDesc.ComparisonFunc), - BorderColorToD3D12StaticBorderColor(SamDesc.BorderColor), - SamDesc.MinLOD, - SamDesc.MaxLOD, - SampAttr.ShaderRegister + ArrInd, - SampAttr.RegisterSpace + FirstSpace, - ShaderVisibility // - } // - ); - } + auto ShaderVisibility = ShaderStagesToD3D12ShaderVisibility(ImtblSam.ShaderStages); + + d3d12StaticSamplers.emplace_back( + D3D12_STATIC_SAMPLER_DESC // + { + FilterTypeToD3D12Filter(SamDesc.MinFilter, SamDesc.MagFilter, SamDesc.MipFilter), + TexAddressModeToD3D12AddressMode(SamDesc.AddressU), + TexAddressModeToD3D12AddressMode(SamDesc.AddressV), + TexAddressModeToD3D12AddressMode(SamDesc.AddressW), + SamDesc.MipLODBias, + SamDesc.MaxAnisotropy, + ComparisonFuncToD3D12ComparisonFunc(SamDesc.ComparisonFunc), + BorderColorToD3D12StaticBorderColor(SamDesc.BorderColor), + SamDesc.MinLOD, + SamDesc.MaxLOD, + SampAttr.ShaderRegister + ArrInd, + SampAttr.RegisterSpace + BaseRegisterSpace, + ShaderVisibility // + } // + ); } } + + BaseRegisterSpace += MaxSpaceUsed + 1; } + m_TotalSpacesUsed = BaseRegisterSpace; + + VERIFY_EXPR(descr_range_it == d3d12DescrRanges.end()); - rootSignatureDesc.NumParameters = static_cast(D3D12Parameters.size()); - rootSignatureDesc.pParameters = D3D12Parameters.size() ? D3D12Parameters.data() : nullptr; + rootSignatureDesc.NumParameters = static_cast(d3d12Parameters.size()); + rootSignatureDesc.pParameters = d3d12Parameters.size() ? d3d12Parameters.data() : nullptr; - rootSignatureDesc.NumStaticSamplers = TotalD3D12StaticSamplers; + rootSignatureDesc.NumStaticSamplers = Totald3d12StaticSamplers; rootSignatureDesc.pStaticSamplers = nullptr; - if (!D3D12StaticSamplers.empty()) + if (!d3d12StaticSamplers.empty()) { - rootSignatureDesc.pStaticSamplers = D3D12StaticSamplers.data(); - VERIFY_EXPR(D3D12StaticSamplers.size() == TotalD3D12StaticSamplers); + rootSignatureDesc.pStaticSamplers = d3d12StaticSamplers.data(); + VERIFY_EXPR(d3d12StaticSamplers.size() == Totald3d12StaticSamplers); } CComPtr signature; @@ -220,11 +248,13 @@ bool LocalRootSignatureD3D12::IsShaderRecord(const D3DShaderResourceAttribs& CB) return false; } -ID3D12RootSignature* LocalRootSignatureD3D12::Create(ID3D12Device* pDevice) +ID3D12RootSignature* LocalRootSignatureD3D12::Create(ID3D12Device* pDevice, Uint32 RegisterSpace) { if (m_ShaderRecordSize == 0) return nullptr; + m_RegisterSpace = RegisterSpace; + VERIFY(m_pd3d12RootSignature == nullptr, "This root signature is already created"); D3D12_ROOT_SIGNATURE_DESC d3d12RootSignatureDesc = {}; @@ -233,7 +263,7 @@ ID3D12RootSignature* LocalRootSignatureD3D12::Create(ID3D12Device* pDevice) d3d12Params.ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS; d3d12Params.ShaderVisibility = D3D12_SHADER_VISIBILITY_ALL; d3d12Params.Constants.Num32BitValues = m_ShaderRecordSize / 4; - d3d12Params.Constants.RegisterSpace = GetRegisterSpace(); + d3d12Params.Constants.RegisterSpace = m_RegisterSpace; d3d12Params.Constants.ShaderRegister = GetShaderRegister(); d3d12RootSignatureDesc.Flags = D3D12_ROOT_SIGNATURE_FLAG_LOCAL_ROOT_SIGNATURE; -- cgit v1.2.3