From c2a6a2c4b716d45ddc92ed04bb0ac7fb7200e548 Mon Sep 17 00:00:00 2001 From: Egor Yusov Date: Thu, 18 Oct 2018 08:38:21 -0700 Subject: Implemented separate samplers in D3D12 --- .../include/ShaderResourceLayoutD3D11.h | 12 +- .../src/ShaderResourceLayoutD3D11.cpp | 28 ++- .../src/ShaderResourcesD3D11.cpp | 2 +- .../GraphicsEngineD3D12/include/RootSignature.h | 7 +- .../include/ShaderResourceLayoutD3D12.h | 15 +- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 29 ++- .../src/ShaderResourceLayoutD3D12.cpp | 268 +++++++++++---------- .../src/ShaderVariableD3D12.cpp | 28 ++- .../include/D3DShaderResourceLoader.h | 4 +- .../include/ShaderResources.h | 23 +- .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 2 +- 11 files changed, 232 insertions(+), 186 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h index 24284cec..274c0e28 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.h @@ -250,7 +250,7 @@ private: const ConstBuffBindInfo& GetCB(Uint32 cb)const { VERIFY_EXPR(cb(m_ResourceBuffer.get())[cb]; + return reinterpret_cast(m_ResourceBuffer.get())[cb]; } TexSRVBindInfo& GetTexSRV(Uint32 t) @@ -261,7 +261,7 @@ private: const TexSRVBindInfo& GetTexSRV(Uint32 t)const { VERIFY_EXPR(t( reinterpret_cast(m_ResourceBuffer.get()) + m_TexSRVsOffset)[t]; + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_TexSRVsOffset)[t]; } TexUAVBindInfo& GetTexUAV(Uint32 u) @@ -272,7 +272,7 @@ private: const TexUAVBindInfo& GetTexUAV(Uint32 u)const { VERIFY_EXPR(u < m_NumTexUAVs); - return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_TexUAVsOffset)[u]; + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_TexUAVsOffset)[u]; } BuffUAVBindInfo& GetBufUAV(Uint32 u) @@ -283,7 +283,7 @@ private: const BuffUAVBindInfo& GetBufUAV(Uint32 u)const { VERIFY_EXPR(u < m_NumBufUAVs); - return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_BuffUAVsOffset)[u]; + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_BuffUAVsOffset)[u]; } BuffSRVBindInfo& GetBufSRV(Uint32 s) @@ -294,7 +294,7 @@ private: const BuffSRVBindInfo& GetBufSRV(Uint32 s)const { VERIFY_EXPR(s < m_NumBufSRVs); - return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_BuffSRVsOffset)[s]; + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_BuffSRVsOffset)[s]; } SamplerBindInfo& GetSampler(Uint32 s) @@ -305,7 +305,7 @@ private: const SamplerBindInfo& GetSampler(Uint32 s)const { VERIFY_EXPR(s < m_NumSamplers); - return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_SamplerOffset)[s]; + return reinterpret_cast( reinterpret_cast(m_ResourceBuffer.get()) + m_SamplerOffset)[s]; } templateGetSampler(TexSRV.GetSamplerId()); + DEV_CHECK_ERR(AssignedSamplerAttribs.GetVariableType() == TexSRV.GetVariableType(), + "The type (", GetShaderVariableTypeLiteralName(TexSRV.GetVariableType()),") of texture SRV variable '", TexSRV.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(AssignedSamplerAttribs.GetVariableType()), + ") of the sampler '", AssignedSamplerAttribs.Name, "' that is assigned to it"); // Do not assign static sampler to texture SRV as it is initialized directly in the shader resource cache if (!AssignedSamplerAttribs.IsStaticSampler()) { @@ -366,7 +370,7 @@ void ShaderResourceLayoutD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* p { auto &pResourceCache = m_ParentResLayout.m_pResourceCache; VERIFY(pResourceCache, "Resource cache is null"); - VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + DEV_CHECK_ERR(ArrayIndex < Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", Attribs.Name, "'. Max allowed index: ", Attribs.BindCount); RefCntAutoPtr pBuffD3D11Impl; if( pBuffer ) @@ -448,7 +452,7 @@ void ShaderResourceLayoutD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pVie Uint32 ArrayIndex) { VERIFY(m_ParentResLayout.m_pResourceCache, "Resource cache is null"); - VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + DEV_CHECK_ERR(ArrayIndex < Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", Attribs.Name, "'. Max allowed index: ", Attribs.BindCount); auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the @@ -502,7 +506,7 @@ void ShaderResourceLayoutD3D11::SamplerBindInfo::BindResource(IDeviceObject* pSa Uint32 ArrayIndex) { VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); - VERIFY_EXPR(ArrayIndex < Attribs.BindCount); + DEV_CHECK_ERR(ArrayIndex < Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", Attribs.Name, "'. Max allowed index: ", Attribs.BindCount); auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; VERIFY(!Attribs.IsStaticSampler(), "Cannot bind sampler to a static sampler"); @@ -538,7 +542,7 @@ void ShaderResourceLayoutD3D11::BuffSRVBindInfo::BindResource(IDeviceObject* pVi Uint32 ArrayIndex) { VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); - VERIFY(ArrayIndex < Attribs.BindCount, "Array index is out of range"); + DEV_CHECK_ERR(ArrayIndex < Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", Attribs.Name, "'. Max allowed index: ", Attribs.BindCount); auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the @@ -569,7 +573,7 @@ void ShaderResourceLayoutD3D11::TexUAVBindInfo::BindResource(IDeviceObject* pVie Uint32 ArrayIndex) { VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); - VERIFY(ArrayIndex < Attribs.BindCount, "Array index is out of range"); + DEV_CHECK_ERR(ArrayIndex < Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", Attribs.Name, "'. Max allowed index: ", Attribs.BindCount); auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the @@ -600,7 +604,7 @@ void ShaderResourceLayoutD3D11::BuffUAVBindInfo::BindResource(IDeviceObject* pVi Uint32 ArrayIndex) { VERIFY(m_ParentResLayout.m_pResourceCache != nullptr, "Resource cache is null"); - VERIFY(ArrayIndex < Attribs.BindCount, "Array index is out of range"); + DEV_CHECK_ERR(ArrayIndex < Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", Attribs.Name, "'. Max allowed index: ", Attribs.BindCount); auto& ResourceCache = *m_ParentResLayout.m_pResourceCache; // We cannot use ValidatedCast<> here as the resource retrieved from the @@ -799,7 +803,7 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base Uint32 Index = 0; if (Offset < m_TexSRVsOffset) { - VERIFY(Offset % sizeof(ConstBuffBindInfo) == 0, "Offset is not multiple of sizeof(ConstBuffBindInfo)"); + DEV_CHECK_ERR(Offset % sizeof(ConstBuffBindInfo) == 0, "Offset is not multiple of sizeof(ConstBuffBindInfo)"); return Index + static_cast(Offset / sizeof(ConstBuffBindInfo)); } else @@ -807,7 +811,7 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base if (Offset < m_TexUAVsOffset) { - VERIFY( (Offset - m_TexSRVsOffset) % sizeof(TexSRVBindInfo) == 0, "Offset is not multiple of sizeof(TexSRVBindInfo)"); + DEV_CHECK_ERR( (Offset - m_TexSRVsOffset) % sizeof(TexSRVBindInfo) == 0, "Offset is not multiple of sizeof(TexSRVBindInfo)"); return Index + static_cast((Offset - m_TexSRVsOffset) / sizeof(TexSRVBindInfo)); } else @@ -815,7 +819,7 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base if (Offset < m_BuffUAVsOffset) { - VERIFY( (Offset - m_TexUAVsOffset) % sizeof(TexUAVBindInfo) == 0, "Offset is not multiple of sizeof(TexUAVBindInfo)"); + DEV_CHECK_ERR( (Offset - m_TexUAVsOffset) % sizeof(TexUAVBindInfo) == 0, "Offset is not multiple of sizeof(TexUAVBindInfo)"); return Index + static_cast((Offset - m_TexUAVsOffset) / sizeof(TexUAVBindInfo)); } else @@ -823,7 +827,7 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base if (Offset < m_BuffSRVsOffset) { - VERIFY( (Offset - m_BuffUAVsOffset) % sizeof(BuffUAVBindInfo) == 0, "Offset is not multiple of sizeof(BuffUAVBindInfo)" ); + DEV_CHECK_ERR( (Offset - m_BuffUAVsOffset) % sizeof(BuffUAVBindInfo) == 0, "Offset is not multiple of sizeof(BuffUAVBindInfo)" ); return Index + static_cast((Offset - m_BuffUAVsOffset) / sizeof(BuffUAVBindInfo)); } else @@ -831,7 +835,7 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base if (Offset < static_cast(m_BuffSRVsOffset + m_NumBufSRVs * sizeof(BuffSRVBindInfo))) { - VERIFY( (Offset - m_BuffSRVsOffset) % sizeof(BuffSRVBindInfo) == 0, "Offset is not multiple of sizeof(BuffSRVBindInfo)" ); + DEV_CHECK_ERR( (Offset - m_BuffSRVsOffset) % sizeof(BuffSRVBindInfo) == 0, "Offset is not multiple of sizeof(BuffSRVBindInfo)" ); return Index + static_cast((Offset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo)); } else @@ -839,7 +843,7 @@ Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base if (Offset < static_cast(m_SamplerOffset + m_NumSamplers * sizeof(SamplerBindInfo))) { - VERIFY( (Offset - m_SamplerOffset) % sizeof(SamplerBindInfo) == 0, "Offset is not multiple of sizeof(SamplerBindInfo)" ); + DEV_CHECK_ERR( (Offset - m_SamplerOffset) % sizeof(SamplerBindInfo) == 0, "Offset is not multiple of sizeof(SamplerBindInfo)" ); return Index + static_cast((Offset - m_SamplerOffset) / sizeof(SamplerBindInfo)); } else diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp index b92c16fe..544d9088 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp @@ -116,7 +116,7 @@ ShaderResourcesD3D11::ShaderResourcesD3D11(RenderDeviceD3D11Impl* pDeviceD3D11Im for (; ssd < ShdrDesc.NumStaticSamplers; ++ssd) { const auto& StaticSamplerDesc = ShdrDesc.StaticSamplers[ssd]; - if (StrCmpSuff(Sam.Name, StaticSamplerDesc.SamplerOrTextureName, CombinedSamplerSuffix)) + if (StreqSuff(Sam.Name, StaticSamplerDesc.SamplerOrTextureName, CombinedSamplerSuffix)) { auto &StaticSamplerAttrs = GetStaticSampler(CurrStaticSam++); StaticSamplerAttrs.first = &Sam; diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.h b/Graphics/GraphicsEngineD3D12/include/RootSignature.h index 66e6002f..6c99d1a4 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.h +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.h @@ -298,9 +298,10 @@ public: void InitResourceCache(class RenderDeviceD3D12Impl* pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator& CacheMemAllocator)const; - void InitStaticSampler(SHADER_TYPE ShaderType, - const String& TextureName, - const D3DShaderResourceAttribs& ShaderResAttribs); + void InitStaticSampler(SHADER_TYPE ShaderType, + const char* SamplerName, + const char* SamplerSuffix, + const D3DShaderResourceAttribs& ShaderResAttribs); void AllocateResourceSlot(SHADER_TYPE ShaderType, const D3DShaderResourceAttribs& ShaderResAttribs, diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h index 460c06c6..4328c893 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.h @@ -186,9 +186,9 @@ public: Uint32 ArrayIndex, ShaderResourceCacheD3D12& ResourceCache)const; - bool IsValidSampler() const { return SamplerId != InvalidSamplerId; } - bool IsValidRootIndex()const { return RootIndex != InvalidRootIndex; } - bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; } + bool ValidSamplerAssigned()const { return SamplerId != InvalidSamplerId; } + bool IsValidRootIndex() const { return RootIndex != InvalidRootIndex; } + bool IsValidOffset() const { return OffsetFromTableStart != InvalidOffset; } CachedResourceType GetResType() const { return static_cast( ResourceType ); } @@ -208,7 +208,7 @@ public: TViewTypeEnum dbgExpectedViewType, TBindSamplerProcType BindSamplerProc)const; - void CacheSampler(class ITextureViewD3D12* pTexViewD3D12, + void CacheSampler(IDeviceObject* pSampler, ShaderResourceCacheD3D12::Resource& DstSam, Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)const; @@ -244,6 +244,8 @@ public: return GetResource(GetSamplerOffset(VarType,s)); } + const bool IsUsingSeparateSamplers() const {return !m_pResources->IsUsingCombinedTextureSamplers();} + private: const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv)const; D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv); @@ -300,6 +302,11 @@ private: VERIFY_EXPR( s < GetSamplerCount(VarType) ); return GetResource(GetSamplerOffset(VarType,s)); } + const D3D12Resource& GetSampler(Uint32 s)const + { + VERIFY_EXPR( s < GetTotalSamplerCount() ); + return GetResource(m_SamplersOffsets[0] + s); + } void AllocateMemory(IMemoryAllocator& Allocator, const std::array& CbvSrvUavCount, diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index 565fc958..4578d1f7 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -255,14 +255,17 @@ D3D12_DESCRIPTOR_HEAP_TYPE HeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE Ran } -void RootSignature::InitStaticSampler(SHADER_TYPE ShaderType, const String& TextureName, const D3DShaderResourceAttribs& SamplerAttribs) +void RootSignature::InitStaticSampler(SHADER_TYPE ShaderType, + const char* SamplerName, + const char* SamplerSuffix, + const D3DShaderResourceAttribs& SamplerAttribs) { auto ShaderVisibility = GetShaderVisibility(ShaderType); auto SamplerFound = false; for (auto& StSmplr : m_StaticSamplers) { if (StSmplr.ShaderVisibility == ShaderVisibility && - TextureName.compare(StSmplr.SamplerDesc.SamplerOrTextureName) == 0) + StreqSuff(SamplerName, StSmplr.SamplerDesc.SamplerOrTextureName, SamplerSuffix)) { StSmplr.ShaderRegister = SamplerAttribs.BindPoint; StSmplr.ArraySize = SamplerAttribs.BindCount; @@ -274,7 +277,7 @@ void RootSignature::InitStaticSampler(SHADER_TYPE ShaderType, const String& Text if (!SamplerFound) { - LOG_ERROR("Failed to find static sampler for variable \"", TextureName, '\"'); + LOG_ERROR("Unable to find static sampler \'", SamplerName, '\''); } } @@ -935,22 +938,24 @@ void RootSignature::CommitDescriptorHandlesInternal_SMD(RenderDeviceD3D12Impl* { if (IsResourceTable) { - if( Res.CPUDescriptorHandle.ptr == 0 ) + VERIFY( DynamicCbvSrvUavTblOffset < NumDynamicCbvSrvUavDescriptors, "Not enough space in the descriptor heap allocation"); + + if( Res.CPUDescriptorHandle.ptr != 0 ) + pd3d12Device->CopyDescriptorsSimple(1, DynamicCbvSrvUavDescriptors.GetCpuHandle(DynamicCbvSrvUavTblOffset), Res.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); + else LOG_ERROR_MESSAGE("No valid CbvSrvUav descriptor handle found for root parameter ", RootInd, ", descriptor slot ", OffsetFromTableStart); - VERIFY( DynamicCbvSrvUavTblOffset < NumDynamicCbvSrvUavDescriptors, "Not enough space in the descriptor heap allocation"); - - pd3d12Device->CopyDescriptorsSimple(1, DynamicCbvSrvUavDescriptors.GetCpuHandle(DynamicCbvSrvUavTblOffset), Res.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV); ++DynamicCbvSrvUavTblOffset; } else { - if( Res.CPUDescriptorHandle.ptr == 0 ) - LOG_ERROR_MESSAGE("No valid sampler descriptor handle found for root parameter ", RootInd, ", descriptor slot ", OffsetFromTableStart); - VERIFY( DynamicSamplerTblOffset < NumDynamicSamplerDescriptors, "Not enough space in the descriptor heap allocation"); - - pd3d12Device->CopyDescriptorsSimple(1, DynamicSamplerDescriptors.GetCpuHandle(DynamicSamplerTblOffset), Res.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + + if( Res.CPUDescriptorHandle.ptr != 0 ) + pd3d12Device->CopyDescriptorsSimple(1, DynamicSamplerDescriptors.GetCpuHandle(DynamicSamplerTblOffset), Res.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); + else + LOG_ERROR_MESSAGE("No valid sampler descriptor handle found for root parameter ", RootInd, ", descriptor slot ", OffsetFromTableStart); + ++DynamicSamplerTblOffset; } } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 708d971b..a3c910df 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -140,7 +140,10 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* [&](const D3DShaderResourceAttribs& Sam, Uint32) { VERIFY_EXPR(Sam.IsAllowedType(AllowedTypeBits)); - + if (!Sam.IsStaticSampler()) + { + ++SamplerCount[Sam.GetVariableType()]; + } }, [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { @@ -151,11 +154,10 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* { auto SamplerId = TexSRV.GetSamplerId(); const auto& SamplerAttribs = m_pResources->GetSampler(SamplerId); - VERIFY(SamplerAttribs.GetVariableType() == VarType, "Texture and sampler variable types are not conistent"); - if(!SamplerAttribs.IsStaticSampler()) - { - ++SamplerCount[VarType]; - } + DEV_CHECK_ERR(SamplerAttribs.GetVariableType() == TexSRV.GetVariableType(), + "The type (", GetShaderVariableTypeLiteralName(TexSRV.GetVariableType()),") of texture SRV variable '", TexSRV.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SamplerAttribs.GetVariableType()), + ") of the sampler '", SamplerAttribs.Name, "' that is assigned to it"); } }, [&](const D3DShaderResourceAttribs& TexUAV, Uint32) @@ -205,7 +207,7 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* VERIFY_EXPR(pResourceCache != nullptr); RootIndex = DescriptorRangeType; - Offset = Attribs.BindPoint; + Offset = Attribs.BindPoint; // Resources in the static resource cache are indexed by the bind point StaticResCacheTblSizes[RootIndex] = std::max(StaticResCacheTblSizes[RootIndex], Offset + Attribs.BindCount); } @@ -213,7 +215,11 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* VERIFY(Offset != D3D12Resource::InvalidOffset, "Offset must be valid"); // Static samplers are never copied, and SamplerId == InvalidSamplerId - ::new (&GetSrvCbvUav(Attribs.GetVariableType(), CurrCbvSrvUav[Attribs.GetVariableType()]++)) D3D12Resource( *this, Attribs, ResType, RootIndex, Offset, SamplerId); + auto VarType = Attribs.GetVariableType(); + auto& NewResource = (ResType == CachedResourceType::Sampler) ? + GetSampler (VarType, CurrSampler [VarType]++) : + GetSrvCbvUav(VarType, CurrCbvSrvUav[VarType]++); + ::new (&NewResource) D3D12Resource(*this, Attribs, ResType, RootIndex, Offset, SamplerId); }; @@ -228,57 +234,46 @@ void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* [&](const D3DShaderResourceAttribs& Sam, Uint32) { VERIFY_EXPR( Sam.IsAllowedType(AllowedTypeBits) ); - + if (Sam.IsStaticSampler()) + { + if (pRootSig != nullptr) + pRootSig->InitStaticSampler(m_pResources->GetShaderType(), Sam.Name, m_pResources->GetCombinedSamplerSuffix(), Sam); + } + else + { + AddResource(Sam, CachedResourceType::Sampler); + } }, [&](const D3DShaderResourceAttribs& TexSRV, Uint32) { VERIFY_EXPR(TexSRV.IsAllowedType(AllowedTypeBits) ); - auto VarType = TexSRV.GetVariableType(); + static_assert(SHADER_VARIABLE_TYPE_NUM_TYPES == 3, "Unexpected number of shader variable types"); + VERIFY(CurrSampler[SHADER_VARIABLE_TYPE_STATIC] + CurrSampler[SHADER_VARIABLE_TYPE_MUTABLE] + CurrSampler[SHADER_VARIABLE_TYPE_DYNAMIC] == GetTotalSamplerCount(), "All samplers must be initialized before texture SRVs"); Uint32 SamplerId = D3D12Resource::InvalidSamplerId; - if(TexSRV.ValidSamplerAssigned()) + if (TexSRV.ValidSamplerAssigned()) { - const auto& SrcSamplerAttribs = m_pResources->GetSampler(TexSRV.GetSamplerId()); - VERIFY(SrcSamplerAttribs.GetVariableType() == VarType, "Inconsistent texture and sampler variable types" ); + const auto& SamplerAttribs = m_pResources->GetSampler(TexSRV.GetSamplerId()); + DEV_CHECK_ERR(SamplerAttribs.GetVariableType() == TexSRV.GetVariableType(), + "The type (", GetShaderVariableTypeLiteralName(TexSRV.GetVariableType()),") of texture SRV variable '", TexSRV.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(SamplerAttribs.GetVariableType()), + ") of the sampler '", SamplerAttribs.Name, "' that is assigned to it"); - if (SrcSamplerAttribs.IsStaticSampler()) + if (SamplerAttribs.IsStaticSampler()) { - if (pRootSig != nullptr) - pRootSig->InitStaticSampler(m_pResources->GetShaderType(), TexSRV.Name, SrcSamplerAttribs); - // Static samplers are never copied, and SamplerId == InvalidSamplerId } else { - Uint32 SamplerRootIndex = D3D12Resource::InvalidRootIndex; - Uint32 SamplerOffset = D3D12Resource::InvalidOffset; - if (pRootSig) + auto SamplerCount = GetTotalSamplerCount(); + for (SamplerId = 0; SamplerId < SamplerCount; ++SamplerId) { - pRootSig->AllocateResourceSlot(m_pResources->GetShaderType(), SrcSamplerAttribs, D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER, SamplerRootIndex, SamplerOffset ); + const auto& Sampler = GetSampler(SamplerId); + if (strcmp(Sampler.Attribs.Name, SamplerAttribs.Name) == 0) + break; } - else - { - // If root signature is not provided, we are initializing resource cache to store - // static shader resources. - VERIFY_EXPR(pResourceCache != nullptr); - - // We use the following artifial root signature: - // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV (0) - // 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) - // Every resource is stored at offset that equals its bind point - SamplerRootIndex = D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER; - SamplerOffset = SrcSamplerAttribs.BindPoint; - // Resources in the static resource cache are indexed by the bind point - StaticResCacheTblSizes[SamplerRootIndex] = std::max(StaticResCacheTblSizes[SamplerRootIndex], SamplerOffset + SrcSamplerAttribs.BindCount); - } - VERIFY(SamplerRootIndex != D3D12Resource::InvalidRootIndex, "Sampler root index must be valid"); - VERIFY(SamplerOffset != D3D12Resource::InvalidOffset, "Sampler offset must be valid"); - - SamplerId = CurrSampler[VarType]; + VERIFY(SamplerId < SamplerCount, "Unable to find assigned sampler"); VERIFY(SamplerId <= D3D12Resource::MaxSamplerId, "Sampler index excceeds allowed limit"); - ::new (&GetSampler(VarType, CurrSampler[VarType]++)) D3D12Resource( *this, SrcSamplerAttribs, CachedResourceType::Sampler, SamplerRootIndex, SamplerOffset, D3D12Resource::InvalidSamplerId); } } AddResource(TexSRV, CachedResourceType::TexSRV, SamplerId); @@ -354,7 +349,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheCB(IDeviceObject* if(DstRes.pObject != pBuffD3D12) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null constant buffer is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayInd), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempring to bind another constant buffer is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null constant buffer is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayInd), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempring to bind another constant buffer is an error and will be ignored. Use another shader resource binding instance or label the variable as dynamic." ); } // Do not update resource if one is already bound unless it is dynamic. This may be @@ -424,12 +419,12 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject* // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type RefCntAutoPtr pViewD3D12(pView, ResourceViewTraits::IID); - if( pViewD3D12 ) + if (pViewD3D12) { #ifdef DEVELOPMENT const auto& ViewDesc = pViewD3D12->GetDesc(); auto ViewType = ViewDesc.ViewType; - if( ViewType != dbgExpectedViewType ) + if (ViewType != dbgExpectedViewType) { const auto *ExpectedViewTypeName = GetViewTypeLiteralName( dbgExpectedViewType ); const auto *ActualViewTypeName = GetViewTypeLiteralName( ViewType ); @@ -438,12 +433,12 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject* return; } #endif - if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr ) + if (Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr) { if(DstRes.pObject != pViewD3D12) { auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null resource is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempting to bind another resource or null is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); + LOG_ERROR_MESSAGE( "Non-null resource is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempting to bind another resource or null is an error and will be ignored. Use another shader resource binding instance or label the variable as dynamic." ); } // Do not update resource if one is already bound unless it is dynamic. This may be @@ -474,68 +469,60 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject* } } -void ShaderResourceLayoutD3D12::D3D12Resource::CacheSampler(ITextureViewD3D12* pTexViewD3D12, +void ShaderResourceLayoutD3D12::D3D12Resource::CacheSampler(IDeviceObject* pSampler, ShaderResourceCacheD3D12::Resource& DstSam, Uint32 ArrayIndex, D3D12_CPU_DESCRIPTOR_HANDLE ShdrVisibleHeapCPUDescriptorHandle)const { VERIFY(Attribs.IsValidBindPoint(), "Invalid bind point"); VERIFY_EXPR(ArrayIndex < Attribs.BindCount); - - if( pTexViewD3D12 ) + + RefCntAutoPtr pSamplerD3D12(pSampler, IID_SamplerD3D12); + if (pSamplerD3D12) { - auto pSampler = pTexViewD3D12->GetSampler(); - if( pSampler ) + if (Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC && DstSam.pObject != nullptr) { - if( Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC && DstSam.pObject != nullptr) + if (DstSam.pObject != pSampler) { - if(DstSam.pObject != pSampler) - { - auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); - LOG_ERROR_MESSAGE( "Non-null sampler is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempting to bind another sampler is an error and will be ignored. Use another shader resource binding instance or mark shader variable as dynamic." ); - } - - // Do not update resource if one is already bound unless it is dynamic. This may be - // dangerous as CopyDescriptorsSimple() may interfere with GPU reading the same descriptor. - return; + auto VarTypeStr = GetShaderVariableTypeLiteralName(Attribs.GetVariableType()); + LOG_ERROR_MESSAGE( "Non-null sampler is already bound to ", VarTypeStr, " shader variable \"", Attribs.GetPrintName(ArrayIndex), "\" in shader \"", ParentResLayout.GetShaderName(), "\". Attempting to bind another sampler is an error and will be ignored. Use another shader resource binding instance or label the variable as dynamic." ); } + + // Do not update resource if one is already bound unless it is dynamic. This may be + // dangerous as CopyDescriptorsSimple() may interfere with GPU reading the same descriptor. + return; + } - DstSam.Type = CachedResourceType::Sampler; - - auto *pSamplerD3D12 = ValidatedCast(pSampler); - DstSam.CPUDescriptorHandle = pSamplerD3D12->GetCPUDescriptorHandle(); - VERIFY(DstSam.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 sampler descriptor handle"); - - if(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0) - { - // Dynamic resources are assigned descriptor in the GPU-visible heap at every draw call, and - // the descriptor is copied by the RootSignature when resources are committed - VERIFY(DstSam.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); + DstSam.Type = CachedResourceType::Sampler; - ID3D12Device *pd3d12Device = ParentResLayout.m_pd3d12Device; - pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstSam.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - } + DstSam.CPUDescriptorHandle = pSamplerD3D12->GetCPUDescriptorHandle(); + VERIFY(DstSam.CPUDescriptorHandle.ptr != 0, "No relevant D3D12 sampler descriptor handle"); - DstSam.pObject = pSampler; - } - else + if(ShdrVisibleHeapCPUDescriptorHandle.ptr != 0) { - LOG_ERROR_MESSAGE( "Failed to bind sampler to variable \"", Attribs.Name, ". Sampler is not set in the texture view \"", pTexViewD3D12->GetDesc().Name, "\"" ); + // Dynamic resources are assigned descriptor in the GPU-visible heap at every draw call, and + // the descriptor is copied by the RootSignature when resources are committed + VERIFY(DstSam.pObject == nullptr, "Static and mutable resource descriptors must be copied only once"); + + ID3D12Device *pd3d12Device = ParentResLayout.m_pd3d12Device; + pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleHeapCPUDescriptorHandle, DstSam.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } + + DstSam.pObject = pSampler; } else { - DstSam = ShaderResourceCacheD3D12::Resource(); + LOG_RESOURCE_BINDING_ERROR("Sampler", pSampler, Attribs.GetPrintName(ArrayIndex), ParentResLayout.GetShaderName(), "Incorect resource type: sampler is expected.") } } const ShaderResourceLayoutD3D12::D3D12Resource& ShaderResourceLayoutD3D12::GetAssignedSampler(const D3D12Resource& TexSrv)const { VERIFY(TexSrv.GetResType() == CachedResourceType::TexSRV, "Unexpected resource type: texture SRV is expected"); - VERIFY(TexSrv.IsValidSampler(), "Texture SRV has no associated sampler"); - const auto& SamInfo = GetSampler(TexSrv.Attribs.GetVariableType(), TexSrv.SamplerId); + VERIFY(TexSrv.ValidSamplerAssigned(), "Texture SRV has no associated sampler"); + const auto& SamInfo = GetSampler(TexSrv.SamplerId); VERIFY(SamInfo.Attribs.GetVariableType() == TexSrv.Attribs.GetVariableType(), "Inconsistent texture and sampler variable types"); - //VERIFY(StrCmpSuff(SamInfo.Attribs.Name, TexSrv.Attribs.Name, SamplerSuffix), "Sampler name \"", SamInfo.Attribs.Name, "\" does not match texture name \"", TexSrv.Attribs.Name, '\"'); + VERIFY(StreqSuff(SamInfo.Attribs.Name, TexSrv.Attribs.Name, m_pResources->GetCombinedSamplerSuffix()), "Sampler name \"", SamInfo.Attribs.Name, "\" does not match texture name \"", TexSrv.Attribs.Name, '\"'); return SamInfo; } @@ -551,8 +538,12 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* { VERIFY_EXPR(ArrayIndex < Attribs.BindCount); - auto& DstRes = ResourceCache.GetRootTable(RootIndex).GetResource(OffsetFromTableStart + ArrayIndex, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, ParentResLayout.m_pResources->GetShaderType()); - auto ShdrVisibleHeapCPUDescriptorHandle = ResourceCache.GetShaderVisibleTableCPUDescriptorHandle(RootIndex, OffsetFromTableStart+ArrayIndex); + const bool IsSampler = GetResType() == CachedResourceType::Sampler; + auto DescriptorHeapType = IsSampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER : D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV; + auto& DstRes = ResourceCache.GetRootTable(RootIndex).GetResource(OffsetFromTableStart + ArrayIndex, DescriptorHeapType, ParentResLayout.m_pResources->GetShaderType()); + auto ShdrVisibleHeapCPUDescriptorHandle = IsSampler ? + ResourceCache.GetShaderVisibleTableCPUDescriptorHandle (RootIndex, OffsetFromTableStart + ArrayIndex) : + ResourceCache.GetShaderVisibleTableCPUDescriptorHandle(RootIndex, OffsetFromTableStart + ArrayIndex); #ifdef _DEBUG { @@ -592,7 +583,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* case CachedResourceType::TexSRV: CacheResourceView(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle, TEXTURE_VIEW_SHADER_RESOURCE, [&](ITextureViewD3D12* pTexView) { - if(IsValidSampler()) + if(ValidSamplerAssigned()) { auto &Sam = ParentResLayout.GetAssignedSampler(*this); VERIFY( !Sam.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" ); @@ -619,7 +610,15 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* } } #endif - Sam.CacheSampler(pTexView, DstSam, SamplerArrInd, ShdrVisibleSamplerHeapCPUDescriptorHandle); + auto pSampler = pTexView->GetSampler(); + if( pSampler ) + { + Sam.CacheSampler(pSampler, DstSam, SamplerArrInd, ShdrVisibleSamplerHeapCPUDescriptorHandle); + } + else + { + LOG_ERROR_MESSAGE( "Failed to bind sampler to variable \"", Sam.Attribs.Name, ". Sampler is not set in the texture view \"", pTexView->GetDesc().Name, "\"" ); + } } }); break; @@ -636,24 +635,29 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* CacheResourceView(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle, BUFFER_VIEW_UNORDERED_ACCESS, [](IBufferViewD3D12*){}); break; + case CachedResourceType::Sampler: + DEV_CHECK_ERR(ParentResLayout.IsUsingSeparateSamplers(), "Samplers should not be set directly when using combined texture samplers"); + CacheSampler(pObj, DstRes, ArrayIndex, ShdrVisibleHeapCPUDescriptorHandle); + break; + default: UNEXPECTED("Unknown resource type ", static_cast(GetResType())); } } else { - if (DstRes.pObject && Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) - { - LOG_ERROR_MESSAGE( "Shader variable \"", Attribs.Name, "\" in shader \"", ParentResLayout.GetShaderName(), "\" is not dynamic but being unbound. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or mark shader variable as dynamic if you need to bind another resource." ); - } + if (DstRes.pObject != nullptr && Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) + LOG_ERROR_MESSAGE( "Shader variable \"", Attribs.Name, "\" in shader \"", ParentResLayout.GetShaderName(), "\" is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic if you need to bind another resource." ); - DstRes = ShaderResourceCacheD3D12::Resource(); - if(IsValidSampler()) + DstRes = ShaderResourceCacheD3D12::Resource{}; + if (ValidSamplerAssigned()) { auto &Sam = ParentResLayout.GetAssignedSampler(*this); D3D12_CPU_DESCRIPTOR_HANDLE NullHandle = {0}; auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0; auto& DstSam = ResourceCache.GetRootTable(Sam.RootIndex).GetResource(Sam.OffsetFromTableStart + SamplerArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, ParentResLayout.m_pResources->GetShaderType()); - Sam.CacheSampler(nullptr, DstSam, SamplerArrInd, NullHandle); + if (DstSam.pObject != nullptr && Sam.Attribs.GetVariableType() != SHADER_VARIABLE_TYPE_DYNAMIC) + LOG_ERROR_MESSAGE( "Sampler variable \"", Sam.Attribs.Name, "\" in shader \"", ParentResLayout.GetShaderName(), "\" is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic if you need to bind another sampler." ); + DstSam = ShaderResourceCacheD3D12::Resource{}; } } } @@ -734,7 +738,7 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR } } - if(res.IsValidSampler()) + if(res.ValidSamplerAssigned()) { const auto& SamInfo = DstLayout.GetAssignedSampler(res); @@ -742,39 +746,45 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid"); VERIFY_EXPR(SamInfo.Attribs.BindCount == res.Attribs.BindCount || SamInfo.Attribs.BindCount == 1); + } + } - for(Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd) - { - auto BindPoint = SamInfo.Attribs.BindPoint + ArrInd; - // Source sampler in the static resource cache is in the root table at index 3 - // (D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = 3), at offset BindPoint - const auto& SrcSampler = SrcCache.GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); - if( !SrcSampler.pObject ) - LOG_ERROR_MESSAGE( "No sampler assigned to static shader variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"." ); - auto &DstSampler = DstCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + auto SamplerCount = DstLayout.GetSamplerCount(SHADER_VARIABLE_TYPE_STATIC); + VERIFY(GetSamplerCount(SHADER_VARIABLE_TYPE_STATIC) == SamplerCount, "Number of static-type samplers in the source cache (", GetSamplerCount(SHADER_VARIABLE_TYPE_STATIC), ") is not consistent with the number of static-type samplers in destination cache (", SamplerCount, ")" ); + for(Uint32 s=0; s < SamplerCount; ++s) + { + const auto& SamInfo = DstLayout.GetSampler(SHADER_VARIABLE_TYPE_STATIC, s); + for(Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd) + { + auto BindPoint = SamInfo.Attribs.BindPoint + ArrInd; + // Source sampler in the static resource cache is in the root table at index 3 + // (D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER = 3), at offset BindPoint + const auto& SrcSampler = SrcCache.GetRootTable(D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER).GetResource(BindPoint, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); + if( !SrcSampler.pObject ) + LOG_ERROR_MESSAGE( "No sampler assigned to static shader variable \"", SamInfo.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"." ); + auto &DstSampler = DstCache.GetRootTable(SamInfo.RootIndex).GetResource(SamInfo.OffsetFromTableStart + ArrInd, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, m_pResources->GetShaderType()); - if(DstSampler.pObject != SrcSampler.pObject) - { - VERIFY(DstSampler.pObject == nullptr, "Static sampler resource has already been initialized, and the resource to be assigned from the shader does not match previously assigned resource"); + if(DstSampler.pObject != SrcSampler.pObject) + { + VERIFY(DstSampler.pObject == nullptr, "Static-type sampler has already been initialized, and the sampler to be assigned from the shader does not match previously assigned resource"); - DstSampler.pObject = SrcSampler.pObject; - DstSampler.Type = SrcSampler.Type; - DstSampler.CPUDescriptorHandle = SrcSampler.CPUDescriptorHandle; + DstSampler.pObject = SrcSampler.pObject; + DstSampler.Type = SrcSampler.Type; + DstSampler.CPUDescriptorHandle = SrcSampler.CPUDescriptorHandle; - auto ShdrVisibleSamplerHeapCPUDescriptorHandle = DstCache.GetShaderVisibleTableCPUDescriptorHandle(SamInfo.RootIndex, SamInfo.OffsetFromTableStart + ArrInd); - VERIFY_EXPR(ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr != 0); - if (ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr != 0) - { - m_pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleSamplerHeapCPUDescriptorHandle, SrcSampler.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); - } - } - else + auto ShdrVisibleSamplerHeapCPUDescriptorHandle = DstCache.GetShaderVisibleTableCPUDescriptorHandle(SamInfo.RootIndex, SamInfo.OffsetFromTableStart + ArrInd); + VERIFY_EXPR(ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr != 0); + if (ShdrVisibleSamplerHeapCPUDescriptorHandle.ptr != 0) { - VERIFY_EXPR(DstSampler.pObject == SrcSampler.pObject); - VERIFY_EXPR(DstSampler.Type == SrcSampler.Type); - VERIFY_EXPR(DstSampler.CPUDescriptorHandle.ptr == SrcSampler.CPUDescriptorHandle.ptr); + m_pd3d12Device->CopyDescriptorsSimple(1, ShdrVisibleSamplerHeapCPUDescriptorHandle, SrcSampler.CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER); } } + else + { + VERIFY_EXPR(DstSampler.pObject == SrcSampler.pObject); + VERIFY_EXPR(DstSampler.Type == SrcSampler.Type); + VERIFY_EXPR(DstSampler.CPUDescriptorHandle.ptr == SrcSampler.CPUDescriptorHandle.ptr); + } } } } @@ -803,7 +813,7 @@ void ShaderResourceLayoutD3D12::dvpVerifyBindings(ShaderResourceCacheD3D12& Reso CachedRes.CPUDescriptorHandle.ptr == 0 && !(CachedRes.Type==CachedResourceType::CBV && CachedRes.pObject.RawPtr()->GetDesc().Usage == USAGE_DYNAMIC) ) LOG_ERROR_MESSAGE( "No resource is bound to ", GetShaderVariableTypeLiteralName(res.Attribs.GetVariableType()), " variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\"" ); - if (res.Attribs.BindCount > 1 && res.IsValidSampler()) + if (res.Attribs.BindCount > 1 && res.ValidSamplerAssigned()) { // Verify that if single sampler is used for all texture array elements, all samplers set in the resource views are consistent const auto &SamInfo = const_cast(this)->GetAssignedSampler(res); @@ -813,7 +823,7 @@ void ShaderResourceLayoutD3D12::dvpVerifyBindings(ShaderResourceCacheD3D12& Reso if( auto *pTexView = CachedRes.pObject.RawPtr() ) { auto *pSampler = const_cast(pTexView)->GetSampler(); - if (pSampler != nullptr && CachedSampler.pObject != pSampler) + if (pSampler != nullptr && CachedSampler.pObject != nullptr && CachedSampler.pObject != pSampler) LOG_ERROR_MESSAGE( "All elements of texture array \"", res.Attribs.Name, "\" in shader \"", GetShaderName(), "\" share the same sampler. However, the sampler set in view for element ", ArrInd, " does not match bound sampler. This may cause incorrect behavior on GL platform." ); } } @@ -848,10 +858,10 @@ void ShaderResourceLayoutD3D12::dvpVerifyBindings(ShaderResourceCacheD3D12& Reso #endif } - if (res.IsValidSampler()) + if (res.ValidSamplerAssigned()) { VERIFY(res.GetResType() == CachedResourceType::TexSRV, "Sampler can only be assigned to a texture SRV" ); - const auto &SamInfo = const_cast(this)->GetAssignedSampler(res); + const auto& SamInfo = GetAssignedSampler(res); VERIFY(!SamInfo.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" ); VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid"); @@ -865,7 +875,7 @@ void ShaderResourceLayoutD3D12::dvpVerifyBindings(ShaderResourceCacheD3D12& Reso if( !CachedSampler.pObject || CachedSampler.CPUDescriptorHandle.ptr == 0 ) LOG_ERROR_MESSAGE("No sampler is assigned to texture variable \"", res.Attribs.GetPrintName(ArrInd), "\" in shader \"", GetShaderName(), "\""); - #ifdef _DEBUG +#ifdef _DEBUG { auto ShdrVisibleHeapCPUDescriptorHandle = ResourceCache.GetShaderVisibleTableCPUDescriptorHandle(SamInfo.RootIndex, SamInfo.OffsetFromTableStart + ArrInd); if (ResourceCache.DbgGetContentType() == ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources) @@ -884,7 +894,7 @@ void ShaderResourceLayoutD3D12::dvpVerifyBindings(ShaderResourceCacheD3D12& Reso UNEXPECTED("Unknown content type"); } } - #endif +#endif } } } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp index 0b9dda11..f9930073 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp @@ -35,9 +35,14 @@ size_t ShaderVariableManagerD3D12::GetRequiredMemorySize(const ShaderResourceLay { NumVariables = 0; Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) + for (SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) { - NumVariables += IsAllowedType(VarType, AllowedTypeBits) ? Layout.GetCbvSrvUavCount(VarType) : 0; + if (IsAllowedType(VarType, AllowedTypeBits)) + { + NumVariables += Layout.GetCbvSrvUavCount(VarType); + if (Layout.IsUsingSeparateSamplers()) + NumVariables += Layout.GetSamplerCount(VarType); + } } return NumVariables*sizeof(ShaderVariableD3D12Impl); @@ -67,18 +72,29 @@ void ShaderVariableManagerD3D12::Initialize(const ShaderResourceLayoutD3D12& Src m_pVariables = reinterpret_cast(pRawMem); Uint32 VarInd = 0; - for(SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) + for (SHADER_VARIABLE_TYPE VarType = SHADER_VARIABLE_TYPE_STATIC; VarType < SHADER_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType+1)) { if (!IsAllowedType(VarType, AllowedTypeBits)) continue; Uint32 NumResources = SrcLayout.GetCbvSrvUavCount(VarType); - for( Uint32 r=0; r < NumResources; ++r ) + for (Uint32 r=0; r < NumResources; ++r) { const auto& SrcRes = SrcLayout.GetSrvCbvUav(VarType, r); - ::new (m_pVariables + VarInd) ShaderVariableD3D12Impl(*this, SrcRes ); + ::new (m_pVariables + VarInd) ShaderVariableD3D12Impl(*this, SrcRes); ++VarInd; } + + if (SrcLayout.IsUsingSeparateSamplers()) + { + Uint32 NumSamplers = SrcLayout.GetSamplerCount(VarType); + for (Uint32 r=0; r < NumSamplers; ++r) + { + const auto& SrcSampler = SrcLayout.GetSampler(VarType, r); + ::new (m_pVariables + VarInd) ShaderVariableD3D12Impl(*this, SrcSampler); + ++VarInd; + } + } } VERIFY_EXPR(VarInd == m_NumVariables); } @@ -160,7 +176,7 @@ void ShaderVariableManagerD3D12::BindResources( IResourceMapping* pResourceMappi for(Uint32 ArrInd = 0; ArrInd < Res.Attribs.BindCount; ++ArrInd) { - if( Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS ) + if (Flags & BIND_SHADER_RESOURCES_RESET_BINDINGS) Res.BindResource(nullptr, ArrInd, *m_pResourceCache); if( (Flags & BIND_SHADER_RESOURCES_UPDATE_UNRESOLVED) && Res.IsBound(ArrInd, *m_pResourceCache) ) diff --git a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h index 1a256bce..bc6b19fe 100644 --- a/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h +++ b/Graphics/GraphicsEngineD3DBase/include/D3DShaderResourceLoader.h @@ -153,7 +153,7 @@ namespace Diligent { for (Uint32 s = 0; s < ShdrDesc.NumStaticSamplers; ++s) { - if (StrCmpSuff(Name.c_str(), ShdrDesc.StaticSamplers[s].SamplerOrTextureName, SamplerSuffix)) + if (StreqSuff(Name.c_str(), ShdrDesc.StaticSamplers[s].SamplerOrTextureName, SamplerSuffix)) { IsStaticSampler = true; break; @@ -163,7 +163,7 @@ namespace Diligent VarType = GetShaderVariableType(ShdrDesc.DefaultVariableType, ShdrDesc.VariableDesc, ShdrDesc.NumVariables, [&](const char* VarName) { - return StrCmpSuff(Name.c_str(), VarName, SamplerSuffix); + return StreqSuff(Name.c_str(), VarName, SamplerSuffix); }); } else diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h index 9c2278d4..6cc30b55 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.h @@ -388,8 +388,9 @@ public: } } - bool IsCompatibleWith(const ShaderResources& Resources) const; - bool IsUsingCombinedTextureSamplers() const {return m_UseCombinedTextureSamplers;} + bool IsCompatibleWith(const ShaderResources& Resources) const; + bool IsUsingCombinedTextureSamplers() const { return m_SamplerSuffix != nullptr; } + const char* GetCombinedSamplerSuffix() const { return m_SamplerSuffix; } size_t GetHash()const; @@ -415,7 +416,7 @@ protected: { VERIFY(n < NumResources, "Resource index (", n, ") is out of range. Resource array size: ", NumResources); VERIFY_EXPR(Offset + n < m_TotalResources); - return reinterpret_cast(m_MemoryBuffer.get())[Offset + n]; + return reinterpret_cast(m_MemoryBuffer.get())[Offset + n]; } D3DShaderResourceAttribs& GetCB (Uint32 n)noexcept{ return GetResAttribs(n, GetNumCBs(), 0); } @@ -441,7 +442,8 @@ private: // | CBs | TexSRVs | TexUAVs | BufSRVs | BufUAVs | Samplers | Resource Names | std::unique_ptr< void, STDDeleterRawMem > m_MemoryBuffer; - StringPool m_ResourceNames; + StringPool m_ResourceNames; + const char* m_SamplerSuffix = nullptr; // The suffix is put into the m_ResourceNames // Offsets in elements of D3DShaderResourceAttribs typedef Uint16 OffsetType; @@ -452,8 +454,6 @@ private: OffsetType m_SamplersOffset = 0; OffsetType m_TotalResources = 0; - bool m_UseCombinedTextureSamplers = false; - SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; }; @@ -467,14 +467,15 @@ void ShaderResources::Initialize(ID3DBlob* pShaderByteCode, const ShaderDesc& ShdrDesc, const Char* CombinedSamplerSuffix) { - m_UseCombinedTextureSamplers = CombinedSamplerSuffix != nullptr; - Uint32 CurrCB = 0, CurrTexSRV = 0, CurrTexUAV = 0, CurrBufSRV = 0, CurrBufUAV = 0, CurrSampler = 0; LoadD3DShaderResources( pShaderByteCode, [&](Uint32 NumCBs, Uint32 NumTexSRVs, Uint32 NumTexUAVs, Uint32 NumBufSRVs, Uint32 NumBufUAVs, Uint32 NumSamplers, size_t ResourceNamesPoolSize) { + if (CombinedSamplerSuffix != nullptr) + ResourceNamesPoolSize += strlen(CombinedSamplerSuffix)+1; + AllocateMemory(GetRawAllocator(), NumCBs, NumTexSRVs, NumTexUAVs, NumBufSRVs, NumBufUAVs, NumSamplers, ResourceNamesPoolSize); }, @@ -531,17 +532,19 @@ void ShaderResources::Initialize(ID3DBlob* pShaderByteCode, ShdrDesc, CombinedSamplerSuffix); -#ifdef DEVELOPMENT if (CombinedSamplerSuffix != nullptr) { + m_SamplerSuffix = m_ResourceNames.CopyString(CombinedSamplerSuffix); + +#ifdef DEVELOPMENT for (Uint32 n=0; n < GetNumSamplers(); ++n) { const auto& Sampler = GetSampler(n); if (!Sampler.ValidTexSRVAssigned()) LOG_ERROR_MESSAGE("Shader '", ShdrDesc.Name, "' uses combined texture samplers, but sampler '", Sampler.Name, "' is not assigned to any texture"); } - } #endif + } VERIFY_EXPR(m_ResourceNames.GetRemainingSize() == 0); VERIFY(CurrCB == GetNumCBs(), "Not all CBs are initialized which will cause a crash when ~D3DShaderResourceAttribs() is called"); diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 52fc96d9..f31da6a0 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -166,7 +166,7 @@ Uint32 ShaderResources::FindAssignedSamplerId(const D3DShaderResourceAttribs& Te for (Uint32 s = 0; s < NumSamplers; ++s) { const auto &Sampler = GetSampler(s); - if( StrCmpSuff(Sampler.Name, TexSRV.Name, SamplerSuffix) ) + if( StreqSuff(Sampler.Name, TexSRV.Name, SamplerSuffix) ) { VERIFY(Sampler.GetVariableType() == TexSRV.GetVariableType(), "Inconsistent texture and sampler variable types"); VERIFY(Sampler.BindCount == TexSRV.BindCount || Sampler.BindCount == 1, "Sampler assigned to array \"", TexSRV.Name, "\" is expected to be scalar or have the same dimension (",TexSRV.BindCount,"). Actual sampler array dimension : ", Sampler.BindCount); -- cgit v1.2.3