git.s-ol.nu ~forks/DiligentCore / e854ec0
PipelineResourceSignatureD3D12Impl: updated immutable samplers handling plus resource binding refactoring assiduous 6 months ago
6 changed file(s) with 288 addition(s) and 279 deletion(s). Raw diff Collapse all Expand all
302302 Uint32 SigRootIndex = ResourceAttribs::InvalidSigRootIndex;
303303 Uint32 SigOffsetFromTableStart = ResourceAttribs::InvalidOffset;
304304
305 if (ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
306 {
307 // Use artifial root signature:
308 // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV (0)
309 // UAVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_UAV (1)
310 // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV (2)
311 // Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER (3)
312 SigRootIndex = d3d12DescriptorRangeType;
313 SigOffsetFromTableStart = StaticResCacheTblSizes[SigRootIndex];
314 StaticResCacheTblSizes[SigRootIndex] += ResDesc.ArraySize;
315 }
316
317305 auto d3d12RootParamType = static_cast<D3D12_ROOT_PARAMETER_TYPE>(D3D12_ROOT_PARAMETER_TYPE_UAV + 1);
318306 // Do not allocate resource slot for immutable samplers that are also defined as resource
319307 if (!(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER && SrcImmutableSamplerInd >= 0))
320308 {
309 if (ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC)
310 {
311 // Use artifial root signature:
312 // SRVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_SRV (0)
313 // UAVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_UAV (1)
314 // CBVs at root index D3D12_DESCRIPTOR_RANGE_TYPE_CBV (2)
315 // Samplers at root index D3D12_DESCRIPTOR_RANGE_TYPE_SAMPLER (3)
316 SigRootIndex = d3d12DescriptorRangeType;
317 SigOffsetFromTableStart = StaticResCacheTblSizes[SigRootIndex];
318 StaticResCacheTblSizes[SigRootIndex] += ResDesc.ArraySize;
319 }
320
321321 if (IsRTSizedArray)
322322 {
323323 // All run-time sized arrays are allocated in separate spaces.
542542 VERIFY_EXPR(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
543543
544544 if (IsSampler && Attr.IsImmutableSamplerAssigned())
545 {
546 // Immutable samplers should not be assigned cache space
547 VERIFY_EXPR(Attr.RootIndex(CacheContentType::Signature) == ResourceAttribs::InvalidSigRootIndex);
548 VERIFY_EXPR(Attr.RootIndex(CacheContentType::SRB) == ResourceAttribs::InvalidSRBRootIndex);
549 VERIFY_EXPR(Attr.SigOffsetFromTableStart == ResourceAttribs::InvalidOffset);
550 VERIFY_EXPR(Attr.SRBOffsetFromTableStart == ResourceAttribs::InvalidOffset);
545551 continue;
552 }
546553
547554 const auto HeapType = IsSampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER : D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
548555 const auto DstRootIndex = Attr.RootIndex(DstCacheType);
594601 VERIFY_EXPR(CacheTbl.IsRootView());
595602 const auto& BaseRootIndex = CommitAttribs.BaseRootIndex;
596603
604 VERIFY_EXPR(CacheTbl.GetSize() == 1);
597605 const auto& Res = CacheTbl.GetResource(0);
598606 if (Res.IsNull())
599607 {
688696 "] in EngineD3D12CreateInfo or optimizing dynamic resource utilization by using static "
689697 "or mutable shader resource variables instead.");
690698
691 // Copy all all dynamic descriptors from the CPU-only cache allocation
692 auto& SrcDynamicAllocation = ResourceCache.GetDescriptorAllocation(d3d12HeapType, ROOT_PARAMETER_GROUP_DYNAMIC);
699 // Copy all dynamic descriptors from the CPU-only cache allocation
700 const auto& SrcDynamicAllocation = ResourceCache.GetDescriptorAllocation(d3d12HeapType, ROOT_PARAMETER_GROUP_DYNAMIC);
693701 VERIFY_EXPR(SrcDynamicAllocation.GetNumHandles() == NumDynamicDescriptors);
694702 pd3d12Device->CopyDescriptorsSimple(NumDynamicDescriptors, pAllocation->GetCpuHandle(), SrcDynamicAllocation.GetCpuHandle(), d3d12HeapType);
695703 }
696704 }
697705
698 auto* pSrvCbvUavDynamicAllocation = pDynamicDescriptorAllocations[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV];
699 auto* pSamplerDynamicAllocation = pDynamicDescriptorAllocations[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER];
706 auto* const pSrvCbvUavDynamicAllocation = pDynamicDescriptorAllocations[D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV];
707 auto* const pSamplerDynamicAllocation = pDynamicDescriptorAllocations[D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER];
700708
701709 CommandContext::ShaderDescriptorHeaps Heaps{
702710 ResourceCache.GetDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, ROOT_PARAMETER_GROUP_STATIC_MUTABLE),
838846 namespace
839847 {
840848
841 struct BindResourceHelper
842 {
843 const ShaderResourceCacheD3D12::Resource& DstRes;
844 const PipelineResourceDesc& ResDesc;
845 const PipelineResourceSignatureD3D12Impl::ResourceAttribs& Attribs;
846 const Uint32 RootIndex;
847 const Uint32 ArrayIndex;
848 const Uint32 OffsetFromTableStart;
849 D3D12_CPU_DESCRIPTOR_HANDLE DstTableCPUDescriptorHandle;
850 PipelineResourceSignatureD3D12Impl const& Signature;
851 ShaderResourceCacheD3D12& ResourceCache;
852
853 void BindResource(IDeviceObject* pObj) const;
849 class BindResourceHelper
850 {
851 public:
852 BindResourceHelper(const PipelineResourceSignatureD3D12Impl& Signature,
853 ShaderResourceCacheD3D12& ResourceCache,
854 Uint32 ResIndex,
855 Uint32 ArrayIndex);
856
857 void operator()(IDeviceObject* pObj) const;
854858
855859 private:
856860 void CacheCB(IDeviceObject* pBuffer) const;
857861 void CacheSampler(IDeviceObject* pBuffer) const;
858862 void CacheAccelStruct(IDeviceObject* pBuffer) const;
859
860 template <typename TResourceViewType, ///< ResType of the view (ITextureViewD3D12 or IBufferViewD3D12)
861 typename TViewTypeEnum, ///< ResType of the expected view type enum (TEXTURE_VIEW_TYPE or BUFFER_VIEW_TYPE)
862 typename TBindSamplerProcType> ///< ResType of the procedure to set sampler
863 void CacheResourceView(IDeviceObject* pBufferView,
864 TViewTypeEnum dbgExpectedViewType,
865 TBindSamplerProcType BindSamplerProc) const;
866
867 ID3D12Device* GetD3D12Device() const { return Signature.GetDevice()->GetD3D12Device(); }
863 void BindCombinedSampler(TextureViewD3D12Impl* pTexView) const;
864 void BindCombinedSampler(BufferViewD3D12Impl* pTexView) const {}
865
866 template <typename TResourceViewType, ///< The type of the view (TextureViewD3D12Impl or BufferViewD3D12Impl)
867 typename TViewTypeEnum ///< The type of the expected view type enum (TEXTURE_VIEW_TYPE or BUFFER_VIEW_TYPE)
868 >
869 void CacheResourceView(IDeviceObject* pBufferView,
870 TViewTypeEnum dbgExpectedViewType) const;
871
872 ID3D12Device* GetD3D12Device() const { return m_Signature.GetDevice()->GetD3D12Device(); }
873
874 void SetResource(D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle, RefCntAutoPtr<IDeviceObject>&& pObject) const
875 {
876 if (m_DstTableCPUDescriptorHandle.ptr != 0)
877 {
878 VERIFY(CPUDescriptorHandle.ptr != 0, "CPU descriptor handle must not be null for resources allocated in descriptor tables");
879 DEV_CHECK_ERR(m_ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || m_DstRes.pObject == nullptr, "Static and mutable resource descriptors should only be copied once");
880 const auto d3d12HeapType = m_ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER ?
881 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER :
882 D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
883 GetD3D12Device()->CopyDescriptorsSimple(1, m_DstTableCPUDescriptorHandle, CPUDescriptorHandle, d3d12HeapType);
884 }
885
886 m_ResourceCache.SetResource(m_RootIndex, m_OffsetFromTableStart, m_ResDesc.ResourceType, CPUDescriptorHandle, std::move(pObject));
887 }
888
889 private:
890 using ResourceAttribs = PipelineResourceSignatureD3D12Impl::ResourceAttribs;
891 using ContentType = PipelineResourceSignatureD3D12Impl::CacheContentType;
892
893 const PipelineResourceSignatureD3D12Impl& m_Signature;
894 ShaderResourceCacheD3D12& m_ResourceCache;
895
896 const PipelineResourceDesc& m_ResDesc;
897 const ResourceAttribs& m_Attribs; // Must go before m_RootIndex, m_OffsetFromTableStart
898
899 const ContentType m_CacheType; // Must go before m_RootIndex, m_OffsetFromTableStart
900 const Uint32 m_RootIndex; // Must go before m_DstRes
901 const Uint32 m_ArrayIndex;
902 const Uint32 m_OffsetFromTableStart; // Must go before m_DstRes
903
904 const ShaderResourceCacheD3D12::Resource& m_DstRes;
905
906 D3D12_CPU_DESCRIPTOR_HANDLE m_DstTableCPUDescriptorHandle{};
868907 };
869908
909 BindResourceHelper::BindResourceHelper(const PipelineResourceSignatureD3D12Impl& Signature,
910 ShaderResourceCacheD3D12& ResourceCache,
911 Uint32 ResIndex,
912 Uint32 ArrayIndex) :
913 // clang-format off
914 m_Signature {Signature},
915 m_ResourceCache {ResourceCache},
916 m_ResDesc {Signature.GetResourceDesc(ResIndex)},
917 m_Attribs {Signature.GetResourceAttribs(ResIndex)},
918 m_CacheType {ResourceCache.GetContentType()},
919 m_RootIndex {m_Attribs.RootIndex(m_CacheType)},
920 m_ArrayIndex {ArrayIndex},
921 m_OffsetFromTableStart{m_Attribs.OffsetFromTableStart(m_CacheType) + ArrayIndex},
922 m_DstRes {const_cast<const ShaderResourceCacheD3D12&>(ResourceCache).GetRootTable(m_RootIndex).GetResource(m_OffsetFromTableStart)}
923 // clang-format on
924 {
925 VERIFY(ArrayIndex < m_ResDesc.ArraySize, "Array index is out of range");
926
927 if (m_CacheType != ShaderResourceCacheD3D12::CacheContentType::Signature && !m_Attribs.IsRootView())
928 {
929 const auto IsSampler = (m_ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
930 const auto RootParamGroup = VariableTypeToRootParameterGroup(m_ResDesc.VarType);
931 // Static/mutable resources are allocated in GPU-visible descriptor heap, while dynamic resources - in CPU-only heap.
932 m_DstTableCPUDescriptorHandle =
933 ResourceCache.GetDescriptorTableHandle<D3D12_CPU_DESCRIPTOR_HANDLE>(
934 IsSampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER : D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
935 RootParamGroup, m_RootIndex, m_OffsetFromTableStart);
936 }
937
938 #ifdef DILIGENT_DEBUG
939 if (m_CacheType == ContentType::Signature)
940 {
941 VERIFY(m_DstTableCPUDescriptorHandle.ptr == 0, "Static shader resource cache should never be assigned descriptor space.");
942 }
943 else if (m_CacheType == ContentType::SRB)
944 {
945 if (m_Attribs.GetD3D12RootParamType() == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
946 {
947 VERIFY(m_DstTableCPUDescriptorHandle.ptr != 0, "Shader resources allocated in descriptor tables must be assigned descriptor space.");
948 }
949 else
950 {
951 VERIFY_EXPR(m_Attribs.IsRootView());
952 VERIFY((m_ResDesc.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER ||
953 m_ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV ||
954 m_ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV),
955 "Only constant buffers and dynamic buffer views can be allocated as root views");
956 VERIFY(m_DstTableCPUDescriptorHandle.ptr == 0, "Resources allocated as root views should never be assigned descriptor space.");
957 }
958 }
959 else
960 {
961 UNEXPECTED("Unknown content type");
962 }
963 #endif
964 }
870965
871966 void BindResourceHelper::CacheCB(IDeviceObject* pBuffer) const
872967 {
874969 // resource mapping can be of wrong type
875970 RefCntAutoPtr<BufferD3D12Impl> pBuffD3D12{pBuffer, IID_BufferD3D12};
876971 #ifdef DILIGENT_DEVELOPMENT
877 VerifyConstantBufferBinding(ResDesc.Name, ResDesc.ArraySize, ResDesc.VarType, ResDesc.Flags, ArrayIndex,
878 pBuffer, pBuffD3D12.RawPtr(), DstRes.pObject.RawPtr());
879 if (ResDesc.ArraySize != 1 && pBuffD3D12 && pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC && pBuffD3D12->GetD3D12Resource() == nullptr)
880 {
881 LOG_ERROR_MESSAGE("Attempting to bind dynamic buffer '", pBuffD3D12->GetDesc().Name, "' that doesn't have backing d3d12 resource to array variable '", ResDesc.Name,
882 "[", ResDesc.ArraySize, "]', which is currently not supported in Direct3D12 backend. Either use non-array variable, or bind non-dynamic buffer.");
972 VerifyConstantBufferBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ResDesc.Flags, m_ArrayIndex,
973 pBuffer, pBuffD3D12.RawPtr(), m_DstRes.pObject.RawPtr());
974 if (m_ResDesc.ArraySize != 1 && pBuffD3D12 && pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC && pBuffD3D12->GetD3D12Resource() == nullptr)
975 {
976 LOG_ERROR_MESSAGE("Attempting to bind dynamic buffer '", pBuffD3D12->GetDesc().Name, "' that doesn't have backing d3d12 resource to array variable '", m_ResDesc.Name,
977 "[", m_ResDesc.ArraySize, "]', which is currently not supported in Direct3D12 backend. Either use non-array variable, or bind non-dynamic buffer.");
883978 }
884979 #endif
885980 if (pBuffD3D12)
886981 {
887 if (ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr)
982 if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr)
888983 {
889984 // Do not update resource if one is already bound unless it is dynamic. This may be
890985 // dangerous as CopyDescriptorsSimple() may interfere with GPU reading the same descriptor.
892987 }
893988
894989 const auto CPUDescriptorHandle = pBuffD3D12->GetCBVHandle();
895 VERIFY(CPUDescriptorHandle.ptr != 0 || pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC, "No relevant CBV CPU descriptor handle");
896
897 if (DstTableCPUDescriptorHandle.ptr != 0)
898 {
899 VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr,
900 "Static and mutable resource descriptors must be copied only once");
901 VERIFY_EXPR(CPUDescriptorHandle.ptr != 0);
902
903 GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
904 }
905
906 ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pBuffD3D12));
990 VERIFY(CPUDescriptorHandle.ptr != 0 || pBuffD3D12->GetDesc().Usage == USAGE_DYNAMIC,
991 "Only dynamic constant buffers may have null CPU descriptor");
992
993 SetResource(CPUDescriptorHandle, std::move(pBuffD3D12));
907994 }
908995 }
909996
9131000 RefCntAutoPtr<ISamplerD3D12> pSamplerD3D12{pSampler, IID_SamplerD3D12};
9141001 if (pSamplerD3D12)
9151002 {
916 if (ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr)
917 {
918 if (DstRes.pObject != pSampler)
919 {
920 auto VarTypeStr = GetShaderVariableTypeLiteralName(ResDesc.VarType);
921 LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetShaderResourcePrintName(ResDesc, ArrayIndex),
1003 if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr)
1004 {
1005 if (m_DstRes.pObject != pSampler)
1006 {
1007 auto VarTypeStr = GetShaderVariableTypeLiteralName(m_ResDesc.VarType);
1008 LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex),
9221009 "'. Attempting to bind another sampler is an error and will be ignored. ",
9231010 "Use another shader resource binding instance or label the variable as dynamic.");
9241011 }
9291016 }
9301017
9311018 const auto CPUDescriptorHandle = pSamplerD3D12->GetCPUDescriptorHandle();
932 VERIFY(CPUDescriptorHandle.ptr != 0, "No relevant D3D12 sampler descriptor handle");
933
934 if (DstTableCPUDescriptorHandle.ptr != 0)
935 {
936 VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once");
937 GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER);
938 }
939 else
940 {
941 VERIFY(ResourceCache.GetContentType() == ShaderResourceCacheD3D12::CacheContentType::Signature,
942 "Samplers must always be allocated in root tables and thus assigned descriptor");
943 }
944
945 ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pSamplerD3D12));
1019 VERIFY(CPUDescriptorHandle.ptr != 0, "Samplers must always have valid CPU descriptors");
1020 VERIFY(m_CacheType == ShaderResourceCacheD3D12::CacheContentType::Signature || m_DstTableCPUDescriptorHandle.ptr != 0,
1021 "Samplers in SRB cache must always be allocated in root tables and thus assigned descriptor in the table");
1022
1023 SetResource(CPUDescriptorHandle, std::move(pSamplerD3D12));
9461024 }
9471025 else
9481026 {
9491027 LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '",
950 GetShaderResourcePrintName(ResDesc, ArrayIndex), "'. Incorect object type: sampler is expected.");
1028 GetShaderResourcePrintName(m_ResDesc, m_ArrayIndex), "'. Incorect object type: sampler is expected.");
9511029 }
9521030 }
9531031
9571035 RefCntAutoPtr<ITopLevelASD3D12> pTLASD3D12{pTLAS, IID_TopLevelASD3D12};
9581036 if (pTLASD3D12)
9591037 {
960 if (ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr)
1038 if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr)
9611039 {
9621040 // Do not update resource if one is already bound unless it is dynamic. This may be
9631041 // dangerous as CopyDescriptorsSimple() may interfere with GPU reading the same descriptor.
9641042 return;
9651043 }
9661044
967
9681045 const auto CPUDescriptorHandle = pTLASD3D12->GetCPUDescriptorHandle();
969 VERIFY(CPUDescriptorHandle.ptr != 0, "No relevant D3D12 resource");
970 if (DstTableCPUDescriptorHandle.ptr != 0)
971 {
972 VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr, "Static and mutable resource descriptors must be copied only once");
973 GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
974 }
975 else
976 {
977 VERIFY(ResourceCache.GetContentType() == ShaderResourceCacheD3D12::CacheContentType::Signature,
978 "Acceleration structures are always allocated in root tables and thus must have a descriptor");
979 }
980
981 ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pTLASD3D12));
1046 VERIFY(CPUDescriptorHandle.ptr != 0, "Acceleration structures must always have valid CPU descriptor handles");
1047 VERIFY(m_CacheType == ShaderResourceCacheD3D12::CacheContentType::Signature || m_DstTableCPUDescriptorHandle.ptr != 0,
1048 "Acceleration structures in SRB cache are always allocated in root tables and thus must have a descriptor");
1049
1050 SetResource(CPUDescriptorHandle, std::move(pTLASD3D12));
9821051 }
9831052 }
9841053
9921061 {
9931062 static const INTERFACE_ID& IID;
9941063
995 static bool VerifyView(TextureViewD3D12Impl* pViewD3D12, const PipelineResourceDesc& ResDesc)
1064 static bool VerifyView(const TextureViewD3D12Impl* pViewD3D12, const PipelineResourceDesc& ResDesc)
9961065 {
9971066 return true;
9981067 }
10041073 {
10051074 static const INTERFACE_ID& IID;
10061075
1007 static bool VerifyView(BufferViewD3D12Impl* pViewD3D12, const PipelineResourceDesc& ResDesc)
1076 static bool VerifyView(const BufferViewD3D12Impl* pViewD3D12, const PipelineResourceDesc& ResDesc)
10081077 {
10091078 if (pViewD3D12 != nullptr)
10101079 {
1011 auto* pBuffer = pViewD3D12->GetBuffer<BufferD3D12Impl>();
1080 const auto* const pBuffer = pViewD3D12->GetBuffer<BufferD3D12Impl>();
10121081 if (ResDesc.ArraySize != 1 && pBuffer->GetDesc().Usage == USAGE_DYNAMIC && pBuffer->GetD3D12Resource() == nullptr)
10131082 {
10141083 LOG_ERROR_MESSAGE("Attempting to bind dynamic buffer '", pBuffer->GetDesc().Name, "' that doesn't have backing d3d12 resource to array variable '", ResDesc.Name,
10181087 }
10191088
10201089 return true;
1021 //return VerifyBufferViewModeD3D(pViewD3D12, Attribs);
10221090 }
10231091 };
10241092 const INTERFACE_ID& ResourceViewTraits<BufferViewD3D12Impl>::IID = IID_BufferViewD3D12;
10251093
10261094
1027 template <typename TResourceViewType, ///< ResType of the view (ITextureViewD3D12 or IBufferViewD3D12)
1028 typename TViewTypeEnum, ///< ResType of the expected view type enum (TEXTURE_VIEW_TYPE or BUFFER_VIEW_TYPE)
1029 typename TBindSamplerProcType> ///< ResType of the procedure to set sampler
1030 void BindResourceHelper::CacheResourceView(IDeviceObject* pView,
1031 TViewTypeEnum dbgExpectedViewType,
1032 TBindSamplerProcType BindSamplerProc) const
1095 template <typename TResourceViewType,
1096 typename TViewTypeEnum>
1097 void BindResourceHelper::CacheResourceView(IDeviceObject* pView,
1098 TViewTypeEnum dbgExpectedViewType) const
10331099 {
10341100 // We cannot use ValidatedCast<> here as the resource retrieved from the
10351101 // resource mapping can be of wrong type
10361102 RefCntAutoPtr<TResourceViewType> pViewD3D12{pView, ResourceViewTraits<TResourceViewType>::IID};
10371103 #ifdef DILIGENT_DEVELOPMENT
1038 VerifyResourceViewBinding(ResDesc.Name, ResDesc.ArraySize, ResDesc.VarType, ArrayIndex,
1104 VerifyResourceViewBinding(m_ResDesc.Name, m_ResDesc.ArraySize, m_ResDesc.VarType, m_ArrayIndex,
10391105 pView, pViewD3D12.RawPtr(),
10401106 {dbgExpectedViewType}, RESOURCE_DIM_UNDEFINED,
10411107 false, // IsMultisample
1042 DstRes.pObject.RawPtr());
1043 ResourceViewTraits<TResourceViewType>::VerifyView(pViewD3D12, ResDesc);
1108 m_DstRes.pObject.RawPtr());
1109 ResourceViewTraits<TResourceViewType>::VerifyView(pViewD3D12, m_ResDesc);
10441110 #endif
10451111 if (pViewD3D12)
10461112 {
1047 if (ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && DstRes.pObject != nullptr)
1113 if (m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && m_DstRes.pObject != nullptr)
10481114 {
10491115 // Do not update resource if one is already bound unless it is dynamic. This may be
10501116 // dangerous as CopyDescriptorsSimple() may interfere with GPU reading the same descriptor.
10521118 }
10531119
10541120 const auto CPUDescriptorHandle = pViewD3D12->GetCPUDescriptorHandle();
1055 VERIFY(CPUDescriptorHandle.ptr != 0, "No relevant D3D12 view");
1056
1057 if (DstTableCPUDescriptorHandle.ptr != 0)
1058 {
1059 VERIFY(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC || DstRes.pObject == nullptr,
1060 "Static and mutable resource descriptors must be copied only once");
1061
1062 GetD3D12Device()->CopyDescriptorsSimple(1, DstTableCPUDescriptorHandle, CPUDescriptorHandle, D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
1063 }
1064
1065 BindSamplerProc(pViewD3D12);
1066
1067 ResourceCache.SetResource(RootIndex, OffsetFromTableStart, ResDesc.ResourceType, CPUDescriptorHandle, std::move(pViewD3D12));
1068 }
1069 }
1070
1071 void BindResourceHelper::BindResource(IDeviceObject* pObj) const
1072 {
1073 VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);
1074
1075 #ifdef DILIGENT_DEBUG
1076 using CacheContentType = PipelineResourceSignatureD3D12Impl::CacheContentType;
1077
1078 if (ResourceCache.GetContentType() == CacheContentType::Signature)
1079 {
1080 VERIFY(DstTableCPUDescriptorHandle.ptr == 0, "Static shader resources should never be assigned descriptor space.");
1081 }
1082 else if (ResourceCache.GetContentType() == CacheContentType::SRB)
1083 {
1084 if (Attribs.GetD3D12RootParamType() == D3D12_ROOT_PARAMETER_TYPE_DESCRIPTOR_TABLE)
1085 {
1086 VERIFY(DstTableCPUDescriptorHandle.ptr != 0, "Shader resources allocated in descriptor tables must be assigned descriptor space.");
1087 }
1088 else
1089 {
1090 VERIFY((ResDesc.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER ||
1091 ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV ||
1092 ResDesc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV),
1093 "Only constant buffers and dynamic buffers views can be allocated as root views");
1094 VERIFY(DstTableCPUDescriptorHandle.ptr == 0, "Resources allocated as root views should never be assigned descriptor space.");
1095 }
1096 }
1097 else
1098 {
1099 UNEXPECTED("Unknown content type");
1100 }
1101 #endif
1102
1121 // Note that for dynamic structured buffers we still create SRV even though we don't really use it.
1122 VERIFY(CPUDescriptorHandle.ptr != 0, "Texture/buffer views should always have valid CPU descriptor handles");
1123
1124 BindCombinedSampler(pViewD3D12);
1125
1126 SetResource(CPUDescriptorHandle, std::move(pViewD3D12));
1127 }
1128 }
1129
1130
1131 void BindResourceHelper::BindCombinedSampler(TextureViewD3D12Impl* pTexView) const
1132 {
1133 if (m_ResDesc.ResourceType != SHADER_RESOURCE_TYPE_TEXTURE_SRV)
1134 {
1135 VERIFY(!m_Attribs.IsCombinedWithSampler(), "Only texture SRVs can be combined with sampler");
1136 return;
1137 }
1138
1139 if (!m_Attribs.IsCombinedWithSampler())
1140 return;
1141
1142 const auto& SamplerResDesc = m_Signature.GetResourceDesc(m_Attribs.SamplerInd);
1143 const auto& SamplerAttribs = m_Signature.GetResourceAttribs(m_Attribs.SamplerInd);
1144 VERIFY_EXPR(SamplerResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
1145
1146 if (SamplerAttribs.IsImmutableSamplerAssigned())
1147 {
1148 // Immutable samplers should not be assigned cache space
1149 VERIFY_EXPR(SamplerAttribs.RootIndex(ContentType::Signature) == ResourceAttribs::InvalidSigRootIndex);
1150 VERIFY_EXPR(SamplerAttribs.RootIndex(ContentType::SRB) == ResourceAttribs::InvalidSRBRootIndex);
1151 VERIFY_EXPR(SamplerAttribs.SigOffsetFromTableStart == ResourceAttribs::InvalidOffset);
1152 VERIFY_EXPR(SamplerAttribs.SRBOffsetFromTableStart == ResourceAttribs::InvalidOffset);
1153 return;
1154 }
1155
1156 auto* const pSampler = pTexView->GetSampler();
1157 if (pSampler == nullptr)
1158 {
1159 LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", SamplerResDesc.Name, ". Sampler is not set in the texture view '", pTexView->GetDesc().Name, '\'');
1160 return;
1161 }
1162
1163 VERIFY_EXPR(m_ResDesc.ArraySize == SamplerResDesc.ArraySize || SamplerResDesc.ArraySize == 1);
1164 const auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? m_ArrayIndex : 0;
1165
1166 BindResourceHelper BindSampler{m_Signature, m_ResourceCache, m_Attribs.SamplerInd, SamplerArrInd};
1167 BindSampler(pSampler);
1168 }
1169
1170 void BindResourceHelper::operator()(IDeviceObject* pObj) const
1171 {
11031172 if (pObj)
11041173 {
11051174 static_assert(SHADER_RESOURCE_TYPE_LAST == 8, "Please update this function to handle the new resource type");
1106 switch (ResDesc.ResourceType)
1175 switch (m_ResDesc.ResourceType)
11071176 {
11081177 case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER:
11091178 CacheCB(pObj);
11101179 break;
11111180
11121181 case SHADER_RESOURCE_TYPE_TEXTURE_SRV:
1113 CacheResourceView<TextureViewD3D12Impl>(
1114 pObj, TEXTURE_VIEW_SHADER_RESOURCE,
1115 [&](TextureViewD3D12Impl* pTexView) //
1116 {
1117 if (Attribs.IsCombinedWithSampler())
1118 {
1119 auto& SamplerResDesc = Signature.GetResourceDesc(Attribs.SamplerInd);
1120 auto& SamplerAttribs = Signature.GetResourceAttribs(Attribs.SamplerInd);
1121 VERIFY_EXPR(SamplerResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
1122
1123 if (!SamplerAttribs.IsImmutableSamplerAssigned())
1124 {
1125 auto* pSampler = pTexView->GetSampler();
1126 if (pSampler)
1127 {
1128 VERIFY_EXPR(ResDesc.ArraySize == SamplerResDesc.ArraySize || SamplerResDesc.ArraySize == 1);
1129 const auto CacheType = ResourceCache.GetContentType();
1130 const auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? ArrayIndex : 0;
1131 const auto SamRootIndex = SamplerAttribs.RootIndex(CacheType);
1132 const auto SamOffsetFromTableStart = SamplerAttribs.OffsetFromTableStart(CacheType) + SamplerArrInd;
1133 auto& SampleDstRes = const_cast<const ShaderResourceCacheD3D12&>(ResourceCache).GetRootTable(SamRootIndex).GetResource(SamOffsetFromTableStart);
1134
1135 D3D12_CPU_DESCRIPTOR_HANDLE CPUDescriptorHandle{};
1136 if (CacheType != ShaderResourceCacheD3D12::CacheContentType::Signature)
1137 {
1138 const auto RootParamGroup = VariableTypeToRootParameterGroup(SamplerResDesc.VarType);
1139 // Static/mutable resources are allocated in GPU-visible descriptor heap, while dynamic resources - in CPU-only heap.
1140 CPUDescriptorHandle = ResourceCache.GetDescriptorTableHandle<D3D12_CPU_DESCRIPTOR_HANDLE>(
1141 D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, RootParamGroup, RootIndex, OffsetFromTableStart);
1142 }
1143
1144 BindResourceHelper SeparateSampler{
1145 SampleDstRes,
1146 SamplerResDesc,
1147 SamplerAttribs,
1148 SamRootIndex,
1149 SamplerArrInd,
1150 SamOffsetFromTableStart,
1151 CPUDescriptorHandle,
1152 Signature,
1153 ResourceCache};
1154 SeparateSampler.BindResource(pSampler);
1155 }
1156 else
1157 {
1158 LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", SamplerResDesc.Name, ". Sampler is not set in the texture view '", pTexView->GetDesc().Name, '\'');
1159 }
1160 }
1161 }
1162 });
1182 CacheResourceView<TextureViewD3D12Impl>(pObj, TEXTURE_VIEW_SHADER_RESOURCE);
11631183 break;
11641184
11651185 case SHADER_RESOURCE_TYPE_TEXTURE_UAV:
1166 CacheResourceView<TextureViewD3D12Impl>(pObj, TEXTURE_VIEW_UNORDERED_ACCESS, [](TextureViewD3D12Impl*) {});
1186 CacheResourceView<TextureViewD3D12Impl>(pObj, TEXTURE_VIEW_UNORDERED_ACCESS);
11671187 break;
11681188
11691189 case SHADER_RESOURCE_TYPE_BUFFER_SRV:
1170 CacheResourceView<BufferViewD3D12Impl>(pObj, BUFFER_VIEW_SHADER_RESOURCE, [](BufferViewD3D12Impl*) {});
1190 CacheResourceView<BufferViewD3D12Impl>(pObj, BUFFER_VIEW_SHADER_RESOURCE);
11711191 break;
11721192
11731193 case SHADER_RESOURCE_TYPE_BUFFER_UAV:
1174 CacheResourceView<BufferViewD3D12Impl>(pObj, BUFFER_VIEW_UNORDERED_ACCESS, [](BufferViewD3D12Impl*) {});
1194 CacheResourceView<BufferViewD3D12Impl>(pObj, BUFFER_VIEW_UNORDERED_ACCESS);
11751195 break;
11761196
11771197 case SHADER_RESOURCE_TYPE_SAMPLER:
1178 //DEV_CHECK_ERR(Signature.IsUsingSeparateSamplers(), "Samplers should not be set directly when using combined texture samplers");
11791198 CacheSampler(pObj);
11801199 break;
11811200
11831202 CacheAccelStruct(pObj);
11841203 break;
11851204
1186 default: UNEXPECTED("Unknown resource type ", static_cast<Int32>(ResDesc.ResourceType));
1205 default: UNEXPECTED("Unknown resource type ", static_cast<Int32>(m_ResDesc.ResourceType));
11871206 }
11881207 }
11891208 else
11901209 {
1191 if (DstRes.pObject != nullptr && ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
1192 LOG_ERROR_MESSAGE("Shader variable '", ResDesc.Name, "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. ",
1210 if (m_DstRes.pObject != nullptr && m_ResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
1211 {
1212 LOG_ERROR_MESSAGE("Shader variable '", m_ResDesc.Name, "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. ",
11931213 "Use another shader resource binding instance or label the variable as dynamic if you need to bind another resource.");
1194
1195 ResourceCache.ResetResource(RootIndex, OffsetFromTableStart);
1196 if (Attribs.IsCombinedWithSampler())
1197 {
1198 auto& SamplerResDesc = Signature.GetResourceDesc(Attribs.SamplerInd);
1199 auto& SamplerAttribs = Signature.GetResourceAttribs(Attribs.SamplerInd);
1214 }
1215
1216 m_ResourceCache.ResetResource(m_RootIndex, m_OffsetFromTableStart);
1217 if (m_Attribs.IsCombinedWithSampler())
1218 {
1219 auto& SamplerResDesc = m_Signature.GetResourceDesc(m_Attribs.SamplerInd);
1220 auto& SamplerAttribs = m_Signature.GetResourceAttribs(m_Attribs.SamplerInd);
12001221 VERIFY_EXPR(SamplerResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
12011222
12021223 if (!SamplerAttribs.IsImmutableSamplerAssigned())
12031224 {
1204 const auto CacheType = ResourceCache.GetContentType();
1205 auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? ArrayIndex : 0;
1206 const auto SamRootIndex = SamplerAttribs.RootIndex(CacheType);
1207 const auto SamOffsetFromTableStart = SamplerAttribs.OffsetFromTableStart(CacheType) + SamplerArrInd;
1208 const auto& DstSam = const_cast<const ShaderResourceCacheD3D12&>(ResourceCache).GetRootTable(SamRootIndex).GetResource(SamOffsetFromTableStart);
1225 const auto SamplerArrInd = SamplerResDesc.ArraySize > 1 ? m_ArrayIndex : 0;
1226 const auto SamRootIndex = SamplerAttribs.RootIndex(m_CacheType);
1227 const auto SamOffsetFromTableStart = SamplerAttribs.OffsetFromTableStart(m_CacheType) + SamplerArrInd;
1228 const auto& DstSam = const_cast<const ShaderResourceCacheD3D12&>(m_ResourceCache).GetRootTable(SamRootIndex).GetResource(SamOffsetFromTableStart);
12091229
12101230 if (DstSam.pObject != nullptr && SamplerResDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC)
1231 {
12111232 LOG_ERROR_MESSAGE("Sampler variable '", SamplerResDesc.Name, "' is not dynamic but is being reset to null. This is an error and may cause unpredicted behavior. ",
12121233 "Use another shader resource binding instance or label the variable as dynamic if you need to bind another sampler.");
1213
1214 ResourceCache.ResetResource(SamRootIndex, SamOffsetFromTableStart);
1234 }
1235
1236 m_ResourceCache.ResetResource(SamRootIndex, SamOffsetFromTableStart);
12151237 }
12161238 }
12171239 }
12251247 Uint32 ResIndex,
12261248 ShaderResourceCacheD3D12& ResourceCache) const
12271249 {
1228 const auto& ResDesc = GetResourceDesc(ResIndex);
1229 const auto& Attribs = GetResourceAttribs(ResIndex);
1230 const bool IsSampler = (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER);
1231 const auto CacheType = ResourceCache.GetContentType();
1232 const auto RootIndex = Attribs.RootIndex(CacheType);
1233 const auto OffsetFromTableStart = Attribs.OffsetFromTableStart(CacheType) + ArrayIndex;
1234
1235 VERIFY_EXPR(ArrayIndex < ResDesc.ArraySize);
1236
1237 const auto& RootTable = const_cast<const ShaderResourceCacheD3D12&>(ResourceCache).GetRootTable(RootIndex);
1238 const auto& DstRes = RootTable.GetResource(OffsetFromTableStart);
1239
1240 D3D12_CPU_DESCRIPTOR_HANDLE DstTableCPUDescriptorHandle{};
1241 if (CacheType != ShaderResourceCacheD3D12::CacheContentType::Signature && !Attribs.IsRootView())
1242 {
1243 const auto RootParamGroup = VariableTypeToRootParameterGroup(ResDesc.VarType);
1244 // Static/mutable resources are allocated in GPU-visible descriptor heap, while dynamic resources - in CPU-only heap.
1245 DstTableCPUDescriptorHandle =
1246 ResourceCache.GetDescriptorTableHandle<D3D12_CPU_DESCRIPTOR_HANDLE>(
1247 IsSampler ? D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER : D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV,
1248 RootParamGroup, RootIndex, OffsetFromTableStart);
1249 }
1250
1251 BindResourceHelper Helper{
1252 DstRes,
1253 ResDesc,
1254 Attribs,
1255 RootIndex,
1256 ArrayIndex,
1257 OffsetFromTableStart,
1258 DstTableCPUDescriptorHandle,
1259 *this,
1260 ResourceCache};
1261
1262 Helper.BindResource(pObj);
1250 VERIFY(IsUsingSeparateSamplers() || GetResourceDesc(ResIndex).ResourceType != SHADER_RESOURCE_TYPE_SAMPLER,
1251 "Samplers should not be set directly when using combined texture samplers");
1252 BindResourceHelper BindResHelper{*this, ResourceCache, ResIndex, ArrayIndex};
1253 BindResHelper(pObj);
12631254 }
12641255
12651256 bool PipelineResourceSignatureD3D12Impl::IsBound(Uint32 ArrayIndex,
13031294 if ((ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER) && ResAttribs.IsImmutableSamplerAssigned())
13041295 return true;
13051296
1306 const auto CacheType = ResourceCache.GetContentType();
1297 const auto CacheType = ResourceCache.GetContentType();
1298 VERIFY(CacheType == CacheContentType::SRB, "Only SRB resource cache can be committed");
13071299 const auto RootIndex = ResAttribs.RootIndex(CacheType);
13081300 const auto OffsetFromTableStart = ResAttribs.OffsetFromTableStart(CacheType);
13091301 const auto& RootTable = ResourceCache.GetRootTable(RootIndex);
4949 {
5050 for (Uint32 group = 0; group < ROOT_PARAMETER_GROUP_COUNT; ++group)
5151 {
52 auto GroupType = static_cast<ROOT_PARAMETER_GROUP>(group);
53
54 auto TotalTableResources = RootParams.GetParameterGroupSize(d3d12HeapType, GroupType);
55 MemReqs.TotalResources += TotalTableResources;
56 if (TotalTableResources != 0)
57 {
52 const auto ParamGroupSize = RootParams.GetParameterGroupSize(d3d12HeapType, static_cast<ROOT_PARAMETER_GROUP>(group));
53 if (ParamGroupSize != 0)
54 {
55 MemReqs.TotalResources += ParamGroupSize;
5856 // Every non-empty table from each group will need a descriptor table
5957 ++MemReqs.NumDescriptorAllocations;
6058 }
144142 new (&GetRootTable(t)) RootTable{TableSizes[t], TableSizes[t] > 0 ? &GetResource(ResIdx) : nullptr, false};
145143 ResIdx += TableSizes[t];
146144 }
145 VERIFY_EXPR(ResIdx == m_TotalResourceCount);
147146 }
148147
149148
5858
5959 if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER &&
6060 (UsingCombinedSamplers || Attr.IsImmutableSamplerAssigned()))
61 {
62 // Skip samplers combined with textures and immutable samplers
6163 continue;
64 }
6265
6366 Handler(r);
6467 }
201201 std::fill(UsedValues.begin(), UsedValues.end(), false);
202202 }
203203
204 size_t GetTextureCount() const { return Textures.size(); }
205
204206 private:
205207 std::vector<RefCntAutoPtr<ITexture>> Textures;
206208
13941394 TEXTURE_VIEW_SHADER_RESOURCE //
13951395 };
13961396
1397 RefCntAutoPtr<ISampler> pSampler;
1398 pDevice->CreateSampler(SamplerDesc{}, &pSampler);
1399 for (Uint32 i = 0; i < RefTextures.GetTextureCount(); ++i)
1400 RefTextures.GetView(i)->SetSampler(pSampler);
1401
13971402 ShaderMacroHelper Macros;
13981403
13991404 // Add macros that define reference colors
14511456 {SHADER_TYPE_VERTEX | SHADER_TYPE_PIXEL, "g_Tex2D_Mut", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE},
14521457 {SHADER_TYPE_VERTEX | SHADER_TYPE_PIXEL, "g_Tex2D_Dyn", SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}
14531458 };
1454
1455 const ImmutableSamplerDesc ImmutableSamplers[] =
1456 {
1457 ImmutableSamplerDesc{SHADER_TYPE_VERTEX | SHADER_TYPE_PIXEL, "g_Tex2D_Static", SamplerDesc{}},
1458 ImmutableSamplerDesc{SHADER_TYPE_VERTEX | SHADER_TYPE_PIXEL, "g_Tex2D_Mut", SamplerDesc{}},
1459 ImmutableSamplerDesc{SHADER_TYPE_VERTEX | SHADER_TYPE_PIXEL, "g_Tex2D_Dyn", SamplerDesc{}}
1460 };
14611459 // clang-format on
14621460
14631461 PipelineResourceLayoutDesc ResourceLayout;
1464 ResourceLayout.Variables = Vars;
1465 ResourceLayout.NumVariables = _countof(Vars);
1466 ResourceLayout.ImmutableSamplers = ImmutableSamplers;
1467 ResourceLayout.NumImmutableSamplers = _countof(ImmutableSamplers);
1462 ResourceLayout.Variables = Vars;
1463 ResourceLayout.NumVariables = _countof(Vars);
14681464
14691465 RefCntAutoPtr<IPipelineState> pPSO;
14701466 RefCntAutoPtr<IShaderResourceBinding> pSRB;
14781474
14791475 SET_STATIC_VAR(pPSO, SHADER_TYPE_PIXEL, "g_Tex2D_Static", Set, RefTextures.GetView(0));
14801476 SET_SRB_VAR(pSRB, SHADER_TYPE_VERTEX, "g_Tex2D_Mut", Set, RefTextures.GetView(1));
1477
1478 SET_SRB_VAR(pSRB, SHADER_TYPE_PIXEL, "g_Tex2D_Dyn", Set, RefTextures.GetView(0));
1479 SET_SRB_VAR(pSRB, SHADER_TYPE_PIXEL, "g_Tex2D_Dyn", Set, nullptr); // Test resetting combined texture to null
14811480 SET_SRB_VAR(pSRB, SHADER_TYPE_PIXEL, "g_Tex2D_Dyn", Set, RefTextures.GetView(2));
14821481
14831482 pPSO->InitializeStaticSRBResources(pSRB);
741741 UniformBuff_Dyn->GetResourceDesc(ResDesc);
742742 EXPECT_EQ(ResDesc.ArraySize, 1u);
743743 EXPECT_EQ(UniformBuff_Dyn, pSRB->GetVariableByName(SHADER_TYPE_VERTEX, ResDesc.Name));
744 UniformBuff_Dyn->Set(pUBs[1]);
745 UniformBuff_Dyn->Set(nullptr);
744746 UniformBuff_Dyn->Set(pUBs[0]);
745747 }
746748
773775 EXPECT_EQ(ResDesc.ArraySize, 1u);
774776 EXPECT_EQ(Buffer_Dyn, pSRB->GetVariableByName(SHADER_TYPE_VERTEX, ResDesc.Name));
775777 Buffer_Dyn->Set(pFormattedBuffSRV);
778 Buffer_Dyn->Set(nullptr);
779 Buffer_Dyn->Set(pFormattedBuffSRV);
776780 }
777781
778782 {
835839 tex2D_Dyn->GetResourceDesc(ResDesc);
836840 EXPECT_EQ(ResDesc.ArraySize, 1u);
837841 EXPECT_EQ(tex2D_Dyn, pSRB->GetVariableByName(SHADER_TYPE_PIXEL, ResDesc.Name));
842 tex2D_Dyn->Set(pRWTexSRVs[6]);
843 tex2D_Dyn->Set(nullptr);
838844 tex2D_Dyn->Set(pRWTexSRVs[7]);
839845 }
840846
876882 UniformBuff_Dyn->GetResourceDesc(ResDesc);
877883 EXPECT_EQ(ResDesc.ArraySize, 1u);
878884 EXPECT_EQ(UniformBuff_Dyn, pSRB->GetVariableByName(SHADER_TYPE_PIXEL, ResDesc.Name));
885 UniformBuff_Dyn->Set(pUBs[1]);
886 UniformBuff_Dyn->Set(nullptr);
879887 UniformBuff_Dyn->Set(pUBs[0]);
880888 }
881889
907915 Buffer_Dyn->GetResourceDesc(ResDesc);
908916 EXPECT_EQ(ResDesc.ArraySize, 1u);
909917 EXPECT_EQ(Buffer_Dyn, pSRB->GetVariableByName(SHADER_TYPE_PIXEL, ResDesc.Name));
918 Buffer_Dyn->Set(pFormattedBuffSRVs[2]);
919 Buffer_Dyn->Set(nullptr);
910920 Buffer_Dyn->Set(pFormattedBuffSRVs[3]);
911921 }
912922
938948 rwtex2D_Dyn->GetResourceDesc(ResDesc);
939949 EXPECT_EQ(ResDesc.ArraySize, 1u);
940950 EXPECT_EQ(rwtex2D_Dyn, pSRB->GetVariableByName(SHADER_TYPE_PIXEL, ResDesc.Name));
951 rwtex2D_Dyn->Set(pTexUAVs[2]);
952 rwtex2D_Dyn->Set(nullptr);
941953 rwtex2D_Dyn->Set(pTexUAVs[3]);
942954 }
943955
958970 rwBuff_Dyn->GetResourceDesc(ResDesc);
959971 EXPECT_EQ(ResDesc.ArraySize, 1u);
960972 EXPECT_EQ(rwBuff_Dyn, pSRB->GetVariableByName(SHADER_TYPE_PIXEL, ResDesc.Name));
973 rwBuff_Dyn->Set(pFormattedBuffUAV[1]);
974 rwBuff_Dyn->Set(nullptr);
961975 rwBuff_Dyn->Set(pFormattedBuffUAV[2]);
962976 }
963977