From 9411711453738341acc10dec8be88675fafd3155 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Wed, 10 Mar 2021 02:33:41 +0300 Subject: Direct3D11: added resource signature --- Graphics/GraphicsEngineD3D11/CMakeLists.txt | 7 +- .../include/BufferD3D11Impl.hpp | 6 +- .../include/BufferViewD3D11Impl.hpp | 6 +- .../include/DeviceContextD3D11Impl.hpp | 140 ++- .../include/EngineD3D11ImplTraits.hpp | 120 +++ .../GraphicsEngineD3D11/include/FenceD3D11Impl.hpp | 6 +- .../include/FramebufferD3D11Impl.hpp | 4 +- .../include/PipelineResourceAttribsD3D11.hpp | 115 +++ .../include/PipelineResourceSignatureD3D11Impl.hpp | 160 +++ .../include/PipelineStateD3D11Impl.hpp | 145 +-- .../GraphicsEngineD3D11/include/QueryD3D11Impl.hpp | 4 +- .../include/RenderDeviceD3D11Impl.hpp | 14 +- .../include/RenderPassD3D11Impl.hpp | 4 +- .../include/SamplerD3D11Impl.hpp | 4 +- .../include/ShaderD3D11Impl.hpp | 7 +- .../include/ShaderResourceBindingD3D11Impl.hpp | 76 +- .../include/ShaderResourceCacheD3D11.hpp | 376 +++++-- .../include/ShaderResourceLayoutD3D11.hpp | 430 -------- .../include/ShaderVariableManagerD3D11.hpp | 496 +++++++++ .../include/TextureBaseD3D11.hpp | 4 +- .../include/TextureViewD3D11Impl.hpp | 4 +- .../src/BufferViewD3D11Impl.cpp | 3 +- .../src/DeviceContextD3D11Impl.cpp | 1051 ++++++++------------ .../src/PipelineResourceSignatureD3D11Impl.cpp | 489 +++++++++ .../src/PipelineStateD3D11Impl.cpp | 774 +++++++------- .../src/RenderDeviceD3D11Impl.cpp | 147 +-- .../GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp | 4 - .../src/ShaderResourceBindingD3D11Impl.cpp | 209 +--- .../src/ShaderResourceCacheD3D11.cpp | 642 +++++++++--- .../src/ShaderResourceLayoutD3D11.cpp | 1022 ------------------- .../src/ShaderResourcesD3D11.cpp | 28 +- .../src/ShaderVariableManagerD3D11.cpp | 857 ++++++++++++++++ 32 files changed, 4096 insertions(+), 3258 deletions(-) create mode 100644 Graphics/GraphicsEngineD3D11/include/EngineD3D11ImplTraits.hpp create mode 100644 Graphics/GraphicsEngineD3D11/include/PipelineResourceAttribsD3D11.hpp create mode 100644 Graphics/GraphicsEngineD3D11/include/PipelineResourceSignatureD3D11Impl.hpp delete mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp create mode 100644 Graphics/GraphicsEngineD3D11/include/ShaderVariableManagerD3D11.hpp create mode 100644 Graphics/GraphicsEngineD3D11/src/PipelineResourceSignatureD3D11Impl.cpp delete mode 100755 Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp create mode 100644 Graphics/GraphicsEngineD3D11/src/ShaderVariableManagerD3D11.cpp (limited to 'Graphics/GraphicsEngineD3D11') diff --git a/Graphics/GraphicsEngineD3D11/CMakeLists.txt b/Graphics/GraphicsEngineD3D11/CMakeLists.txt index 05715440..cd903d79 100644 --- a/Graphics/GraphicsEngineD3D11/CMakeLists.txt +++ b/Graphics/GraphicsEngineD3D11/CMakeLists.txt @@ -16,6 +16,8 @@ set(INCLUDE include/FenceD3D11Impl.hpp include/FramebufferD3D11Impl.hpp include/PipelineStateD3D11Impl.hpp + include/PipelineResourceAttribsD3D11.hpp + include/PipelineResourceSignatureD3D11Impl.hpp include/QueryD3D11Impl.hpp include/RenderDeviceD3D11Impl.hpp include/RenderPassD3D11Impl.hpp @@ -23,7 +25,7 @@ set(INCLUDE include/ShaderD3D11Impl.hpp include/ShaderResourceBindingD3D11Impl.hpp include/ShaderResourceCacheD3D11.hpp - include/ShaderResourceLayoutD3D11.hpp + include/ShaderVariableManagerD3D11.hpp include/ShaderResourcesD3D11.hpp include/SwapChainD3D11Impl.hpp include/targetver.h @@ -63,6 +65,7 @@ set(SRC src/FramebufferD3D11Impl.cpp src/GUIDDef.cpp src/PipelineStateD3D11Impl.cpp + src/PipelineResourceSignatureD3D11Impl.cpp src/QueryD3D11Impl.cpp src/RenderDeviceD3D11Impl.cpp src/RenderPassD3D11Impl.cpp @@ -70,7 +73,7 @@ set(SRC src/ShaderD3D11Impl.cpp src/ShaderResourceBindingD3D11Impl.cpp src/ShaderResourceCacheD3D11.cpp - src/ShaderResourceLayoutD3D11.cpp + src/ShaderVariableManagerD3D11.cpp src/ShaderResourcesD3D11.cpp src/SwapChainD3D11Impl.cpp src/Texture1D_D3D11.cpp diff --git a/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp index 4d82cd39..2f523ea5 100644 --- a/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/BufferD3D11Impl.hpp @@ -39,13 +39,11 @@ namespace Diligent { -class FixedBlockMemoryAllocator; - /// Buffer object implementation in Direct3D11 backend. -class BufferD3D11Impl final : public BufferBase +class BufferD3D11Impl final : public BufferBase { public: - using TBufferBase = BufferBase; + using TBufferBase = BufferBase; BufferD3D11Impl(IReferenceCounters* pRefCounters, FixedBlockMemoryAllocator& BuffViewObjMemAllocator, diff --git a/Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.hpp index 0f9ee914..44121a4a 100644 --- a/Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/BufferViewD3D11Impl.hpp @@ -41,15 +41,15 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Buffer view implementation in Direct3D11 backend. -class BufferViewD3D11Impl final : public BufferViewBase +class BufferViewD3D11Impl final : public BufferViewBase { public: - using TBufferViewBase = BufferViewBase; + using TBufferViewBase = BufferViewBase; BufferViewD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pDevice, const BufferViewDesc& ViewDesc, - IBuffer* pBuffer, + BufferD3D11Impl* pBuffer, ID3D11View* pD3D11View, bool bIsDefaultView); diff --git a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp index 3c7bf09c..5c72ed1f 100644 --- a/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/DeviceContextD3D11Impl.hpp @@ -43,32 +43,20 @@ #include "DisjointQueryPool.hpp" #include "BottomLevelASBase.hpp" #include "TopLevelASBase.hpp" +#include "ShaderResourceBindingD3D11Impl.hpp" -#ifdef DILIGENT_DEBUG +#ifdef DILIGENT_DEVELOPMENT # define VERIFY_CONTEXT_BINDINGS #endif namespace Diligent { -struct DeviceContextD3D11ImplTraits -{ - using BufferType = BufferD3D11Impl; - using TextureType = TextureBaseD3D11; - using PipelineStateType = PipelineStateD3D11Impl; - using DeviceType = RenderDeviceD3D11Impl; - using QueryType = QueryD3D11Impl; - using FramebufferType = FramebufferD3D11Impl; - using RenderPassType = RenderPassD3D11Impl; - using BottomLevelASType = BottomLevelASBase; - using TopLevelASType = TopLevelASBase; -}; - /// Device context implementation in Direct3D11 backend. -class DeviceContextD3D11Impl final : public DeviceContextBase +class DeviceContextD3D11Impl final : public DeviceContextBase { public: - using TDeviceContextBase = DeviceContextBase; + using TDeviceContextBase = DeviceContextBase; DeviceContextD3D11Impl(IReferenceCounters* pRefCounters, IMemoryAllocator& Allocator, @@ -288,8 +276,8 @@ public: /// Unbinds all render targets. Used when resizing the swap chain. virtual void ResetRenderTargets() override final; - /// Number of different shader types (Vertex, Pixel, Geometry, Domain, Hull, Compute) - static constexpr int NumShaderTypes = 6; + void TransitionResource(TextureBaseD3D11* pTexture, RESOURCE_STATE NewState, RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN, bool UpdateResourceState = true); + void TransitionResource(BufferD3D11Impl* pBuffer, RESOURCE_STATE NewState, RESOURCE_STATE OldState = RESOURCE_STATE_UNKNOWN, bool UpdateResourceState = true); private: /// Commits d3d11 index buffer to d3d11 device context. @@ -341,54 +329,53 @@ private: /// Ends current subpass void EndSubpass(); - template - void TransitionAndCommitShaderResources(IPipelineState* pPSO, IShaderResourceBinding* pShaderResourceBinding, bool VerifyStates); - void ClearStateCache(); + void BindShaderResources(); + + using TBindingsPerStage = PipelineResourceSignatureD3D11Impl::TBindingsPerStage; + using TCommittedResources = ShaderResourceCacheD3D11::TCommittedResources; + using TMinMaxSlotPerStage = ShaderResourceCacheD3D11::TMinMaxSlotPerStage; + + static constexpr auto NumShaderTypes = PipelineResourceSignatureD3D11Impl::NumShaderTypes; + +#ifdef DILIGENT_DEVELOPMENT + void DvpValidateCommittedShaderResources(); +#endif + std::shared_ptr BeginDisjointQuery(); CComPtr m_pd3d11DeviceContext; ///< D3D11 device context - // clang-format off - - /// An array of D3D11 constant buffers committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11Buffer* m_CommittedD3D11CBs [NumShaderTypes][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {}; - - /// An array of D3D11 shader resource views committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11ShaderResourceView* m_CommittedD3D11SRVs [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; - - /// An array of D3D11 samplers committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11SamplerState* m_CommittedD3D11Samplers[NumShaderTypes][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {}; - - /// An array of D3D11 UAVs committed to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11UnorderedAccessView* m_CommittedD3D11UAVs [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; - - /// An array of D3D11 resources commited as SRV to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11Resource* m_CommittedD3D11SRVResources [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; - - /// An array of D3D11 resources commited as UAV to D3D11 device context, - /// for each shader type. The context addref's all bound resources, so we do - /// not need to keep strong references. - ID3D11Resource* m_CommittedD3D11UAVResources [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; - - Uint8 m_NumCommittedCBs [NumShaderTypes] = {}; - Uint8 m_NumCommittedSRVs [NumShaderTypes] = {}; - Uint8 m_NumCommittedSamplers[NumShaderTypes] = {}; - Uint8 m_NumCommittedUAVs [NumShaderTypes] = {}; - - // clang-format on + struct SRBState + { + // Do not use strong references! + std::array SRBs = {}; + + using Bitfield = Uint8; + static_assert(sizeof(Bitfield) * 8 >= MAX_RESOURCE_SIGNATURES, "not enought space to store MAX_RESOURCE_SIGNATURES bits"); + + Bitfield ActiveSRBMask = 0; // Indicates which SRBs are active in current PSO + Bitfield StaleSRBMask = 0; // Indicates stale SRBs that have descriptor sets that need to be bound + + SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; + +#ifdef DILIGENT_DEVELOPMENT + bool CommittedResourcesValidated = false; + + // Binding offsets that was used at last BindProgramResources() call. + std::array BoundResOffsets = {}; +#endif + + SRBState() + {} + + void SetStaleSRBBit(Uint32 Index) { StaleSRBMask |= static_cast(1u << Index); } + void ClearStaleSRBBit(Uint32 Index) { StaleSRBMask &= static_cast(~(1u << Index)); } + + } m_BindInfo; + + TCommittedResources m_CommittedRes; /// An array of D3D11 vertex buffers committed to D3D device context. /// There is no need to keep strong references because D3D11 device context @@ -438,60 +425,51 @@ private: /// Helper template function used to facilitate context verification template - void dbgVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources], + void DvpVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources], Uint8 NumCommittedResourcesArr[], TGetD3D11ResourcesType GetD3D11ResMethods[], const Char* ResourceName, - SHADER_TYPE ShaderType); + SHADER_TYPE ShaderStages); /// Helper template function used to facilitate validation of SRV and UAV consistency with D3D11 resources template - void dbgVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources], + void DvpVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources], ID3D11Resource* CommittedD3D11ResourcesArr[][MaxResources], Uint8 NumCommittedResourcesArr[], const Char* ResourceName, - SHADER_TYPE ShaderType); + SHADER_TYPE ShaderStages); /// Debug function that verifies that SRVs cached in m_CommittedD3D11SRVs /// array comply with resources actually committed to D3D11 device context - void dbgVerifyCommittedSRVs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + void DvpVerifyCommittedSRVs(SHADER_TYPE ShaderStages); /// Debug function that verifies that UAVs cached in m_CommittedD3D11UAVs /// array comply with resources actually committed to D3D11 device context - void dbgVerifyCommittedUAVs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + void DvpVerifyCommittedUAVs(SHADER_TYPE ShaderStages); /// Debug function that verifies that samplers cached in m_CommittedD3D11Samplers /// array comply with resources actually committed to D3D11 device context - void dbgVerifyCommittedSamplers(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + void DvpVerifyCommittedSamplers(SHADER_TYPE ShaderStages); /// Debug function that verifies that constant buffers cached in m_CommittedD3D11CBs /// array comply with buffers actually committed to D3D11 device context - void dbgVerifyCommittedCBs(SHADER_TYPE ShaderType = SHADER_TYPE_UNKNOWN); + void DvpVerifyCommittedCBs(SHADER_TYPE ShaderStages); /// Debug function that verifies that index buffer cached in /// m_CommittedD3D11IndexBuffer is the buffer actually committed to D3D11 /// device context - void dbgVerifyCommittedIndexBuffer(); + void DvpVerifyCommittedIndexBuffer(); /// Debug function that verifies that vertex buffers cached in /// m_CommittedD3D11VertexBuffers are the buffers actually committed to D3D11 /// device context - void dbgVerifyCommittedVertexBuffers(); + void DvpVerifyCommittedVertexBuffers(); /// Debug function that verifies that shaders cached in /// m_CommittedD3DShaders are the shaders actually committed to D3D11 /// device context - void dbgVerifyCommittedShaders(); - -#else -# define dbgVerifyRenderTargetFormats(...) -# define dbgVerifyCommittedSRVs(...) -# define dbgVerifyCommittedUAVs(...) -# define dbgVerifyCommittedSamplers(...) -# define dbgVerifyCommittedCBs(...) -# define dbgVerifyCommittedIndexBuffer(...) -# define dbgVerifyCommittedVertexBuffers(...) -# define dbgVerifyCommittedShaders(...) + void DvpVerifyCommittedShaders(); + #endif // VERIFY_CONTEXT_BINDINGS }; diff --git a/Graphics/GraphicsEngineD3D11/include/EngineD3D11ImplTraits.hpp b/Graphics/GraphicsEngineD3D11/include/EngineD3D11ImplTraits.hpp new file mode 100644 index 00000000..87e3e0cb --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/EngineD3D11ImplTraits.hpp @@ -0,0 +1,120 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Declaration of Diligent::EngineD3D11ImplTraits struct + +#include "RenderDeviceD3D11.h" +#include "PipelineStateD3D11.h" +#include "ShaderResourceBindingD3D11.h" +#include "BufferD3D11.h" +#include "BufferViewD3D11.h" +#include "TextureD3D11.h" +#include "TextureViewD3D11.h" +#include "ShaderD3D11.h" +#include "SamplerD3D11.h" +#include "FenceD3D11.h" +#include "QueryD3D11.h" +#include "RenderPass.h" +#include "Framebuffer.h" +#include "PipelineResourceSignature.h" +#include "DeviceContextD3D11.h" + +namespace Diligent +{ + +class RenderDeviceD3D11Impl; +class DeviceContextD3D11Impl; +class PipelineStateD3D11Impl; +class ShaderResourceBindingD3D11Impl; +class BufferD3D11Impl; +class BufferViewD3D11Impl; +class TextureBaseD3D11; +class TextureViewD3D11Impl; +class ShaderD3D11Impl; +class SamplerD3D11Impl; +class FenceD3D11Impl; +class QueryD3D11Impl; +class RenderPassD3D11Impl; +class FramebufferD3D11Impl; +class BottomLevelASD3D11Impl; +class TopLevelASD3D11Impl; +class ShaderBindingTableD3D11Impl; +class PipelineResourceSignatureD3D11Impl; + +class FixedBlockMemoryAllocator; + +class ShaderResourceCacheD3D11; +class ShaderVariableManagerD3D11; + +struct EngineD3D11ImplTraits +{ + using RenderDeviceInterface = IRenderDeviceD3D11; + using DeviceContextInterface = IDeviceContextD3D11; + using PipelineStateInterface = IPipelineStateD3D11; + using ShaderResourceBindingInterface = IShaderResourceBindingD3D11; + using BufferInterface = IBufferD3D11; + using BufferViewInterface = IBufferViewD3D11; + using TextureInterface = ITextureD3D11; + using TextureViewInterface = ITextureViewD3D11; + using ShaderInterface = IShaderD3D11; + using SamplerInterface = ISamplerD3D11; + using FenceInterface = IFenceD3D11; + using QueryInterface = IQueryD3D11; + using RenderPassInterface = IRenderPass; + using FramebufferInterface = IFramebuffer; + using PipelineResourceSignatureInterface = IPipelineResourceSignature; + + using RenderDeviceImplType = RenderDeviceD3D11Impl; + using DeviceContextImplType = DeviceContextD3D11Impl; + using PipelineStateImplType = PipelineStateD3D11Impl; + using ShaderResourceBindingImplType = ShaderResourceBindingD3D11Impl; + using BufferImplType = BufferD3D11Impl; + using BufferViewImplType = BufferViewD3D11Impl; + using TextureImplType = TextureBaseD3D11; + using TextureViewImplType = TextureViewD3D11Impl; + using ShaderImplType = ShaderD3D11Impl; + using SamplerImplType = SamplerD3D11Impl; + using FenceImplType = FenceD3D11Impl; + using QueryImplType = QueryD3D11Impl; + using RenderPassImplType = RenderPassD3D11Impl; + using FramebufferImplType = FramebufferD3D11Impl; + using BottomLevelASImplType = BottomLevelASD3D11Impl; + using TopLevelASImplType = TopLevelASD3D11Impl; + using ShaderBindingTableImplType = ShaderBindingTableD3D11Impl; + using PipelineResourceSignatureImplType = PipelineResourceSignatureD3D11Impl; + + using BuffViewObjAllocatorType = FixedBlockMemoryAllocator; + using TexViewObjAllocatorType = FixedBlockMemoryAllocator; + + using ShaderResourceCacheImplType = ShaderResourceCacheD3D11; + using ShaderVariableManagerImplType = ShaderVariableManagerD3D11; +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp index f1e0e87a..9385d3c4 100644 --- a/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/FenceD3D11Impl.hpp @@ -39,13 +39,11 @@ namespace Diligent { -class FixedBlockMemoryAllocator; - /// Fence implementation in Direct3D11 backend. -class FenceD3D11Impl final : public FenceBase +class FenceD3D11Impl final : public FenceBase { public: - using TFenceBase = FenceBase; + using TFenceBase = FenceBase; FenceD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pDevice, diff --git a/Graphics/GraphicsEngineD3D11/include/FramebufferD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/FramebufferD3D11Impl.hpp index 39ca46e9..1cd1654a 100644 --- a/Graphics/GraphicsEngineD3D11/include/FramebufferD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/FramebufferD3D11Impl.hpp @@ -40,10 +40,10 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Render pass implementation in Direct3D11 backend. -class FramebufferD3D11Impl final : public FramebufferBase +class FramebufferD3D11Impl final : public FramebufferBase { public: - using TFramebufferBase = FramebufferBase; + using TFramebufferBase = FramebufferBase; FramebufferD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pDevice, diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineResourceAttribsD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineResourceAttribsD3D11.hpp new file mode 100644 index 00000000..ad5ae8c1 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/PipelineResourceAttribsD3D11.hpp @@ -0,0 +1,115 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Declaration of Diligent::PipelineResourceAttribsD3D11 struct + +#include + +#include "BasicTypes.h" +#include "DebugUtilities.hpp" + +namespace Diligent +{ + +enum DESCRIPTOR_RANGE : Uint32 +{ + DESCRIPTOR_RANGE_CBV = 0, + DESCRIPTOR_RANGE_SRV, + DESCRIPTOR_RANGE_SAMPLER, + DESCRIPTOR_RANGE_UAV, + DESCRIPTOR_RANGE_COUNT, + DESCRIPTOR_RANGE_UNKNOWN = ~0u +}; +DESCRIPTOR_RANGE ShaderResourceToDescriptorRange(SHADER_RESOURCE_TYPE Type); + +// sizeof(PipelineResourceAttribsD3D11) == 4, x64 +struct PipelineResourceAttribsD3D11 +{ +private: + static constexpr Uint32 _CacheOffsetBits = 10; + static constexpr Uint32 _SamplerIndBits = 10; + static constexpr Uint32 _SamplerAssignedBits = 1; + +public: + static constexpr Uint32 InvalidCacheOffset = (1u << _CacheOffsetBits) - 1; + static constexpr Uint32 InvalidSamplerInd = (1u << _SamplerIndBits) - 1; + + /// Number of different shader types (Vertex, Pixel, Geometry, Domain, Hull, Compute) + static constexpr Uint32 NumShaderTypes = 6; + + using TBindPoints = std::array; + static constexpr Uint8 InvalidBindPoint = 0xFF; + static constexpr TBindPoints InvalidBindPoints = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + + // clang-format off + const Uint32 CacheOffset : _CacheOffsetBits; // SRB and Signature has the same cache offsets for static resources. + const Uint32 SamplerInd : _SamplerIndBits; // Index of the assigned sampler in m_Desc.Resources. + const Uint32 ImtblSamplerAssigned : _SamplerAssignedBits; // Immutable sampler flag. + TBindPoints BindPoints = InvalidBindPoints; + // clang-format on + + PipelineResourceAttribsD3D11(Uint32 _CacheOffset, + Uint32 _SamplerInd, + bool _ImtblSamplerAssigned) noexcept : + // clang-format off + CacheOffset {_CacheOffset }, + SamplerInd {_SamplerInd }, + ImtblSamplerAssigned{_ImtblSamplerAssigned ? 1u : 0u} + // clang-format on + { + VERIFY(CacheOffset == _CacheOffset, "Cache offset (", _CacheOffset, ") exceeds maximum representable value"); + VERIFY(SamplerInd == _SamplerInd, "Sampler index (", _SamplerInd, ") exceeds maximum representable value"); + } + + bool IsSamplerAssigned() const { return SamplerInd != InvalidSamplerInd; } + bool IsImmutableSamplerAssigned() const { return ImtblSamplerAssigned != 0; } + + bool IsCompatibleWith(const PipelineResourceAttribsD3D11& rhs) const + { + // Ignore sampler index. + // clang-format off + return CacheOffset == rhs.CacheOffset && + IsImmutableSamplerAssigned() == rhs.IsImmutableSamplerAssigned() && + BindPoints == rhs.BindPoints; + // clang-format on + } + + size_t GetHash() const + { + Uint64 h = 0; + for (Uint32 i = 0; i < NumShaderTypes; ++i) + { + h |= (BindPoints[i] << (i * 8)); + } + return ComputeHash(h); + } +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineResourceSignatureD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineResourceSignatureD3D11Impl.hpp new file mode 100644 index 00000000..fc6233be --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/PipelineResourceSignatureD3D11Impl.hpp @@ -0,0 +1,160 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Declaration of Diligent::PipelineResourceSignatureD3D11Impl class + +#include + +#include "ResourceBindingMap.hpp" + +#include "EngineD3D11ImplTraits.hpp" +#include "PipelineResourceSignatureBase.hpp" +#include "PipelineResourceAttribsD3D11.hpp" + +// ShaderVariableManagerD3D11, ShaderResourceCacheD3D11, and ShaderResourceBindingD3D11Impl +// are required by PipelineResourceSignatureBase +#include "ShaderVariableManagerD3D11.hpp" +#include "ShaderResourceBindingD3D11Impl.hpp" +#include "ShaderResourceCacheD3D11.hpp" + +namespace Diligent +{ + +/// Implementation of the Diligent::PipelineResourceSignatureD3D11Impl class +class PipelineResourceSignatureD3D11Impl final : public PipelineResourceSignatureBase +{ +public: + using TPipelineResourceSignatureBase = PipelineResourceSignatureBase; + + PipelineResourceSignatureD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pDevice, + const PipelineResourceSignatureDesc& Desc, + bool bIsDeviceInternal = false); + ~PipelineResourceSignatureD3D11Impl(); + + using ResourceAttribs = PipelineResourceAttribsD3D11; + using TBindPoints = PipelineResourceAttribsD3D11::TBindPoints; + + static constexpr auto NumShaderTypes = ResourceAttribs::NumShaderTypes; + static constexpr auto InvalidBindPoint = ResourceAttribs::InvalidBindPoint; + static constexpr auto InvalidBindPoints = ResourceAttribs::InvalidBindPoints; + + const ResourceAttribs& GetResourceAttribs(Uint32 ResIndex) const + { + VERIFY_EXPR(ResIndex < m_Desc.NumResources); + return m_pResourceAttribs[ResIndex]; + } + + // sizeof(ImmutableSamplerAttribs) == 16, x64 + struct ImmutableSamplerAttribs + { + private: + static constexpr Uint32 _CacheOffsetBits = 10; + static constexpr Uint32 _ArraySizeBits = 22; + + public: + static constexpr Uint32 InvalidCacheOffset = (1u << _CacheOffsetBits) - 1; + static_assert(InvalidCacheOffset == ResourceAttribs::InvalidCacheOffset, + "InvalidCacheOffset value mismatch between ResourceAttribs and ImmutableSamplerAttribs"); + + // clang-format off + RefCntAutoPtr pSampler; + TBindPoints BindPoints = InvalidBindPoints; + TBindPoints LastBindPoints = InvalidBindPoints; // array size for each stage may be different + Uint32 CacheOffset : _CacheOffsetBits; + Uint32 ArraySize : _ArraySizeBits; + // clang-format on + + ImmutableSamplerAttribs() : + CacheOffset{InvalidCacheOffset}, + ArraySize{0} + {} + + bool IsAllocated() const { return CacheOffset != InvalidCacheOffset; } + SamplerD3D11Impl* GetSamplerD3D11() const { return ValidatedCast(pSampler.RawPtr()); } + }; + + const ImmutableSamplerAttribs& GetImmutableSamplerAttribs(Uint32 SampIndex) const + { + VERIFY_EXPR(SampIndex < m_Desc.NumImmutableSamplers); + return m_ImmutableSamplers[SampIndex]; + } + + using TBindings = ShaderResourceCacheD3D11::TResourceCount; + using TBindingsPerStage = ShaderResourceCacheD3D11::TBindingsPerStage; + + void AddBindings(TBindingsPerStage& Bindings) const; + + void InitSRBResourceCache(ShaderResourceCacheD3D11& ResourceCache); + + void UpdateShaderResourceBindingMap(ResourceBinding::TMap& ResourceMap, SHADER_TYPE ShaderStage, const TBindingsPerStage& BaseBindings) const; + + // Copies static resources from the static resource cache to the destination cache + void CopyStaticResources(ShaderResourceCacheD3D11& ResourceCache) const; + +#ifdef DILIGENT_DEVELOPMENT + /// Verifies committed resource attribs using the SPIRV resource attributes from the PSO. + bool DvpValidateCommittedResource(const D3DShaderResourceAttribs& D3DAttribs, + RESOURCE_DIMENSION ResourceDim, + bool IsMultisample, + Uint32 ResIndex, + const ShaderResourceCacheD3D11& ResourceCache, + const char* ShaderName, + const char* PSOName) const; +#endif + +private: + void CreateLayout(); + + void Destruct(); + +private: + TBindings m_ResourceCount = {}; + TBindingsPerStage m_BindingCountPerStage = {}; + + ResourceAttribs* m_pResourceAttribs = nullptr; // [m_Desc.NumResources] + ImmutableSamplerAttribs* m_ImmutableSamplers = nullptr; // [m_Desc.NumImmutableSamplers] +}; + + +__forceinline void PipelineResourceSignatureD3D11Impl::AddBindings(TBindingsPerStage& Bindings) const +{ + for (Uint32 s = 0; s < Bindings.size(); ++s) + { + for (Uint32 i = 0; i < Bindings[s].size(); ++i) + { + Uint32 Count = Bindings[s][i] + m_BindingCountPerStage[s][i]; + VERIFY_EXPR(Count < std::numeric_limits::max()); + Bindings[s][i] = static_cast(Count); + } + } +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 9b1a9330..f473416f 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -33,21 +33,18 @@ #include "PipelineStateD3D11.h" #include "RenderDeviceD3D11.h" #include "PipelineStateBase.hpp" -#include "ShaderResourceLayoutD3D11.hpp" -#include "SRBMemoryAllocator.hpp" -#include "RenderDeviceD3D11Impl.hpp" + +#include "PipelineResourceSignatureD3D11Impl.hpp" // Required by PipelineStateBase #include "ShaderD3D11Impl.hpp" namespace Diligent { -class FixedBlockMemoryAllocator; - /// Pipeline state object implementation in Direct3D11 backend. -class PipelineStateD3D11Impl final : public PipelineStateBase +class PipelineStateD3D11Impl final : public PipelineStateBase { public: - using TPipelineStateBase = PipelineStateBase; + using TPipelineStateBase = PipelineStateBase; PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, class RenderDeviceD3D11Impl* pDeviceD3D11, @@ -59,130 +56,88 @@ public: virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - /// Implementation of IPipelineState::BindStaticResources() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE BindStaticResources(Uint32 ShaderFlags, - IResourceMapping* pResourceMapping, - Uint32 Flags) override final; - - /// Implementation of IPipelineState::GetStaticVariableCount() in Direct3D11 backend. - virtual Uint32 DILIGENT_CALL_TYPE GetStaticVariableCount(SHADER_TYPE ShaderType) const override final; - - /// Implementation of IPipelineState::GetStaticVariableByName() in Direct3D11 backend. - virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByName(SHADER_TYPE ShaderType, - const Char* Name) override final; - - /// Implementation of IPipelineState::GetStaticVariableByIndex() in Direct3D11 backend. - virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetStaticVariableByIndex(SHADER_TYPE ShaderType, - Uint32 Index) override final; - - /// Implementation of IPipelineState::CreateShaderResourceBinding() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, - bool InitStaticResources) override final; - /// Implementation of IPipelineState::IsCompatibleWith() in Direct3D11 backend. virtual bool DILIGENT_CALL_TYPE IsCompatibleWith(const IPipelineState* pPSO) const override final; - /// Implementation of IPipelineStateD3D11::GetD3D11BlendState() method. - virtual ID3D11BlendState* DILIGENT_CALL_TYPE GetD3D11BlendState() override final; + virtual ID3D11BlendState* DILIGENT_CALL_TYPE GetD3D11BlendState() override final { return m_pd3d11BlendState; } /// Implementation of IPipelineStateD3D11::GetD3D11RasterizerState() method. - virtual ID3D11RasterizerState* DILIGENT_CALL_TYPE GetD3D11RasterizerState() override final; + virtual ID3D11RasterizerState* DILIGENT_CALL_TYPE GetD3D11RasterizerState() override final { return m_pd3d11RasterizerState; } /// Implementation of IPipelineStateD3D11::GetD3D11DepthStencilState() method. - virtual ID3D11DepthStencilState* DILIGENT_CALL_TYPE GetD3D11DepthStencilState() override final; + virtual ID3D11DepthStencilState* DILIGENT_CALL_TYPE GetD3D11DepthStencilState() override final { return m_pd3d11DepthStencilState; } /// Implementation of IPipelineStateD3D11::GetD3D11InputLayout() method. - virtual ID3D11InputLayout* DILIGENT_CALL_TYPE GetD3D11InputLayout() override final; + virtual ID3D11InputLayout* DILIGENT_CALL_TYPE GetD3D11InputLayout() override final { return m_pd3d11InputLayout; } /// Implementation of IPipelineStateD3D11::GetD3D11VertexShader() method. - virtual ID3D11VertexShader* DILIGENT_CALL_TYPE GetD3D11VertexShader() override final; + virtual ID3D11VertexShader* DILIGENT_CALL_TYPE GetD3D11VertexShader() override final { return m_pVS; } /// Implementation of IPipelineStateD3D11::GetD3D11PixelShader() method. - virtual ID3D11PixelShader* DILIGENT_CALL_TYPE GetD3D11PixelShader() override final; + virtual ID3D11PixelShader* DILIGENT_CALL_TYPE GetD3D11PixelShader() override final { return m_pPS; } /// Implementation of IPipelineStateD3D11::GetD3D11GeometryShader() method. - virtual ID3D11GeometryShader* DILIGENT_CALL_TYPE GetD3D11GeometryShader() override final; + virtual ID3D11GeometryShader* DILIGENT_CALL_TYPE GetD3D11GeometryShader() override final { return m_pGS; } /// Implementation of IPipelineStateD3D11::GetD3D11DomainShader() method. - virtual ID3D11DomainShader* DILIGENT_CALL_TYPE GetD3D11DomainShader() override final; + virtual ID3D11DomainShader* DILIGENT_CALL_TYPE GetD3D11DomainShader() override final { return m_pDS; } /// Implementation of IPipelineStateD3D11::GetD3D11HullShader() method. - virtual ID3D11HullShader* DILIGENT_CALL_TYPE GetD3D11HullShader() override final; + virtual ID3D11HullShader* DILIGENT_CALL_TYPE GetD3D11HullShader() override final { return m_pHS; } /// Implementation of IPipelineStateD3D11::GetD3D11ComputeShader() method. - virtual ID3D11ComputeShader* DILIGENT_CALL_TYPE GetD3D11ComputeShader() override final; + virtual ID3D11ComputeShader* DILIGENT_CALL_TYPE GetD3D11ComputeShader() override final { return m_pCS; } + Uint32 GetNumShaders() const { return m_NumShaders; } + SHADER_TYPE GetShaderStageType(Uint32 Index) const; - SRBMemoryAllocator& GetSRBMemoryAllocator() - { - return m_SRBMemAllocator; - } +private: + template + void InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector>& ByteCodes); - const ShaderResourceLayoutD3D11& GetStaticResourceLayout(Uint32 s) const - { - VERIFY_EXPR(s < GetNumShaderStages()); - return m_pStaticResourceLayouts[s]; - } + void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, + const std::vector& Shaders, + std::vector>& ByteCodes); - ShaderResourceCacheD3D11& GetStaticResourceCache(Uint32 s) - { - VERIFY_EXPR(s < GetNumShaderStages()); - return m_pStaticResourceCaches[s]; - } + RefCntAutoPtr CreateDefaultResourceSignature( + const PipelineStateCreateInfo& CreateInfo, + const std::vector& Shaders); - const ShaderD3D11Impl* GetShaderByType(SHADER_TYPE ShaderType) const; - const ShaderD3D11Impl* GetShader(Uint32 Index) const; + void Destruct(); - void SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; + void ValidateShaderResources(const ShaderD3D11Impl* pShader); private: - template - void InitInternalObjects(const PSOCreateInfoType& CreateInfo); + using SignaturePtr = RefCntAutoPtr; - void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, - const std::vector& Shaders); - - void Destruct(); + std::array m_ShaderTypes = {}; + Uint8 m_NumShaders = 0; CComPtr m_pd3d11BlendState; CComPtr m_pd3d11RasterizerState; CComPtr m_pd3d11DepthStencilState; CComPtr m_pd3d11InputLayout; - - RefCntAutoPtr m_pVS; - RefCntAutoPtr m_pPS; - RefCntAutoPtr m_pGS; - RefCntAutoPtr m_pDS; - RefCntAutoPtr m_pHS; - RefCntAutoPtr m_pCS; - - // The caches are indexed by the shader order in the PSO, not shader index - ShaderResourceCacheD3D11* m_pStaticResourceCaches = nullptr; // [m_NumShaderStages] - ShaderResourceLayoutD3D11* m_pStaticResourceLayouts = nullptr; // [m_NumShaderStages] - - // SRB memory allocator must be defined before the default shader res binding - SRBMemoryAllocator m_SRBMemAllocator; - - // Resource layout index in m_pStaticResourceLayouts array for every shader stage, - // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; - static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); - - std::array m_ImmutableSamplerOffsets = {}; - struct ImmutableSamplerInfo - { - const D3DShaderResourceAttribs& Attribs; - RefCntAutoPtr pSampler; - ImmutableSamplerInfo(const D3DShaderResourceAttribs& _Attribs, - RefCntAutoPtr _pSampler) : - // clang-format off - Attribs {_Attribs}, - pSampler {std::move(_pSampler)} - // clang-format on - {} - }; - std::vector> m_ImmutableSamplers; + CComPtr m_pVS; + CComPtr m_pPS; + CComPtr m_pGS; + CComPtr m_pDS; + CComPtr m_pHS; + CComPtr m_pCS; + +#ifdef DILIGENT_DEVELOPMENT + // Shader resources for all shaders in all shader stages in the pipeline. + std::vector> m_ShaderResources; + + // Shader resource attributions for every resource in m_ShaderResources, in the same order. + std::vector m_ResourceAttibutions; +#endif }; +__forceinline SHADER_TYPE GetShaderStageType(const ShaderD3D11Impl* pShader) +{ + return pShader->GetDesc().ShaderType; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp index c7052d4f..6d011c5d 100644 --- a/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/QueryD3D11Impl.hpp @@ -43,10 +43,10 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Query implementation in Direct3D11 backend. -class QueryD3D11Impl final : public QueryBase +class QueryD3D11Impl final : public QueryBase { public: - using TQueryBase = QueryBase; + using TQueryBase = QueryBase; QueryD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pDevice, diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp index 0d5d4187..bd9cf2f9 100644 --- a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp @@ -30,7 +30,7 @@ /// \file /// Declaration of Diligent::RenderDeviceD3D11Impl class -#include "RenderDeviceD3D11.h" +#include "EngineD3D11ImplTraits.hpp" #include "RenderDeviceD3DBase.hpp" #include "DeviceContextD3D11.h" @@ -38,10 +38,10 @@ namespace Diligent { /// Render device implementation in Direct3D11 backend. -class RenderDeviceD3D11Impl final : public RenderDeviceD3DBase +class RenderDeviceD3D11Impl final : public RenderDeviceD3DBase { public: - using TRenderDeviceBase = RenderDeviceD3DBase; + using TRenderDeviceBase = RenderDeviceD3DBase; RenderDeviceD3D11Impl(IReferenceCounters* pRefCounters, IMemoryAllocator& RawMemAllocator, @@ -109,6 +109,14 @@ public: virtual void DILIGENT_CALL_TYPE CreateSBT(const ShaderBindingTableDesc& Desc, IShaderBindingTable** ppSBT) override final; + /// Implementation of IRenderDevice::CreatePipelineResourceSignature() in Direct3D11 backend. + virtual void DILIGENT_CALL_TYPE CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc, + IPipelineResourceSignature** ppSignature) override final; + + void CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc, + IPipelineResourceSignature** ppSignature, + bool IsDeviceInternal); + /// Implementation of IRenderDeviceD3D11::GetD3D11Device() in Direct3D11 backend. ID3D11Device* DILIGENT_CALL_TYPE GetD3D11Device() override final { return m_pd3d11Device; } diff --git a/Graphics/GraphicsEngineD3D11/include/RenderPassD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderPassD3D11Impl.hpp index 2ac99a15..82a5d290 100644 --- a/Graphics/GraphicsEngineD3D11/include/RenderPassD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/RenderPassD3D11Impl.hpp @@ -40,10 +40,10 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Render pass implementation in Direct3D11 backend. -class RenderPassD3D11Impl final : public RenderPassBase +class RenderPassD3D11Impl final : public RenderPassBase { public: - using TRenderPassBase = RenderPassBase; + using TRenderPassBase = RenderPassBase; RenderPassD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pDevice, diff --git a/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp index f30427e0..415b8b69 100644 --- a/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/SamplerD3D11Impl.hpp @@ -41,10 +41,10 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Sampler implementation in Direct3D11 backend. -class SamplerD3D11Impl final : public SamplerBase +class SamplerD3D11Impl final : public SamplerBase { public: - using TSamplerBase = SamplerBase; + using TSamplerBase = SamplerBase; SamplerD3D11Impl(IReferenceCounters* pRefCounters, class RenderDeviceD3D11Impl* pRenderDeviceD3D11, diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp index 257286bf..b17e473d 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderD3D11Impl.hpp @@ -34,7 +34,6 @@ #include "RenderDeviceD3D11.h" #include "ShaderBase.hpp" #include "ShaderD3DBase.hpp" -#include "ShaderResourceLayoutD3D11.hpp" #include "ShaderResourceCacheD3D11.hpp" #include "EngineD3D11Defines.h" #include "ShaderResourcesD3D11.hpp" @@ -47,10 +46,10 @@ class FixedBlockMemoryAllocator; class ResourceMapping; /// Shader implementation in Direct3D11 backend. -class ShaderD3D11Impl final : public ShaderBase, public ShaderD3DBase +class ShaderD3D11Impl final : public ShaderBase, public ShaderD3DBase { public: - using TShaderBase = ShaderBase; + using TShaderBase = ShaderBase; ShaderD3D11Impl(IReferenceCounters* pRefCounters, class RenderDeviceD3D11Impl* pRenderDeviceD3D11, @@ -85,7 +84,7 @@ public: ID3DBlob* GetBytecode() { return m_pShaderByteCode; } - const std::shared_ptr& GetD3D11Resources() const { return m_pShaderResources; } + const std::shared_ptr& GetShaderResources() const { return m_pShaderResources; } private: /// D3D11 shader diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp index 5beeb027..36be84cc 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp @@ -35,87 +35,25 @@ #include "ShaderResourceBindingD3D11.h" #include "RenderDeviceD3D11.h" #include "ShaderResourceBindingBase.hpp" + +// ShaderResourceCacheD3D11 and ShaderVariableManagerD3D11 are required by ShaderResourceBindingBase #include "ShaderResourceCacheD3D11.hpp" -#include "ShaderResourceLayoutD3D11.hpp" -#include "STDAllocator.hpp" +#include "ShaderVariableManagerD3D11.hpp" namespace Diligent { -class PipelineStateD3D11Impl; - /// Implementation of shader resource binding object in Direct3D11 backend. -class ShaderResourceBindingD3D11Impl final : public ShaderResourceBindingBase +class ShaderResourceBindingD3D11Impl final : public ShaderResourceBindingBase { public: - using TBase = ShaderResourceBindingBase; + using TBase = ShaderResourceBindingBase; - ShaderResourceBindingD3D11Impl(IReferenceCounters* pRefCounters, - PipelineStateD3D11Impl* pPSO, - bool IsInternal); + ShaderResourceBindingD3D11Impl(IReferenceCounters* pRefCounters, + PipelineResourceSignatureD3D11Impl* pPRS); ~ShaderResourceBindingD3D11Impl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - - /// Implementation of IShaderResourceBinding::BindResources() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE BindResources(Uint32 ShaderFlags, - IResourceMapping* pResMapping, - Uint32 Flags) override final; - - /// Implementation of IShaderResourceBinding::GetVariableByName() in Direct3D11 backend. - virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetVariableByName(SHADER_TYPE ShaderType, const char* Name) override final; - - /// Implementation of IShaderResourceBinding::GetVariableCount() in Direct3D11 backend. - virtual Uint32 DILIGENT_CALL_TYPE GetVariableCount(SHADER_TYPE ShaderType) const override final; - - /// Implementation of IShaderResourceBinding::GetVariableByIndex() in Direct3D11 backend. - virtual IShaderResourceVariable* DILIGENT_CALL_TYPE GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) override final; - - /// Implementation of IShaderResourceBinding::InitializeStaticResources() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE InitializeStaticResources(const IPipelineState* pPipelineState) override final; - - ShaderResourceCacheD3D11& GetResourceCache(Uint32 Ind) - { - VERIFY_EXPR(Ind < m_NumActiveShaders); - return m_pBoundResourceCaches[Ind]; - } - - ShaderResourceLayoutD3D11& GetResourceLayout(Uint32 Ind) - { - VERIFY_EXPR(Ind < m_NumActiveShaders); - return m_pResourceLayouts[Ind]; - } - - inline bool IsStaticResourcesBound() const { return m_bIsStaticResourcesBound; } - - Uint32 GetNumActiveShaders() const - { - return Uint32{m_NumActiveShaders}; - } - - SHADER_TYPE GetActiveShaderType(Uint32 s) const - { - VERIFY_EXPR(s < m_NumActiveShaders); - return m_ShaderTypes[s]; - } - -private: - void Destruct(); - - // The caches are indexed by the shader order in the PSO, not shader index - ShaderResourceCacheD3D11* m_pBoundResourceCaches = nullptr; - ShaderResourceLayoutD3D11* m_pResourceLayouts = nullptr; - - std::array m_ShaderTypes = {}; - - // Resource layout index in m_pResourceLayouts array for every shader stage, - // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1, -1}; - static_assert(MAX_SHADERS_IN_PIPELINE == 6, "Please update the initializer list above"); - - Uint8 m_NumActiveShaders = 0; - - bool m_bIsStaticResourcesBound = false; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp index 321a758a..7f208182 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp @@ -31,9 +31,11 @@ /// Declaration of Diligent::ShaderResourceCacheD3D11 class #include "MemoryAllocator.h" +#include "ShaderResourceCacheCommon.hpp" #include "TextureBaseD3D11.hpp" #include "BufferD3D11Impl.hpp" #include "SamplerD3D11Impl.hpp" +#include "PipelineResourceAttribsD3D11.hpp" namespace Diligent { @@ -51,7 +53,8 @@ namespace Diligent class ShaderResourceCacheD3D11 { public: - ShaderResourceCacheD3D11() noexcept + explicit ShaderResourceCacheD3D11(ResourceCacheContentType ContentType) noexcept : + m_ContentType{ContentType} {} ~ShaderResourceCacheD3D11(); @@ -63,12 +66,81 @@ public: ShaderResourceCacheD3D11& operator = (ShaderResourceCacheD3D11&&) = delete; // clang-format on + enum class StateTransitionMode + { + Transition, + Verify + }; + // Transitions all resources in the cache + void TransitionResourceStates(DeviceContextD3D11Impl& Ctx, StateTransitionMode Mode); + + + static constexpr int NumShaderTypes = PipelineResourceAttribsD3D11::NumShaderTypes; + + struct TCommittedResources + { + // clang-format off + + /// An array of D3D11 constant buffers committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11Buffer* D3D11CBs [NumShaderTypes][D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT] = {}; + + /// An array of D3D11 shader resource views committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11ShaderResourceView* D3D11SRVs [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; + + /// An array of D3D11 samplers committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11SamplerState* D3D11Samplers[NumShaderTypes][D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT] = {}; + + /// An array of D3D11 UAVs committed to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11UnorderedAccessView* D3D11UAVs [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; + + /// An array of D3D11 resources commited as SRV to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11Resource* D3D11SRVResources [NumShaderTypes][D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT] = {}; + + /// An array of D3D11 resources commited as UAV to D3D11 device context, + /// for each shader type. The context addref's all bound resources, so we do + /// not need to keep strong references. + ID3D11Resource* D3D11UAVResources [NumShaderTypes][D3D11_PS_CS_UAV_REGISTER_COUNT] = {}; + + Uint8 NumCBs [NumShaderTypes] = {}; + Uint8 NumSRVs [NumShaderTypes] = {}; + Uint8 NumSamplers[NumShaderTypes] = {}; + Uint8 NumUAVs [NumShaderTypes] = {}; + + // clang-format on + + void Clear(); + }; + + struct MinMaxSlot + { + UINT MinSlot = UINT_MAX; + UINT MaxSlot = 0; + }; + using TMinMaxSlotPerStage = std::array, NumShaderTypes>; + using TResourceCount = std::array; + using TBindingsPerStage = std::array; + + void BindResources(DeviceContextD3D11Impl& Ctx, const TBindingsPerStage& BaseBindings, TMinMaxSlotPerStage& MinMaxSlot, TCommittedResources& CommittedRes, SHADER_TYPE ActiveStages) const; + + /// Describes a resource associated with a cached constant buffer struct CachedCB { /// Strong reference to the buffer RefCntAutoPtr pBuff; + private: + friend class ShaderResourceCacheD3D11; __forceinline void Set(RefCntAutoPtr&& _pBuff) { pBuff = std::move(_pBuff); @@ -81,6 +153,8 @@ public: /// Strong reference to the sampler RefCntAutoPtr pSampler; + private: + friend class ShaderResourceCacheD3D11; __forceinline void Set(SamplerD3D11Impl* pSam) { pSampler = pSam; @@ -106,6 +180,8 @@ public: CachedResource() noexcept {} + private: + friend class ShaderResourceCacheD3D11; __forceinline void Set(RefCntAutoPtr&& pTexView) { pBuffer = nullptr; @@ -125,211 +201,325 @@ public: } }; - static size_t GetRequriedMemorySize(const class ShaderResourcesD3D11& Resources); + static size_t GetRequriedMemorySize(const TResourceCount& ResCount); + + void Initialize(const TResourceCount& ResCount, IMemoryAllocator& MemAllocator); - void Initialize(const class ShaderResourcesD3D11& Resources, IMemoryAllocator& MemAllocator); - void Initialize(Uint32 CBCount, Uint32 SRVCount, Uint32 SamplerCount, Uint32 UAVCount, IMemoryAllocator& MemAllocator); - void Destroy(IMemoryAllocator& MemAllocator); + using TBindPoints = PipelineResourceAttribsD3D11::TBindPoints; + using TBindPointsAndActiveBits = std::array; // ActiveBits [0], TBindPoints [1..6] + static constexpr auto InvalidBindPoint = PipelineResourceAttribsD3D11::InvalidBindPoint; - __forceinline void SetCB(Uint32 Slot, RefCntAutoPtr&& pBuffD3D11Impl) + __forceinline void SetCB(Uint32 CacheOffset, Uint32 ArrayIndex, TBindPoints BindPoints, RefCntAutoPtr&& pBuffD3D11Impl) { auto* pd3d11Buff = pBuffD3D11Impl ? pBuffD3D11Impl->BufferD3D11Impl::GetD3D11Buffer() : nullptr; - SetD3D11ResourceInternal(Slot, GetCBCount(), &ShaderResourceCacheD3D11::GetCBArrays, std::move(pBuffD3D11Impl), pd3d11Buff); + SetD3D11ResourceInternal(CacheOffset, ArrayIndex, GetCBCount(), BindPoints, &ShaderResourceCacheD3D11::GetCBArrays, std::move(pBuffD3D11Impl), pd3d11Buff); } - __forceinline void SetTexSRV(Uint32 Slot, RefCntAutoPtr&& pTexView) + __forceinline void SetTexSRV(Uint32 CacheOffset, Uint32 ArrayIndex, TBindPoints BindPoints, RefCntAutoPtr&& pTexView) { auto* pd3d11SRV = pTexView ? static_cast(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pTexView), pd3d11SRV); + SetD3D11ResourceInternal(CacheOffset, ArrayIndex, GetSRVCount(), BindPoints, &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pTexView), pd3d11SRV); } - __forceinline void SetBufSRV(Uint32 Slot, RefCntAutoPtr&& pBuffView) + __forceinline void SetBufSRV(Uint32 CacheOffset, Uint32 ArrayIndex, TBindPoints BindPoints, RefCntAutoPtr&& pBuffView) { auto* pd3d11SRV = pBuffView ? static_cast(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetSRVCount(), &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pBuffView), pd3d11SRV); + SetD3D11ResourceInternal(CacheOffset, ArrayIndex, GetSRVCount(), BindPoints, &ShaderResourceCacheD3D11::GetSRVArrays, std::move(pBuffView), pd3d11SRV); } - __forceinline void SetTexUAV(Uint32 Slot, RefCntAutoPtr&& pTexView) + __forceinline void SetTexUAV(Uint32 CacheOffset, Uint32 ArrayIndex, TBindPoints BindPoints, RefCntAutoPtr&& pTexView) { auto* pd3d11UAV = pTexView ? static_cast(pTexView->TextureViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pTexView), pd3d11UAV); + SetD3D11ResourceInternal(CacheOffset, ArrayIndex, GetUAVCount(), BindPoints, &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pTexView), pd3d11UAV); } - __forceinline void SetBufUAV(Uint32 Slot, RefCntAutoPtr&& pBuffView) + __forceinline void SetBufUAV(Uint32 CacheOffset, Uint32 ArrayIndex, TBindPoints BindPoints, RefCntAutoPtr&& pBuffView) { auto* pd3d11UAV = pBuffView ? static_cast(pBuffView->BufferViewD3D11Impl::GetD3D11View()) : nullptr; - SetD3D11ResourceInternal(Slot, GetUAVCount(), &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pBuffView), pd3d11UAV); + SetD3D11ResourceInternal(CacheOffset, ArrayIndex, GetUAVCount(), BindPoints, &ShaderResourceCacheD3D11::GetUAVArrays, std::move(pBuffView), pd3d11UAV); } - __forceinline void SetSampler(Uint32 Slot, SamplerD3D11Impl* pSampler) + __forceinline void SetSampler(Uint32 CacheOffset, Uint32 ArrayIndex, TBindPoints BindPoints, SamplerD3D11Impl* pSampler) { auto* pd3d11Sampler = pSampler ? pSampler->SamplerD3D11Impl::GetD3D11SamplerState() : nullptr; - SetD3D11ResourceInternal(Slot, GetSamplerCount(), &ShaderResourceCacheD3D11::GetSamplerArrays, pSampler, pd3d11Sampler); + SetD3D11ResourceInternal(CacheOffset, ArrayIndex, GetSamplerCount(), BindPoints, &ShaderResourceCacheD3D11::GetSamplerArrays, pSampler, pd3d11Sampler); } - - __forceinline CachedCB& GetCB(Uint32 Slot) + __forceinline CachedCB const& GetCB(Uint32 CacheOffset) const { - VERIFY(Slot < GetCBCount(), "CB slot is out of range"); + VERIFY(CacheOffset < GetCBCount(), "CB slot is out of range"); ShaderResourceCacheD3D11::CachedCB* CBs; ID3D11Buffer** pd3d11CBs; - GetCBArrays(CBs, pd3d11CBs); - return CBs[Slot]; + TBindPointsAndActiveBits* bindPoints; + const_cast(this)->GetCBArrays(CBs, pd3d11CBs, bindPoints); + return CBs[CacheOffset]; } - __forceinline CachedResource& GetSRV(Uint32 Slot) + __forceinline CachedResource const& GetSRV(Uint32 CacheOffset) const { - VERIFY(Slot < GetSRVCount(), "SRV slot is out of range"); + VERIFY(CacheOffset < GetSRVCount(), "SRV slot is out of range"); ShaderResourceCacheD3D11::CachedResource* SRVResources; ID3D11ShaderResourceView** pd3d11SRVs; - GetSRVArrays(SRVResources, pd3d11SRVs); - return SRVResources[Slot]; + TBindPointsAndActiveBits* bindPoints; + const_cast(this)->GetSRVArrays(SRVResources, pd3d11SRVs, bindPoints); + return SRVResources[CacheOffset]; } - __forceinline CachedResource& GetUAV(Uint32 Slot) + __forceinline CachedResource const& GetUAV(Uint32 CacheOffset) const { - VERIFY(Slot < GetUAVCount(), "UAV slot is out of range"); + VERIFY(CacheOffset < GetUAVCount(), "UAV slot is out of range"); ShaderResourceCacheD3D11::CachedResource* UAVResources; ID3D11UnorderedAccessView** pd3d11UAVs; - GetUAVArrays(UAVResources, pd3d11UAVs); - return UAVResources[Slot]; + TBindPointsAndActiveBits* bindPoints; + const_cast(this)->GetUAVArrays(UAVResources, pd3d11UAVs, bindPoints); + return UAVResources[CacheOffset]; } - __forceinline CachedSampler& GetSampler(Uint32 Slot) + __forceinline CachedSampler const& GetSampler(Uint32 CacheOffset) const { - VERIFY(Slot < GetSamplerCount(), "Sampler slot is out of range"); + VERIFY(CacheOffset < GetSamplerCount(), "Sampler slot is out of range"); ShaderResourceCacheD3D11::CachedSampler* Samplers; ID3D11SamplerState** pd3d11Samplers; - GetSamplerArrays(Samplers, pd3d11Samplers); - return Samplers[Slot]; + TBindPointsAndActiveBits* bindPoints; + const_cast(this)->GetSamplerArrays(Samplers, pd3d11Samplers, bindPoints); + return Samplers[CacheOffset]; } - __forceinline bool IsCBBound(Uint32 Slot) const + __forceinline bool IsCBBound(Uint32 CacheOffset) const { - CachedCB* CBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - const_cast(this)->GetCBArrays(CBs, d3d11CBs); - if (Slot < GetCBCount() && d3d11CBs[Slot] != nullptr) + CachedCB const* CBs; + ID3D11Buffer* const* d3d11CBs; + TBindPointsAndActiveBits const* bindPoints; + GetConstCBArrays(CBs, d3d11CBs, bindPoints); + if (CacheOffset < GetCBCount() && d3d11CBs[CacheOffset] != nullptr) { - VERIFY(CBs[Slot].pBuff != nullptr, "No relevant buffer resource"); + VERIFY(CBs[CacheOffset].pBuff != nullptr, "No relevant buffer resource"); return true; } return false; } - __forceinline bool IsSRVBound(Uint32 Slot, bool dbgIsTextureView) const + __forceinline bool IsSRVBound(Uint32 CacheOffset, bool dbgIsTextureView) const { - CachedResource* SRVResources = nullptr; - ID3D11ShaderResourceView** d3d11SRVs = nullptr; - const_cast(this)->GetSRVArrays(SRVResources, d3d11SRVs); - if (Slot < GetSRVCount() && d3d11SRVs[Slot] != nullptr) + CachedResource const* SRVResources; + ID3D11ShaderResourceView* const* d3d11SRVs; + TBindPointsAndActiveBits const* bindPoints; + GetConstSRVArrays(SRVResources, d3d11SRVs, bindPoints); + if (CacheOffset < GetSRVCount() && d3d11SRVs[CacheOffset] != nullptr) { - VERIFY((dbgIsTextureView && SRVResources[Slot].pTexture != nullptr) || (!dbgIsTextureView && SRVResources[Slot].pBuffer != nullptr), + VERIFY((dbgIsTextureView && SRVResources[CacheOffset].pTexture != nullptr) || (!dbgIsTextureView && SRVResources[CacheOffset].pBuffer != nullptr), "No relevant resource"); return true; } return false; } - __forceinline bool IsUAVBound(Uint32 Slot, bool dbgIsTextureView) const + __forceinline bool IsUAVBound(Uint32 CacheOffset, bool dbgIsTextureView) const { - CachedResource* UAVResources = nullptr; - ID3D11UnorderedAccessView** d3d11UAVs = nullptr; - const_cast(this)->GetUAVArrays(UAVResources, d3d11UAVs); - if (Slot < GetUAVCount() && d3d11UAVs[Slot] != nullptr) + CachedResource const* UAVResources; + ID3D11UnorderedAccessView* const* d3d11UAVs; + TBindPointsAndActiveBits const* bindPoints; + GetConstUAVArrays(UAVResources, d3d11UAVs, bindPoints); + if (CacheOffset < GetUAVCount() && d3d11UAVs[CacheOffset] != nullptr) { - VERIFY((dbgIsTextureView && UAVResources[Slot].pTexture != nullptr) || (!dbgIsTextureView && UAVResources[Slot].pBuffer != nullptr), + VERIFY((dbgIsTextureView && UAVResources[CacheOffset].pTexture != nullptr) || (!dbgIsTextureView && UAVResources[CacheOffset].pBuffer != nullptr), "No relevant resource"); return true; } return false; } - __forceinline bool IsSamplerBound(Uint32 Slot) const + __forceinline bool IsSamplerBound(Uint32 CacheOffset) const { - CachedSampler* Samplers = nullptr; - ID3D11SamplerState** d3d11Samplers = nullptr; - const_cast(this)->GetSamplerArrays(Samplers, d3d11Samplers); - if (Slot < GetSamplerCount() && d3d11Samplers[Slot] != nullptr) + CachedSampler const* Samplers; + ID3D11SamplerState* const* d3d11Samplers; + TBindPointsAndActiveBits const* bindPoints; + GetConstSamplerArrays(Samplers, d3d11Samplers, bindPoints); + if (CacheOffset < GetSamplerCount() && d3d11Samplers[CacheOffset] != nullptr) { - VERIFY(Samplers[Slot].pSampler != nullptr, "No relevant sampler"); + VERIFY(Samplers[CacheOffset].pSampler != nullptr, "No relevant sampler"); return true; } return false; } - void dbgVerifyCacheConsistency(); +#ifdef DILIGENT_DEVELOPMENT + void DvpVerifyCacheConsistency(); +#endif // clang-format off - __forceinline Uint32 GetCBCount() const { return (m_SRVOffset - m_CBOffset) / (sizeof(CachedCB) + sizeof(ID3D11Buffer*)); } - __forceinline Uint32 GetSRVCount() const { return (m_SamplerOffset - m_SRVOffset) / (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*)); } - __forceinline Uint32 GetSamplerCount() const { return (m_UAVOffset - m_SamplerOffset) / (sizeof(CachedSampler) + sizeof(ID3D11SamplerState*)); } - __forceinline Uint32 GetUAVCount() const { return (m_MemoryEndOffset - m_UAVOffset) / (sizeof(CachedResource) + sizeof(ID3D11UnorderedAccessView*)); } + __forceinline Uint32 GetCBCount() const { return m_CBCount; } + __forceinline Uint32 GetSRVCount() const { return m_SRVCount; } + __forceinline Uint32 GetSamplerCount() const { return m_SamplerCount; } + __forceinline Uint32 GetUAVCount() const { return m_UAVCount; } // clang-format on - __forceinline void GetCBArrays(CachedCB*& CBs, ID3D11Buffer**& pd3d11CBs) + __forceinline void GetCBArrays(CachedCB*& CBs, ID3D11Buffer**& pd3d11CBs, TBindPointsAndActiveBits*& pBindPoints) { - CBs = reinterpret_cast(m_pResourceData + m_CBOffset); - pd3d11CBs = reinterpret_cast(CBs + GetCBCount()); + VERIFY(alignof(CachedCB) == alignof(ID3D11Buffer*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); + CBs = reinterpret_cast(m_pResourceData + m_CBOffset); + pd3d11CBs = reinterpret_cast(CBs + GetCBCount()); + pBindPoints = reinterpret_cast(pd3d11CBs + GetCBCount()); } - __forceinline void GetSRVArrays(CachedResource*& SRVResources, ID3D11ShaderResourceView**& d3d11SRVs) + __forceinline void GetSRVArrays(CachedResource*& SRVResources, ID3D11ShaderResourceView**& d3d11SRVs, TBindPointsAndActiveBits*& pBindPoints) { + VERIFY(alignof(CachedResource) == alignof(ID3D11ShaderResourceView*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); SRVResources = reinterpret_cast(m_pResourceData + m_SRVOffset); d3d11SRVs = reinterpret_cast(SRVResources + GetSRVCount()); + pBindPoints = reinterpret_cast(d3d11SRVs + GetSRVCount()); } - __forceinline void GetSamplerArrays(CachedSampler*& Samplers, ID3D11SamplerState**& pd3d11Samplers) + __forceinline void GetSamplerArrays(CachedSampler*& Samplers, ID3D11SamplerState**& pd3d11Samplers, TBindPointsAndActiveBits*& pBindPoints) { + VERIFY(alignof(CachedSampler) == alignof(ID3D11SamplerState*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); Samplers = reinterpret_cast(m_pResourceData + m_SamplerOffset); pd3d11Samplers = reinterpret_cast(Samplers + GetSamplerCount()); + pBindPoints = reinterpret_cast(pd3d11Samplers + GetSamplerCount()); } - __forceinline void GetUAVArrays(CachedResource*& UAVResources, ID3D11UnorderedAccessView**& pd3d11UAVs) + __forceinline void GetUAVArrays(CachedResource*& UAVResources, ID3D11UnorderedAccessView**& pd3d11UAVs, TBindPointsAndActiveBits*& pBindPoints) { + VERIFY(alignof(CachedResource) == alignof(ID3D11UnorderedAccessView*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); UAVResources = reinterpret_cast(m_pResourceData + m_UAVOffset); pd3d11UAVs = reinterpret_cast(UAVResources + GetUAVCount()); + pBindPoints = reinterpret_cast(pd3d11UAVs + GetUAVCount()); + } + + __forceinline void GetConstCBArrays(CachedCB const*& CBs, ID3D11Buffer* const*& pd3d11CBs, TBindPointsAndActiveBits const*& pBindPoints) const + { + VERIFY(alignof(CachedCB) == alignof(ID3D11Buffer*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); + CBs = reinterpret_cast(m_pResourceData + m_CBOffset); + pd3d11CBs = reinterpret_cast(CBs + GetCBCount()); + pBindPoints = reinterpret_cast(pd3d11CBs + GetCBCount()); + } + + __forceinline void GetConstSRVArrays(CachedResource const*& SRVResources, ID3D11ShaderResourceView* const*& d3d11SRVs, TBindPointsAndActiveBits const*& pBindPoints) const + { + VERIFY(alignof(CachedResource) == alignof(ID3D11ShaderResourceView*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); + SRVResources = reinterpret_cast(m_pResourceData + m_SRVOffset); + d3d11SRVs = reinterpret_cast(SRVResources + GetSRVCount()); + pBindPoints = reinterpret_cast(d3d11SRVs + GetSRVCount()); + } + + __forceinline void GetConstSamplerArrays(CachedSampler const*& Samplers, ID3D11SamplerState* const*& pd3d11Samplers, TBindPointsAndActiveBits const*& pBindPoints) const + { + VERIFY(alignof(CachedSampler) == alignof(ID3D11SamplerState*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); + Samplers = reinterpret_cast(m_pResourceData + m_SamplerOffset); + pd3d11Samplers = reinterpret_cast(Samplers + GetSamplerCount()); + pBindPoints = reinterpret_cast(pd3d11Samplers + GetSamplerCount()); + } + + __forceinline void GetConstUAVArrays(CachedResource const*& UAVResources, ID3D11UnorderedAccessView* const*& pd3d11UAVs, TBindPointsAndActiveBits const*& pBindPoints) const + { + VERIFY(alignof(CachedResource) == alignof(ID3D11UnorderedAccessView*), "Alignment mismatch, pointer to D3D11 resource may not be properly aligned"); + UAVResources = reinterpret_cast(m_pResourceData + m_UAVOffset); + pd3d11UAVs = reinterpret_cast(UAVResources + GetUAVCount()); + pBindPoints = reinterpret_cast(pd3d11UAVs + GetUAVCount()); } __forceinline bool IsInitialized() const { - return m_MemoryEndOffset != InvalidResourceOffset; + return m_UAVOffset != InvalidResourceOffset; } + ResourceCacheContentType GetContentType() const { return m_ContentType; } + private: template - __forceinline void SetD3D11ResourceInternal(Uint32 Slot, Uint32 Size, TGetResourceArraysFunc GetArrays, TSrcResourceType&& pResource, TD3D11ResourceType* pd3d11Resource) + __forceinline void SetD3D11ResourceInternal(Uint32 CacheOffset, Uint32 ArrayIndex, Uint32 Size, TBindPoints SrcBindPoints, TGetResourceArraysFunc GetArrays, TSrcResourceType&& pResource, TD3D11ResourceType* pd3d11Resource) { - VERIFY(Slot < Size, "Resource cache is not big enough"); + CacheOffset += ArrayIndex; + + TBindPointsAndActiveBits BindPointsAndActiveBits; + auto& ActiveBits = BindPointsAndActiveBits[0]; + auto* BindPoints = &BindPointsAndActiveBits[1]; + + ActiveBits = 0; + for (Uint32 i = 0; i < SrcBindPoints.size(); ++i) + { + if (SrcBindPoints[i] != InvalidBindPoint) + { + auto BindPoint = SrcBindPoints[i] + ArrayIndex; + VERIFY_EXPR(BindPoint < InvalidBindPoint); + BindPoints[i] = static_cast(BindPoint); + ActiveBits |= static_cast(1u << i); + } + else + { + BindPoints[i] = InvalidBindPoint; + } + } + + VERIFY(CacheOffset < Size, "Resource cache is not big enough"); VERIFY(pResource != nullptr && pd3d11Resource != nullptr || pResource == nullptr && pd3d11Resource == nullptr, "Resource and D3D11 resource must be set/unset atomically"); - TCachedResourceType* Resources; - TD3D11ResourceType** d3d11ResArr; - (this->*GetArrays)(Resources, d3d11ResArr); - Resources[Slot].Set(std::forward(pResource)); - d3d11ResArr[Slot] = pd3d11Resource; + TCachedResourceType* Resources; + TD3D11ResourceType** d3d11ResArr; + TBindPointsAndActiveBits* bindPoints; + (this->*GetArrays)(Resources, d3d11ResArr, bindPoints); + Resources[CacheOffset].Set(std::forward(pResource)); + bindPoints[CacheOffset] = BindPointsAndActiveBits; + d3d11ResArr[CacheOffset] = pd3d11Resource; } - static constexpr const Uint16 InvalidResourceOffset = 0xFFFF; - // Resource limits in D3D11: - // Max CB count: 14 - // Max SRV count: 128 - // Max Sampler count: 16 - // Max UAV count: 8 - static constexpr const Uint16 m_CBOffset = 0; - Uint16 m_SRVOffset = InvalidResourceOffset; - Uint16 m_SamplerOffset = InvalidResourceOffset; - Uint16 m_UAVOffset = InvalidResourceOffset; - Uint16 m_MemoryEndOffset = InvalidResourceOffset; - - Uint8* m_pResourceData = nullptr; - -#ifdef DILIGENT_DEBUG - IMemoryAllocator* m_pdbgMemoryAllocator = nullptr; + template + void ProcessResources(THandleResource HandleResource); + + // Transitions resource to the shader resource state required by Type member. + __forceinline void TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedCB* CBs, ID3D11Buffer** pd3d11CBs); + __forceinline void TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedResource* SRVResources, ID3D11ShaderResourceView** d3d11SRVs); + __forceinline void TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedSampler* Samplers, ID3D11SamplerState** pd3d11Samplers); + __forceinline void TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedResource* UAVResources, ID3D11UnorderedAccessView** pd3d11UAVs); + +#ifdef DILIGENT_DEVELOPMENT + // Verifies that resource is in correct shader resource state required by Type member. + void DvpVerifyResourceState(DeviceContextD3D11Impl& Ctx, Uint32 Count, const CachedCB* CBs, ID3D11Buffer**); + void DvpVerifyResourceState(DeviceContextD3D11Impl& Ctx, Uint32 Count, const CachedResource* SRVResources, ID3D11ShaderResourceView**); + void DvpVerifyResourceState(DeviceContextD3D11Impl& Ctx, Uint32 Count, const CachedSampler* Samplers, ID3D11SamplerState**); + void DvpVerifyResourceState(DeviceContextD3D11Impl& Ctx, Uint32 Count, const CachedResource* UAVResources, ID3D11UnorderedAccessView**); #endif + +private: + using OffsetType = Uint16; + + static constexpr size_t MaxAlignment = std::max(std::max(std::max(alignof(CachedCB), alignof(CachedResource)), + std::max(alignof(CachedSampler), alignof(TBindPoints))), + std::max(std::max(alignof(ID3D11Buffer*), alignof(ID3D11ShaderResourceView*)), + std::max(alignof(ID3D11SamplerState*), alignof(ID3D11UnorderedAccessView*)))); + + static constexpr OffsetType InvalidResourceOffset = std::numeric_limits::max(); + + static constexpr OffsetType m_CBOffset = 0; + OffsetType m_SRVOffset = InvalidResourceOffset; + OffsetType m_SamplerOffset = InvalidResourceOffset; + OffsetType m_UAVOffset = InvalidResourceOffset; + + static constexpr Uint32 _CBCountBits = 7; + static constexpr Uint32 _SVCountBits = 10; + static constexpr Uint32 _SampCountBits = 7; + static constexpr Uint32 _UAVCountBits = 4; + + // clang-format off + static_assert((1U << _CBCountBits) >= (D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT * NumShaderTypes), "Number of constant buffers is too small"); + static_assert((1U << _SVCountBits) >= (D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT * NumShaderTypes), "Number of shader resources is too small"); + static_assert((1U << _SampCountBits) >= (D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT * NumShaderTypes), "Number of samplers is too small"); + static_assert((1U << _UAVCountBits) >= D3D11_PS_CS_UAV_REGISTER_COUNT, "Number of UAVs is too small"); + + Uint32 m_CBCount : _CBCountBits; + Uint32 m_SRVCount : _SVCountBits; + Uint32 m_SamplerCount : _SampCountBits; + Uint32 m_UAVCount : _UAVCountBits; + // clang-format on + + // Indicates what types of resources are stored in the cache + const ResourceCacheContentType m_ContentType; + + Uint8* m_pResourceData = nullptr; + IMemoryAllocator* m_pAllocator = nullptr; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp deleted file mode 100644 index fcbe994c..00000000 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright 2019-2021 Diligent Graphics LLC - * Copyright 2015-2019 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#pragma once - -/// \file -/// Declaration of Diligent::ShaderResourceLayoutD3D11 class - -#include "ShaderResources.hpp" -#include "ShaderBase.hpp" -#include "ShaderResourceCacheD3D11.hpp" -#include "EngineD3D11Defines.h" -#include "STDAllocator.hpp" -#include "ShaderVariableD3DBase.hpp" -#include "ShaderResourcesD3D11.hpp" - -namespace Diligent -{ - -/// Diligent::ShaderResourceLayoutD3D11 class -/// http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-layout/ -// sizeof(ShaderResourceLayoutD3D11) == 64 (x64) -class ShaderResourceLayoutD3D11 -{ -public: - ShaderResourceLayoutD3D11(IObject& Owner, - ShaderResourceCacheD3D11& ResourceCache) noexcept : - m_Owner{Owner}, - m_ResourceCache{ResourceCache} - { - } - - void Initialize(std::shared_ptr pSrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, - Uint32 NumVarTypes, - IMemoryAllocator& ResCacheDataAllocator, - IMemoryAllocator& ResLayoutDataAllocator); - ~ShaderResourceLayoutD3D11(); - - // clang-format off - // No copies, only moves are allowed - ShaderResourceLayoutD3D11 (const ShaderResourceLayoutD3D11&) = delete; - ShaderResourceLayoutD3D11& operator = (const ShaderResourceLayoutD3D11&) = delete; - ShaderResourceLayoutD3D11 ( ShaderResourceLayoutD3D11&&) = default; - ShaderResourceLayoutD3D11& operator = ( ShaderResourceLayoutD3D11&&) = delete; - // clang-format on - - static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes) noexcept; - - void CopyResources(ShaderResourceCacheD3D11& DstCache) const; - - using ShaderVariableD3D11Base = ShaderVariableD3DBase; - - struct ConstBuffBindInfo final : ShaderVariableD3D11Base - { - ConstBuffBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, - Uint32 FirstElement, - Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsCBBound(m_Attribs.BindPoint + ArrayIndex); - } - }; - - struct TexSRVBindInfo final : ShaderVariableD3D11Base - { - TexSRVBindInfo(const D3DShaderResourceAttribs& _TextureAttribs, - Uint32 _SamplerIndex, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, _TextureAttribs, VariableType}, - SamplerIndex{_SamplerIndex} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, - Uint32 FirstElement, - Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsSRVBound(m_Attribs.BindPoint + ArrayIndex, true); - } - - - bool ValidSamplerAssigned() const { return SamplerIndex != InvalidSamplerIndex; } - - static constexpr Uint32 InvalidSamplerIndex = static_cast(-1); - const Uint32 SamplerIndex; - }; - - struct TexUAVBindInfo final : ShaderVariableD3D11Base - { - TexUAVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base(ParentResLayout, ResourceAttribs, VariableType) - {} - - // Provide non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, - Uint32 FirstElement, - Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - __forceinline virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsUAVBound(m_Attribs.BindPoint + ArrayIndex, true); - } - }; - - struct BuffUAVBindInfo final : ShaderVariableD3D11Base - { - BuffUAVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, - Uint32 FirstElement, - Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsUAVBound(m_Attribs.BindPoint + ArrayIndex, false); - } - }; - - struct BuffSRVBindInfo final : ShaderVariableD3D11Base - { - BuffSRVBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, - Uint32 FirstElement, - Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsSRVBound(m_Attribs.BindPoint + ArrayIndex, false); - } - }; - - struct SamplerBindInfo final : ShaderVariableD3D11Base - { - SamplerBindInfo(const D3DShaderResourceAttribs& ResourceAttribs, - ShaderResourceLayoutD3D11& ParentResLayout, - SHADER_RESOURCE_VARIABLE_TYPE VariableType) : - ShaderVariableD3D11Base{ParentResLayout, ResourceAttribs, VariableType} - {} - - // Non-virtual function - __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); - - virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final { BindResource(pObject, 0); } - - virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, - Uint32 FirstElement, - Uint32 NumElements) override final - { - VerifyAndCorrectSetArrayArguments(m_Attribs.Name, m_Attribs.BindCount, FirstElement, NumElements); - for (Uint32 elem = 0; elem < NumElements; ++elem) - BindResource(ppObjects[elem], FirstElement + elem); - } - - virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final - { - VERIFY_EXPR(ArrayIndex < m_Attribs.BindCount); - return m_ParentResLayout.m_ResourceCache.IsSamplerBound(m_Attribs.BindPoint + ArrayIndex); - } - }; - - // dbgResourceCache is only used for sanity check and as a remainder that the resource cache must be alive - // while Layout is alive - void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags, const ShaderResourceCacheD3D11& dbgResourceCache); - -#ifdef DILIGENT_DEVELOPMENT - bool dvpVerifyBindings() const; -#endif - - IShaderResourceVariable* GetShaderVariable(const Char* Name); - IShaderResourceVariable* GetShaderVariable(Uint32 Index); - __forceinline SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); } - - IObject& GetOwner() { return m_Owner; } - - Uint32 GetVariableIndex(const ShaderVariableD3D11Base& Variable) const; - Uint32 GetTotalResourceCount() const - { - auto ResourceCount = GetNumCBs() + GetNumTexSRVs() + GetNumTexUAVs() + GetNumBufUAVs() + GetNumBufSRVs(); - // Do not expose sampler variables when using combined texture samplers - if (!m_pResources->IsUsingCombinedTextureSamplers()) - ResourceCount += GetNumSamplers(); - return ResourceCount; - } - - // clang-format off - Uint32 GetNumCBs() const { return (m_TexSRVsOffset - 0 ) / sizeof(ConstBuffBindInfo);} - Uint32 GetNumTexSRVs() const { return (m_TexUAVsOffset - m_TexSRVsOffset ) / sizeof(TexSRVBindInfo); } - Uint32 GetNumTexUAVs() const { return (m_BuffSRVsOffset - m_TexUAVsOffset ) / sizeof(TexUAVBindInfo) ; } - Uint32 GetNumBufSRVs() const { return (m_BuffUAVsOffset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo); } - Uint32 GetNumBufUAVs() const { return (m_SamplerOffset - m_BuffUAVsOffset) / sizeof(BuffUAVBindInfo); } - Uint32 GetNumSamplers() const { return (m_MemorySize - m_SamplerOffset ) / sizeof(SamplerBindInfo); } - - template Uint32 GetNumResources()const; - template<> Uint32 GetNumResources() const { return GetNumCBs(); } - template<> Uint32 GetNumResources () const { return GetNumTexSRVs(); } - template<> Uint32 GetNumResources () const { return GetNumTexUAVs(); } - template<> Uint32 GetNumResources () const { return GetNumBufSRVs(); } - template<> Uint32 GetNumResources () const { return GetNumBufUAVs(); } - template<> Uint32 GetNumResources () const { return GetNumSamplers(); } - // clang-format on - - const Char* GetShaderName() const - { - return m_pResources->GetShaderName(); - } - -private: - // clang-format off - -/* 0 */ IObject& m_Owner; -/* 8 */ std::shared_ptr m_pResources; - - // No need to use shared pointer, as the resource cache is either part of the same - // ShaderD3D11Impl object, or ShaderResourceBindingD3D11Impl object -/*24*/ ShaderResourceCacheD3D11& m_ResourceCache; - -/*32*/ std::unique_ptr > m_ResourceBuffer; - - // Offsets in bytes - using OffsetType = Uint16; -/*48*/ OffsetType m_TexSRVsOffset = 0; -/*50*/ OffsetType m_TexUAVsOffset = 0; -/*52*/ OffsetType m_BuffSRVsOffset = 0; -/*54*/ OffsetType m_BuffUAVsOffset = 0; -/*56*/ OffsetType m_SamplerOffset = 0; -/*58*/ OffsetType m_MemorySize = 0; -/*60 - 64*/ -/*64*/ // End of data - - - template OffsetType GetResourceOffset()const; - template<> OffsetType GetResourceOffset() const { return 0; } - template<> OffsetType GetResourceOffset () const { return m_TexSRVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_TexUAVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_BuffSRVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_BuffUAVsOffset; } - template<> OffsetType GetResourceOffset () const { return m_SamplerOffset; } - - // clang-format on - - template - ResourceType& GetResource(Uint32 ResIndex) - { - VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources() - 1, ")"); - auto Offset = GetResourceOffset(); - return reinterpret_cast(reinterpret_cast(m_ResourceBuffer.get()) + Offset)[ResIndex]; - } - - template - const ResourceType& GetConstResource(Uint32 ResIndex) const - { - VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") exceeds max allowed value (", GetNumResources() - 1, ")"); - auto Offset = GetResourceOffset(); - return reinterpret_cast(reinterpret_cast(m_ResourceBuffer.get()) + Offset)[ResIndex]; - } - - template - IShaderResourceVariable* GetResourceByName(const Char* Name); - - template - void HandleResources(THandleCB HandleCB, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV, - THandleSampler HandleSampler) - { - for (Uint32 cb = 0; cb < GetNumResources(); ++cb) - HandleCB(GetResource(cb)); - - for (Uint32 t = 0; t < GetNumResources(); ++t) - HandleTexSRV(GetResource(t)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleTexUAV(GetResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleBufSRV(GetResource(s)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleBufUAV(GetResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleSampler(GetResource(s)); - } - - template - void HandleConstResources(THandleCB HandleCB, - THandleTexSRV HandleTexSRV, - THandleTexUAV HandleTexUAV, - THandleBufSRV HandleBufSRV, - THandleBufUAV HandleBufUAV, - THandleSampler HandleSampler) const - { - for (Uint32 cb = 0; cb < GetNumResources(); ++cb) - HandleCB(GetConstResource(cb)); - - for (Uint32 t = 0; t < GetNumResources(); ++t) - HandleTexSRV(GetConstResource(t)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleTexUAV(GetConstResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleBufSRV(GetConstResource(s)); - - for (Uint32 u = 0; u < GetNumResources(); ++u) - HandleBufUAV(GetConstResource(u)); - - for (Uint32 s = 0; s < GetNumResources(); ++s) - HandleSampler(GetConstResource(s)); - } - - friend class ShaderVariableIndexLocator; - friend class ShaderVariableLocator; -}; - -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderVariableManagerD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderVariableManagerD3D11.hpp new file mode 100644 index 00000000..d7febdb0 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/include/ShaderVariableManagerD3D11.hpp @@ -0,0 +1,496 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#pragma once + +/// \file +/// Declaration of Diligent::ShaderVariableManagerD3D11 class + +#include "ShaderResources.hpp" +#include "ShaderBase.hpp" +#include "ShaderResourceVariableBase.hpp" +#include "ShaderVariableD3D.hpp" +#include "ShaderResourcesD3D11.hpp" +#include "ShaderResourceVariableD3D.h" +#include "PipelineResourceAttribsD3D11.hpp" +#include "ShaderResourceCacheD3D11.hpp" + +namespace Diligent +{ + +/// Diligent::ShaderVariableManagerD3D11 class +// sizeof(ShaderVariableManagerD3D11) == AZ TODO (Release, x64) +class ShaderVariableManagerD3D11 +{ +public: + ShaderVariableManagerD3D11(IObject& Owner, + ShaderResourceCacheD3D11& ResourceCache) noexcept : + m_Owner{Owner}, + m_ResourceCache{ResourceCache} + { + } + + ~ShaderVariableManagerD3D11(); + + void Destroy(IMemoryAllocator& Allocator); + + // clang-format off + // No copies, only moves are allowed + ShaderVariableManagerD3D11 (const ShaderVariableManagerD3D11&) = delete; + ShaderVariableManagerD3D11& operator = (const ShaderVariableManagerD3D11&) = delete; + ShaderVariableManagerD3D11 ( ShaderVariableManagerD3D11&&) = default; + ShaderVariableManagerD3D11& operator = ( ShaderVariableManagerD3D11&&) = delete; + // clang-format on + + void Initialize(const PipelineResourceSignatureD3D11Impl& Signature, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + SHADER_TYPE ShaderType); + + static size_t GetRequiredMemorySize(const PipelineResourceSignatureD3D11Impl& Signature, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + SHADER_TYPE ShaderType); + + using ResourceAttribs = PipelineResourceAttribsD3D11; + + const PipelineResourceDesc& GetResourceDesc(Uint32 Index) const; + const ResourceAttribs& GetAttribs(Uint32 Index) const; + + + struct ShaderVariableD3D11Base : ShaderVariableBase + { + public: + ShaderVariableD3D11Base(ShaderVariableManagerD3D11& ParentLayout, Uint32 ResIndex) : + ShaderVariableBase{ParentLayout}, + m_ResIndex{ResIndex} + {} + + // clang-format off + ShaderVariableD3D11Base (const ShaderVariableD3D11Base&) = delete; + ShaderVariableD3D11Base ( ShaderVariableD3D11Base&&) = delete; + ShaderVariableD3D11Base& operator= (const ShaderVariableD3D11Base&) = delete; + ShaderVariableD3D11Base& operator= ( ShaderVariableD3D11Base&&) = delete; + // clang-format on + + const PipelineResourceDesc& GetDesc() const { return m_ParentManager.GetResourceDesc(m_ResIndex); } + const ResourceAttribs& GetAttribs() const { return m_ParentManager.GetAttribs(m_ResIndex); } + + virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final + { + if (ppInterface == nullptr) + return; + + *ppInterface = nullptr; + if (IID == IID_ShaderResourceVariableD3D || IID == IID_ShaderResourceVariable || IID == IID_Unknown) + { + *ppInterface = this; + (*ppInterface)->AddRef(); + } + } + + virtual SHADER_RESOURCE_VARIABLE_TYPE DILIGENT_CALL_TYPE GetType() const override final + { + return GetDesc().VarType; + } + + virtual void DILIGENT_CALL_TYPE GetResourceDesc(ShaderResourceDesc& ResourceDesc) const override final + { + const auto& Desc = GetDesc(); + ResourceDesc.Name = Desc.Name; + ResourceDesc.Type = Desc.ResourceType; + ResourceDesc.ArraySize = Desc.ArraySize; + } + + virtual Uint32 DILIGENT_CALL_TYPE GetIndex() const override final + { + return m_ParentManager.GetVariableIndex(*this); + } + + virtual void DILIGENT_CALL_TYPE GetHLSLResourceDesc(HLSLShaderResourceDesc& HLSLResDesc) const override final + { + // AZ TODO + } + + private: + const Uint32 m_ResIndex; + }; + + struct ConstBuffBindInfo final : ShaderVariableD3D11Base + { + ConstBuffBindInfo(ShaderVariableManagerD3D11& ParentLayout, Uint32 ResIndex) : + ShaderVariableD3D11Base{ParentLayout, ResIndex} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObj, Uint32 ArrayIndex); + + virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final + { + BindResource(pObject, 0); + } + + virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, + Uint32 FirstElement, + Uint32 NumElements) override final + { + const auto& Desc = GetDesc(); + VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); + return m_ParentManager.m_ResourceCache.IsCBBound(GetAttribs().CacheOffset + ArrayIndex); + } + }; + + struct TexSRVBindInfo final : ShaderVariableD3D11Base + { + TexSRVBindInfo(ShaderVariableManagerD3D11& ParentLayout, Uint32 ResIndex) : + ShaderVariableD3D11Base{ParentLayout, ResIndex} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final + { + BindResource(pObject, 0); + } + + virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, + Uint32 FirstElement, + Uint32 NumElements) override final + { + const auto& Desc = GetDesc(); + VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); + return m_ParentManager.m_ResourceCache.IsSRVBound(GetAttribs().CacheOffset + ArrayIndex, true); + } + }; + + struct TexUAVBindInfo final : ShaderVariableD3D11Base + { + TexUAVBindInfo(ShaderVariableManagerD3D11& ParentLayout, Uint32 ResIndex) : + ShaderVariableD3D11Base{ParentLayout, ResIndex} + {} + + // Provide non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final + { + BindResource(pObject, 0); + } + + virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, + Uint32 FirstElement, + Uint32 NumElements) override final + { + const auto& Desc = GetDesc(); + VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + __forceinline virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); + return m_ParentManager.m_ResourceCache.IsUAVBound(GetAttribs().CacheOffset + ArrayIndex, true); + } + }; + + struct BuffUAVBindInfo final : ShaderVariableD3D11Base + { + BuffUAVBindInfo(ShaderVariableManagerD3D11& ParentLayout, Uint32 ResIndex) : + ShaderVariableD3D11Base{ParentLayout, ResIndex} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final + { + BindResource(pObject, 0); + } + + virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, + Uint32 FirstElement, + Uint32 NumElements) override final + { + const auto& Desc = GetDesc(); + VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); + return m_ParentManager.m_ResourceCache.IsUAVBound(GetAttribs().CacheOffset + ArrayIndex, false); + } + }; + + struct BuffSRVBindInfo final : ShaderVariableD3D11Base + { + BuffSRVBindInfo(ShaderVariableManagerD3D11& ParentLayout, Uint32 ResIndex) : + ShaderVariableD3D11Base{ParentLayout, ResIndex} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final + { + BindResource(pObject, 0); + } + + virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, + Uint32 FirstElement, + Uint32 NumElements) override final + { + const auto& Desc = GetDesc(); + VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); + return m_ParentManager.m_ResourceCache.IsSRVBound(GetAttribs().CacheOffset + ArrayIndex, false); + } + }; + + struct SamplerBindInfo final : ShaderVariableD3D11Base + { + SamplerBindInfo(ShaderVariableManagerD3D11& ParentLayout, Uint32 ResIndex) : + ShaderVariableD3D11Base{ParentLayout, ResIndex} + {} + + // Non-virtual function + __forceinline void BindResource(IDeviceObject* pObject, Uint32 ArrayIndex); + + virtual void DILIGENT_CALL_TYPE Set(IDeviceObject* pObject) override final + { + BindResource(pObject, 0); + } + + virtual void DILIGENT_CALL_TYPE SetArray(IDeviceObject* const* ppObjects, + Uint32 FirstElement, + Uint32 NumElements) override final + { + const auto& Desc = GetDesc(); + VerifyAndCorrectSetArrayArguments(Desc.Name, Desc.ArraySize, FirstElement, NumElements); + for (Uint32 elem = 0; elem < NumElements; ++elem) + BindResource(ppObjects[elem], FirstElement + elem); + } + + virtual bool DILIGENT_CALL_TYPE IsBound(Uint32 ArrayIndex) const override final + { + VERIFY_EXPR(ArrayIndex < GetDesc().ArraySize); + return m_ParentManager.m_ResourceCache.IsSamplerBound(GetAttribs().CacheOffset + ArrayIndex); + } + }; + + void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags); + +#ifdef DILIGENT_DEVELOPMENT + bool dvpVerifyBindings() const; +#endif + + IShaderResourceVariable* GetVariable(const Char* Name) const; + IShaderResourceVariable* GetVariable(Uint32 Index) const; + + IObject& GetOwner() { return m_Owner; } + + Uint32 GetVariableCount() const; + + Uint32 GetVariableIndex(const ShaderVariableD3D11Base& Variable) const; + + // clang-format off + Uint32 GetNumCBs() const { return (m_TexSRVsOffset - 0 ) / sizeof(ConstBuffBindInfo);} + Uint32 GetNumTexSRVs() const { return (m_TexUAVsOffset - m_TexSRVsOffset ) / sizeof(TexSRVBindInfo); } + Uint32 GetNumTexUAVs() const { return (m_BuffSRVsOffset - m_TexUAVsOffset ) / sizeof(TexUAVBindInfo) ; } + Uint32 GetNumBufSRVs() const { return (m_BuffUAVsOffset - m_BuffSRVsOffset) / sizeof(BuffSRVBindInfo); } + Uint32 GetNumBufUAVs() const { return (m_SamplerOffset - m_BuffUAVsOffset) / sizeof(BuffUAVBindInfo); } + Uint32 GetNumSamplers() const { return (m_MemorySize - m_SamplerOffset ) / sizeof(SamplerBindInfo); } + + template Uint32 GetNumResources()const; + template<> Uint32 GetNumResources() const { return GetNumCBs(); } + template<> Uint32 GetNumResources () const { return GetNumTexSRVs(); } + template<> Uint32 GetNumResources () const { return GetNumTexUAVs(); } + template<> Uint32 GetNumResources () const { return GetNumBufSRVs(); } + template<> Uint32 GetNumResources () const { return GetNumBufUAVs(); } + template<> Uint32 GetNumResources () const { return GetNumSamplers(); } + // clang-format on + +private: + static void CountResources(const PipelineResourceSignatureD3D11Impl& Signature, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + SHADER_TYPE ShaderType, + D3DShaderResourceCounters& Counters); + + template + static void ProcessSignatureResources(const PipelineResourceSignatureD3D11Impl& Signature, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + SHADER_TYPE ShaderType, + HandlerType Handler); + + // clang-format off + using OffsetType = Uint16; + template OffsetType GetResourceOffset()const; + template<> OffsetType GetResourceOffset() const { return 0; } + template<> OffsetType GetResourceOffset () const { return m_TexSRVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_TexUAVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_BuffSRVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_BuffUAVsOffset; } + template<> OffsetType GetResourceOffset () const { return m_SamplerOffset; } + // clang-format on + + template + ResourceType& GetResource(Uint32 ResIndex) const + { + VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") must be less than (", GetNumResources(), ")"); + auto Offset = GetResourceOffset(); + return reinterpret_cast(reinterpret_cast(m_ResourceBuffer) + Offset)[ResIndex]; + } + + template + const ResourceType& GetConstResource(Uint32 ResIndex) const + { + VERIFY(ResIndex < GetNumResources(), "Resource index (", ResIndex, ") must be less than (", GetNumResources(), ")"); + auto Offset = GetResourceOffset(); + return reinterpret_cast(reinterpret_cast(m_ResourceBuffer) + Offset)[ResIndex]; + } + + template + IShaderResourceVariable* GetResourceByName(const Char* Name) const; + + template + void HandleResources(THandleCB HandleCB, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV, + THandleSampler HandleSampler) + { + for (Uint32 cb = 0; cb < GetNumResources(); ++cb) + HandleCB(GetResource(cb)); + + for (Uint32 t = 0; t < GetNumResources(); ++t) + HandleTexSRV(GetResource(t)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleTexUAV(GetResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleBufSRV(GetResource(s)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleBufUAV(GetResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleSampler(GetResource(s)); + } + + template + void HandleConstResources(THandleCB HandleCB, + THandleTexSRV HandleTexSRV, + THandleTexUAV HandleTexUAV, + THandleBufSRV HandleBufSRV, + THandleBufUAV HandleBufUAV, + THandleSampler HandleSampler) const + { + for (Uint32 cb = 0; cb < GetNumResources(); ++cb) + HandleCB(GetConstResource(cb)); + + for (Uint32 t = 0; t < GetNumResources(); ++t) + HandleTexSRV(GetConstResource(t)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleTexUAV(GetConstResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleBufSRV(GetConstResource(s)); + + for (Uint32 u = 0; u < GetNumResources(); ++u) + HandleBufUAV(GetConstResource(u)); + + for (Uint32 s = 0; s < GetNumResources(); ++s) + HandleSampler(GetConstResource(s)); + } + + friend class ShaderVariableIndexLocator; + friend class ShaderVariableLocator; + +private: + PipelineResourceSignatureD3D11Impl const* m_pSignature = nullptr; + + IObject& m_Owner; + + // No need to use shared pointer, as the resource cache is either part of the same + // ShaderD3D11Impl object, or ShaderResourceBindingD3D11Impl object + ShaderResourceCacheD3D11& m_ResourceCache; + void* m_ResourceBuffer = nullptr; + + // Offsets in bytes + OffsetType m_TexSRVsOffset = 0; + OffsetType m_TexUAVsOffset = 0; + OffsetType m_BuffSRVsOffset = 0; + OffsetType m_BuffUAVsOffset = 0; + OffsetType m_SamplerOffset = 0; + OffsetType m_MemorySize = 0; + +#ifdef DILIGENT_DEBUG + IMemoryAllocator* m_pDbgAllocator = nullptr; +#endif +}; + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp index d1d882c2..54cc7031 100644 --- a/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp +++ b/Graphics/GraphicsEngineD3D11/include/TextureBaseD3D11.hpp @@ -42,10 +42,10 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Base implementation of a texture object in Direct3D11 backend. -class TextureBaseD3D11 : public TextureBase +class TextureBaseD3D11 : public TextureBase { public: - using TTextureBase = TextureBase; + using TTextureBase = TextureBase; using ViewImplType = TextureViewD3D11Impl; TextureBaseD3D11(IReferenceCounters* pRefCounters, diff --git a/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp index bfb2e73e..4bb89268 100644 --- a/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/TextureViewD3D11Impl.hpp @@ -41,10 +41,10 @@ namespace Diligent class FixedBlockMemoryAllocator; /// Texture view implementation in Direct3D11 backend. -class TextureViewD3D11Impl final : public TextureViewBase +class TextureViewD3D11Impl final : public TextureViewBase { public: - using TTextureViewBase = TextureViewBase; + using TTextureViewBase = TextureViewBase; TextureViewD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pDevice, diff --git a/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp index 361dfc6d..8844b8d8 100644 --- a/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/BufferViewD3D11Impl.cpp @@ -27,6 +27,7 @@ #include "pch.h" #include "BufferViewD3D11Impl.hpp" +#include "BufferD3D11Impl.hpp" namespace Diligent { @@ -34,7 +35,7 @@ namespace Diligent BufferViewD3D11Impl::BufferViewD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pDevice, const BufferViewDesc& ViewDesc, - IBuffer* pBuffer, + BufferD3D11Impl* pBuffer, ID3D11View* pD3D11View, bool bIsDefaultView) : // clang-format off diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index 7c1ae564..a517a59e 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -133,6 +133,58 @@ void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState) { UNEXPECTED(GetPipelineTypeString(Desc.PipelineType), " pipelines '", Desc.Name, "' are not supported in OpenGL"); } + + const auto SignCount = m_pPipelineState->GetResourceSignatureCount(); + const auto ActiveStages = m_pPipelineState->GetActiveShaderStages(); + + m_BindInfo.ActiveSRBMask = 0; + for (Uint32 s = 0; s < SignCount; ++s) + { + const auto* pLayoutSign = m_pPipelineState->GetResourceSignature(s); + if (pLayoutSign == nullptr || pLayoutSign->GetTotalResourceCount() == 0) + continue; + + m_BindInfo.ActiveSRBMask |= (1u << s); + } + + // Reset states if new pipeline have new shader stages. + if ((m_BindInfo.ActiveStages & ActiveStages) != ActiveStages) + { + m_BindInfo.ActiveStages = ActiveStages; + m_BindInfo.StaleSRBMask = 0xFF; + } + +#ifdef DILIGENT_DEVELOPMENT + // Find the first incompatible shader resource bindings + Uint32 sign = 0; + for (; sign < SignCount; ++sign) + { + const auto* pLayoutSign = m_pPipelineState->GetResourceSignature(sign); + const auto* pSRBSign = m_BindInfo.SRBs[sign] != nullptr ? m_BindInfo.SRBs[sign]->GetSignature() : nullptr; + + if ((pLayoutSign == nullptr || pLayoutSign->GetTotalResourceCount() == 0) != (pSRBSign == nullptr || pSRBSign->GetTotalResourceCount() == 0)) + { + // One signature is null or empty while the other is not - SRB is not compatible with the layout. + break; + } + + if (pLayoutSign != nullptr && pSRBSign != nullptr && pLayoutSign->IsIncompatibleWith(*pSRBSign)) + { + // Signatures are incompatible + break; + } + } + + // Unbind incompatible SRB and SRB with a higher binding index. + // This is the same behavior that used in Vulkan backend. + for (; sign < SignCount; ++sign) + { + m_BindInfo.SRBs[sign] = nullptr; + m_BindInfo.ClearStaleSRBBit(sign); + } + + m_BindInfo.CommittedResourcesValidated = false; +#endif } // clang-format off @@ -168,493 +220,239 @@ void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState) // clang-format on -// http://diligentgraphics.com/diligent-engine/architecture/d3d11/committing-shader-resources-to-the-gpu-pipeline/ -template -void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* pPSO, IShaderResourceBinding* pShaderResourceBinding, bool VerifyStates) +void DeviceContextD3D11Impl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding) { - VERIFY_EXPR(pPSO != nullptr); - static_assert(TransitionResources || CommitResources, "At least one of TransitionResources or CommitResources flags is expected to be true"); - - auto* pPipelineStateD3D11 = ValidatedCast(pPSO); - - if (pShaderResourceBinding == nullptr) + DEV_CHECK_ERR(pPipelineState != nullptr, "Pipeline state must not be null"); + DEV_CHECK_ERR(pShaderResourceBinding != nullptr, "Shader resource binding must not be null"); + if (m_pActiveRenderPass) { -#ifdef DILIGENT_DEVELOPMENT - bool ResourcesPresent = false; - for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaderStages(); ++s) - { - auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); - if (pShaderD3D11->GetD3D11Resources()->GetTotalResources() > 0) - ResourcesPresent = true; - } - - if (ResourcesPresent) - { - LOG_ERROR_MESSAGE("Pipeline state '", pPSO->GetDesc().Name, "' requires shader resource binding object to ", - (CommitResources ? "commit" : "transition"), " resources, but none is provided."); - } -#endif + LOG_ERROR_MESSAGE("State transitions are not allowed inside a render pass."); return; } + auto* pShaderResBindingD3D11 = ValidatedCast(pShaderResourceBinding); + auto& ResourceCache = pShaderResBindingD3D11->GetResourceCache(); - auto pShaderResBindingD3D11 = ValidatedCast(pShaderResourceBinding); -#ifdef DILIGENT_DEVELOPMENT - if (pPipelineStateD3D11->IsIncompatibleWith(pShaderResourceBinding->GetPipelineState())) - { - LOG_ERROR_MESSAGE("Shader resource binding does not match Pipeline State"); + ResourceCache.TransitionResourceStates(*this, ShaderResourceCacheD3D11::StateTransitionMode::Transition); +} + +void DeviceContextD3D11Impl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) +{ + if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/)) return; - } -#endif - auto NumShaders = pShaderResBindingD3D11->GetNumActiveShaders(); - VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaderStages(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state"); + auto* pShaderResBindingD3D11 = ValidatedCast(pShaderResourceBinding); + const auto SRBIndex = pShaderResBindingD3D11->GetBindingIndex(); + auto& ResourceCache = pShaderResBindingD3D11->GetResourceCache(); + + m_BindInfo.SRBs[SRBIndex] = pShaderResBindingD3D11; + m_BindInfo.SetStaleSRBBit(SRBIndex); #ifdef DILIGENT_DEVELOPMENT - { - bool StaticResourcesPresent = false; - for (Uint32 s = 0; s < NumShaders; ++s) - { - const auto& StaticResLayout = pPipelineStateD3D11->GetStaticResourceLayout(s); - if (StaticResLayout.GetTotalResourceCount() > 0) - StaticResourcesPresent = true; - } - // Static resource bindings are verified in BindStaticShaderResources() - if (StaticResourcesPresent && !pShaderResBindingD3D11->IsStaticResourcesBound()) - { - LOG_ERROR_MESSAGE("Static resources have not been initialized in the shader resource binding object being committed for PSO '", pPSO->GetDesc().Name, "'. Please call IShaderResourceBinding::InitializeStaticResources()."); - } - } + m_BindInfo.CommittedResourcesValidated = false; #endif - bool ClearPixelShaderUAVs = m_NumCommittedUAVs[PSInd] > 0; - // First, commit all UAVs for all shader stages. This will unbind them from input - for (Uint32 s = 0; s < NumShaders; ++s) + if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) { - const auto ShaderType = pShaderResBindingD3D11->GetActiveShaderType(s); - const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType); - + ResourceCache.TransitionResourceStates(*this, ShaderResourceCacheD3D11::StateTransitionMode::Transition); + } #ifdef DILIGENT_DEVELOPMENT - auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); - VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType); + else if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY) + { + ResourceCache.TransitionResourceStates(*this, ShaderResourceCacheD3D11::StateTransitionMode::Verify); + } #endif +} - auto& Cache = pShaderResBindingD3D11->GetResourceCache(s); - auto NumUAVs = Cache.GetUAVCount(); - if (NumUAVs) - { - ShaderResourceCacheD3D11::CachedResource* CachedUAVResources; - ID3D11UnorderedAccessView** d3d11UAVs; - Cache.GetUAVArrays(CachedUAVResources, d3d11UAVs); - - auto* CommittedD3D11UAVs = m_CommittedD3D11UAVs[ShaderTypeInd]; - auto* CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[ShaderTypeInd]; +void DeviceContextD3D11Impl::BindShaderResources() +{ + if ((m_BindInfo.StaleSRBMask & m_BindInfo.ActiveSRBMask) == 0) + return; - if (ShaderTypeInd == PSInd) - ClearPixelShaderUAVs = false; + TBindingsPerStage Bindings = {}; + TMinMaxSlotPerStage MinMaxSlot = {}; + const auto ActiveStages = m_BindInfo.ActiveStages; - UINT MinSlot = UINT_MAX; - UINT MaxSlot = 0; + if (m_pPipelineState->GetDesc().IsAnyGraphicsPipeline()) + Bindings[GetShaderTypeIndex(SHADER_TYPE_PIXEL)][DESCRIPTOR_RANGE_UAV] = static_cast(m_pPipelineState->GetGraphicsPipelineDesc().NumRenderTargets); - for (Uint32 uav = 0; uav < NumUAVs; ++uav) - { - VERIFY_EXPR(uav < Cache.GetUAVCount()); - auto& UAVRes = CachedUAVResources[uav]; - // WARNING! This code is not thread-safe. It is up to the application to make - // sure that multiple threads do not modify the texture state simultaneously. - if (TransitionResources) - { - if (auto* pTexture = ValidatedCast(UAVRes.pTexture)) - { - if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - if (pTexture->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) - UnbindTextureFromInput(pTexture, UAVRes.pd3d11Resource); - pTexture->SetState(RESOURCE_STATE_UNORDERED_ACCESS); - } - } - else if (auto* pBuffer = ValidatedCast(UAVRes.pBuffer)) - { - if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - if ((pBuffer->GetState() & RESOURCE_STATE_GENERIC_READ) != 0) - UnbindBufferFromInput(pBuffer, UAVRes.pd3d11Resource); - pBuffer->SetState(RESOURCE_STATE_UNORDERED_ACCESS); - } - } - } -#ifdef DILIGENT_DEVELOPMENT - else if (VerifyStates) - { - if (const auto* pTexture = ValidatedCast(UAVRes.pTexture)) - { - if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state."); - } - } - else if (const auto* pBuffer = ValidatedCast(UAVRes.pBuffer)) - { - if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state."); - } - } - } -#endif - if (CommitResources) - { - bool IsNewUAV = CommittedD3D11UAVs[uav] != d3d11UAVs[uav]; - MinSlot = IsNewUAV ? std::min(MinSlot, uav) : MinSlot; - MaxSlot = IsNewUAV ? uav : MaxSlot; + auto ActiveSRBMask = Uint32{m_BindInfo.ActiveSRBMask}; + while (ActiveSRBMask != 0) + { + Uint32 sign = PlatformMisc::GetLSB(ActiveSRBMask); + Uint32 SigBit = (1u << sign); + VERIFY_EXPR(sign < m_pPipelineState->GetResourceSignatureCount()); - CommittedD3D11UAVRes[uav] = UAVRes.pd3d11Resource; - CommittedD3D11UAVs[uav] = d3d11UAVs[uav]; - } - } + ActiveSRBMask &= ~SigBit; - if (CommitResources) - { - if (MinSlot != UINT_MAX || ShaderTypeInd == PSInd && m_NumCommittedUAVs[PSInd] != NumUAVs) - { - // Something has changed - if (ShaderTypeInd == PSInd) - { - // Pixel shader UAVs cannot be set independently; they all need to be set at the same time. - // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks - auto StartUAVSlot = m_NumBoundRenderTargets; - VERIFY(NumUAVs > StartUAVSlot, "Number of UAVs must be greater than the render target count"); - m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews( - D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, - StartUAVSlot, NumUAVs - StartUAVSlot, CommittedD3D11UAVs + StartUAVSlot, nullptr); - // Clear previously bound UAVs, but do not clear lower slots as if - // render target count reduces, we will bind these UAVs in CommitRenderTargets() - for (Uint32 uav = NumUAVs; uav < m_NumCommittedUAVs[ShaderTypeInd]; ++uav) - { - CommittedD3D11UAVRes[uav] = nullptr; - CommittedD3D11UAVs[uav] = nullptr; - } - m_NumCommittedUAVs[ShaderTypeInd] = static_cast(NumUAVs); - } - else - { - // This can only be CS - auto SetUAVMethod = SetUAVMethods[ShaderTypeInd]; - (m_pd3d11DeviceContext->*SetUAVMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11UAVs + MinSlot, nullptr); - m_NumCommittedUAVs[ShaderTypeInd] = std::max(m_NumCommittedUAVs[ShaderTypeInd], static_cast(NumUAVs)); - } - } + auto* pSRB = m_BindInfo.SRBs[sign]; + VERIFY_EXPR(pSRB); + if (m_BindInfo.StaleSRBMask & SigBit) + { #ifdef DILIGENT_DEVELOPMENT - if ((m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) != 0 && ShaderTypeInd == CSInd) - { - dbgVerifyCommittedUAVs(pShaderD3D11->GetDesc().ShaderType); - } + m_BindInfo.BoundResOffsets[sign] = Bindings; #endif - } + pSRB->GetResourceCache().BindResources(*this, Bindings, MinMaxSlot, m_CommittedRes, ActiveStages); } + pSRB->GetSignature()->AddBindings(Bindings); } - if (ClearPixelShaderUAVs) - { - // If pixel shader stage is inactive or does not use UAVs, unbind all committed UAVs. - // This is important as UnbindPixelShaderUAV<> function may need to rebind - // existing UAVs and the UAVs pointed to by CommittedD3D11UAVRes must be alive - // (we do not keep strong references to d3d11 UAVs) - auto* CommittedD3D11UAVs = m_CommittedD3D11UAVs[PSInd]; - auto* CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[PSInd]; - auto& NumCommittedPixelShaderUAVs = m_NumCommittedUAVs[PSInd]; - for (Uint32 uav = 0; uav < NumCommittedPixelShaderUAVs; ++uav) - { - CommittedD3D11UAVRes[uav] = nullptr; - CommittedD3D11UAVs[uav] = nullptr; - } - m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews( - D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, - 0, 0, nullptr, nullptr); - NumCommittedPixelShaderUAVs = 0; - } + m_BindInfo.StaleSRBMask &= ~m_BindInfo.ActiveSRBMask; + bool ClearPixelShaderUAVs = m_CommittedRes.NumUAVs[PSInd] > 0; - // Commit input resources (CBs, SRVs and Samplers) - for (Uint32 s = 0; s < NumShaders; ++s) + for (Uint32 s = 0, ShaderCount = m_pPipelineState->GetNumShaders(); s < ShaderCount; ++s) { - const auto ShaderType = pShaderResBindingD3D11->GetActiveShaderType(s); - const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType); + const auto ShaderType = m_pPipelineState->GetShaderStageType(s); + const Uint32 ShaderInd = GetShaderTypeIndex(ShaderType); -#ifdef DILIGENT_DEVELOPMENT - auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); - VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType); -#endif - - auto& Cache = pShaderResBindingD3D11->GetResourceCache(s); - - // Transition and commit Constant Buffers - auto NumCBs = Cache.GetCBCount(); - if (NumCBs) + // CBV { - ShaderResourceCacheD3D11::CachedCB* CachedCBs; - ID3D11Buffer** d3d11CBs; - Cache.GetCBArrays(CachedCBs, d3d11CBs); - - auto* CommittedD3D11CBs = m_CommittedD3D11CBs[ShaderTypeInd]; - UINT MinSlot = UINT_MAX; - UINT MaxSlot = 0; - for (Uint32 cb = 0; cb < NumCBs; ++cb) + const auto Range = DESCRIPTOR_RANGE_CBV; + const UINT MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + const UINT MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + if (MinSlot != UINT_MAX) { - VERIFY_EXPR(cb < Cache.GetCBCount()); - - if (TransitionResources) - { - auto& CB = CachedCBs[cb]; - if (auto* pBuff = CB.pBuff.RawPtr()) - { - // WARNING! This code is not thread-safe. It is up to the application to make - // sure that multiple threads do not modify the buffer state simultaneously. - if (pBuff->IsInKnownState() && !pBuff->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) - { - if (pBuff->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - // Even though we have unbound resources from UAV, we only checked shader - // stages active in current PSO, so we still may need to unbind the resource - // from UAV (for instance, unbind resource from CS UAV when running draw command). - UnbindResourceFromUAV(pBuff, d3d11CBs[cb]); - pBuff->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); - } - pBuff->AddState(RESOURCE_STATE_CONSTANT_BUFFER); - } - } - } -#ifdef DILIGENT_DEVELOPMENT - else if (VerifyStates) - { - VERIFY_EXPR(CommitResources); - const auto& CB = CachedCBs[cb]; - if (auto* pBuff = CB.pBuff.RawPtr()) - { - if (pBuff->IsInKnownState() && !pBuff->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) - { - LOG_ERROR_MESSAGE("Buffer '", pBuff->GetDesc().Name, "' has not been transitioned to Constant Buffer state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state."); - } - } - } -#endif - - if (CommitResources) - { - bool IsNewCB = CommittedD3D11CBs[cb] != d3d11CBs[cb]; - MinSlot = IsNewCB ? std::min(MinSlot, cb) : MinSlot; - MaxSlot = IsNewCB ? cb : MaxSlot; - CommittedD3D11CBs[cb] = d3d11CBs[cb]; - } + auto SetCBMethod = SetCBMethods[ShaderInd]; + (m_pd3d11DeviceContext->*SetCBMethod)(MinSlot, MaxSlot - MinSlot + 1, m_CommittedRes.D3D11CBs[ShaderInd] + MinSlot); + m_CommittedRes.NumCBs[ShaderInd] = std::max(m_CommittedRes.NumCBs[ShaderInd], Bindings[ShaderInd][Range]); + VERIFY_EXPR(MaxSlot < Bindings[ShaderInd][Range]); } - - if (CommitResources) +#ifdef VERIFY_CONTEXT_BINDINGS + if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) { - if (MinSlot != UINT_MAX) - { - auto SetCBMethod = SetCBMethods[ShaderTypeInd]; - (m_pd3d11DeviceContext->*SetCBMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11CBs + MinSlot); - m_NumCommittedCBs[ShaderTypeInd] = std::max(m_NumCommittedCBs[ShaderTypeInd], static_cast(NumCBs)); - } -#ifdef DILIGENT_DEVELOPMENT - if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) - { - dbgVerifyCommittedCBs(pShaderD3D11->GetDesc().ShaderType); - } -#endif + DvpVerifyCommittedCBs(ShaderType); } +#endif } - - // Transition and commit Shader Resource Views - auto NumSRVs = Cache.GetSRVCount(); - if (NumSRVs) + // SRV { - ShaderResourceCacheD3D11::CachedResource* CachedSRVResources; - ID3D11ShaderResourceView** d3d11SRVs; - Cache.GetSRVArrays(CachedSRVResources, d3d11SRVs); - - auto* CommittedD3D11SRVs = m_CommittedD3D11SRVs[ShaderTypeInd]; - auto* CommittedD3D11SRVRes = m_CommittedD3D11SRVResources[ShaderTypeInd]; - - UINT MinSlot = UINT_MAX; - UINT MaxSlot = 0; - - for (Uint32 srv = 0; srv < NumSRVs; ++srv) + const auto Range = DESCRIPTOR_RANGE_SRV; + const UINT MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + const UINT MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + if (MinSlot != UINT_MAX) { - VERIFY_EXPR(srv < Cache.GetSRVCount()); - auto& SRVRes = CachedSRVResources[srv]; - // WARNING! This code is not thread-safe. It is up to the application to make - // sure that multiple threads do not modify the texture state simultaneously. - if (TransitionResources) - { - if (auto* pTexture = ValidatedCast(SRVRes.pTexture)) - { - if (pTexture->IsInKnownState() && !pTexture->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) - { - if (pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - // Even though we have unbound resources from UAV, we only checked shader - // stages active in current PSO, so we still may need to unbind the resource - // from UAV (for instance, unbind resource from CS UAV when running draw command). - UnbindResourceFromUAV(pTexture, SRVRes.pd3d11Resource); - pTexture->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); - } - - if (pTexture->CheckState(RESOURCE_STATE_RENDER_TARGET)) - UnbindTextureFromRenderTarget(pTexture); - - if (pTexture->CheckState(RESOURCE_STATE_DEPTH_WRITE)) - UnbindTextureFromDepthStencil(pTexture); - - pTexture->SetState(RESOURCE_STATE_SHADER_RESOURCE); - } - } - else if (auto* pBuffer = ValidatedCast(SRVRes.pBuffer)) - { - if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) - { - if (pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) - { - UnbindResourceFromUAV(pBuffer, SRVRes.pd3d11Resource); - pBuffer->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); - } - pBuffer->AddState(RESOURCE_STATE_SHADER_RESOURCE); - } - } - } -#ifdef DILIGENT_DEVELOPMENT - else if (VerifyStates) - { - VERIFY_EXPR(CommitResources); - if (const auto* pTexture = ValidatedCast(SRVRes.pTexture)) - { - if (pTexture->IsInKnownState() && - !(pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE) || m_pActiveRenderPass != nullptr && pTexture->CheckState(RESOURCE_STATE_INPUT_ATTACHMENT))) - { - LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state."); - } - } - else if (const auto* pBuffer = ValidatedCast(SRVRes.pBuffer)) - { - if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) - { - LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state."); - } - } - } + auto SetSRVMethod = SetSRVMethods[ShaderInd]; + (m_pd3d11DeviceContext->*SetSRVMethod)(MinSlot, MaxSlot - MinSlot + 1, m_CommittedRes.D3D11SRVs[ShaderInd] + MinSlot); + m_CommittedRes.NumSRVs[ShaderInd] = std::max(m_CommittedRes.NumSRVs[ShaderInd], Bindings[ShaderInd][Range]); + VERIFY_EXPR(MaxSlot <= Bindings[ShaderInd][Range]); + } +#ifdef VERIFY_CONTEXT_BINDINGS + if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) + { + DvpVerifyCommittedSRVs(ShaderType); + } #endif + } - if (CommitResources) - { - bool IsNewSRV = CommittedD3D11SRVs[srv] != d3d11SRVs[srv]; - MinSlot = IsNewSRV ? std::min(MinSlot, srv) : MinSlot; - MaxSlot = IsNewSRV ? srv : MaxSlot; - - CommittedD3D11SRVRes[srv] = SRVRes.pd3d11Resource; - CommittedD3D11SRVs[srv] = d3d11SRVs[srv]; - } + // Sampler + { + const auto Range = DESCRIPTOR_RANGE_SAMPLER; + const UINT MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + const UINT MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + if (MinSlot != UINT_MAX) + { + auto SetSamplerMethod = SetSamplerMethods[ShaderInd]; + (m_pd3d11DeviceContext->*SetSamplerMethod)(MinSlot, MaxSlot - MinSlot + 1, m_CommittedRes.D3D11Samplers[ShaderInd] + MinSlot); + m_CommittedRes.NumSamplers[ShaderInd] = std::max(m_CommittedRes.NumSamplers[ShaderInd], Bindings[ShaderInd][Range]); + VERIFY_EXPR(MaxSlot < Bindings[ShaderInd][Range]); } - - if (CommitResources) +#ifdef VERIFY_CONTEXT_BINDINGS + if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) { - if (MinSlot != UINT_MAX) - { - auto SetSRVMethod = SetSRVMethods[ShaderTypeInd]; - (m_pd3d11DeviceContext->*SetSRVMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11SRVs + MinSlot); - m_NumCommittedSRVs[ShaderTypeInd] = std::max(m_NumCommittedSRVs[ShaderTypeInd], static_cast(NumSRVs)); - } -#ifdef DILIGENT_DEVELOPMENT - if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) - { - dbgVerifyCommittedSRVs(pShaderD3D11->GetDesc().ShaderType); - } -#endif + DvpVerifyCommittedSamplers(ShaderType); } +#endif } - - // Commit samplers (no transitions for samplers) - if (CommitResources) + // UAV { - auto NumSamplers = Cache.GetSamplerCount(); - if (NumSamplers) + const auto Range = DESCRIPTOR_RANGE_UAV; + const UINT MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + const UINT MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + if (MinSlot != UINT_MAX) { - ShaderResourceCacheD3D11::CachedSampler* CachedSamplers; - ID3D11SamplerState** d3d11Samplers; - Cache.GetSamplerArrays(CachedSamplers, d3d11Samplers); - - auto* CommittedD3D11Samplers = m_CommittedD3D11Samplers[ShaderTypeInd]; - UINT MinSlot = std::numeric_limits::max(); - UINT MaxSlot = 0; - for (Uint32 sam = 0; sam < NumSamplers; ++sam) - { - VERIFY_EXPR(sam < Cache.GetSamplerCount()); + auto* CommittedD3D11UAVs = m_CommittedRes.D3D11UAVs[ShaderInd]; + auto* CommittedD3D11UAVRes = m_CommittedRes.D3D11UAVResources[ShaderInd]; - bool IsNewSam = CommittedD3D11Samplers[sam] != d3d11Samplers[sam]; - MinSlot = IsNewSam ? std::min(MinSlot, sam) : MinSlot; - MaxSlot = IsNewSam ? sam : MaxSlot; + if (ShaderInd == PSInd) + ClearPixelShaderUAVs = false; - CommittedD3D11Samplers[sam] = d3d11Samplers[sam]; + // Something has changed + if (ShaderInd == PSInd) + { + // Pixel shader UAVs cannot be set independently; they all need to be set at the same time. + // https://docs.microsoft.com/en-us/windows/desktop/api/d3d11/nf-d3d11-id3d11devicecontext-omsetrendertargetsandunorderedaccessviews#remarks + const auto StartUAVSlot = m_NumBoundRenderTargets; + const auto NumUAVSlot = Bindings[ShaderInd][Range]; + VERIFY(NumUAVSlot > StartUAVSlot, "Number of UAVs must be greater than the render target count"); + m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews( + D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, + StartUAVSlot, NumUAVSlot - StartUAVSlot, CommittedD3D11UAVs + StartUAVSlot, nullptr); + // Clear previously bound UAVs, but do not clear lower slots as if + // render target count reduces, we will bind these UAVs in CommitRenderTargets() + for (Uint32 uav = NumUAVSlot; uav < m_CommittedRes.NumUAVs[ShaderInd]; ++uav) + { + CommittedD3D11UAVRes[uav] = nullptr; + CommittedD3D11UAVs[uav] = nullptr; + } + m_CommittedRes.NumUAVs[ShaderInd] = NumUAVSlot; } - - if (MinSlot != UINT_MAX) + else if (ShaderInd == CSInd) { - auto SetSamplerMethod = SetSamplerMethods[ShaderTypeInd]; - (m_pd3d11DeviceContext->*SetSamplerMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11Samplers + MinSlot); - m_NumCommittedSamplers[ShaderTypeInd] = std::max(m_NumCommittedSamplers[ShaderTypeInd], static_cast(NumSamplers)); + // This can only be CS + auto SetUAVMethod = SetUAVMethods[ShaderInd]; + (m_pd3d11DeviceContext->*SetUAVMethod)(MinSlot, MaxSlot - MinSlot + 1, CommittedD3D11UAVs + MinSlot, nullptr); + m_CommittedRes.NumUAVs[ShaderInd] = std::max(m_CommittedRes.NumUAVs[ShaderInd], Bindings[ShaderInd][Range]); + VERIFY_EXPR(MaxSlot < Bindings[ShaderInd][Range]); } -#ifdef DILIGENT_DEVELOPMENT - if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) + else { - dbgVerifyCommittedSamplers(pShaderD3D11->GetDesc().ShaderType); + UNEXPECTED("UAV is not supported in shader that is not pixel or compute"); } -#endif } - } - - - -#ifdef DILIGENT_DEVELOPMENT - if (CommitResources && (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_SHADER_RESOURCES) != 0) - { - // Use full resource layout to verify that all required resources are committed - pShaderD3D11->GetD3D11Resources()->dvpVerifyCommittedResources( - m_CommittedD3D11CBs[ShaderTypeInd], - m_CommittedD3D11SRVs[ShaderTypeInd], - m_CommittedD3D11SRVResources[ShaderTypeInd], - m_CommittedD3D11Samplers[ShaderTypeInd], - m_CommittedD3D11UAVs[ShaderTypeInd], - m_CommittedD3D11UAVResources[ShaderTypeInd], - Cache); - } +#ifdef VERIFY_CONTEXT_BINDINGS + if ((m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) != 0 && ShaderInd == CSInd) + { + DvpVerifyCommittedUAVs(ShaderType); + } #endif + } } -} -void DeviceContextD3D11Impl::TransitionShaderResources(IPipelineState* pPipelineState, IShaderResourceBinding* pShaderResourceBinding) -{ - DEV_CHECK_ERR(pPipelineState != nullptr, "Pipeline state must not be null"); - DEV_CHECK_ERR(pShaderResourceBinding != nullptr, "Shader resource binding must not be null"); - if (m_pActiveRenderPass) + if (ClearPixelShaderUAVs) { - LOG_ERROR_MESSAGE("State transitions are not allowed inside a render pass."); - return; + // If pixel shader stage is inactive or does not use UAVs, unbind all committed UAVs. + // This is important as UnbindPixelShaderUAV<> function may need to rebind + // existing UAVs and the UAVs pointed to by CommittedD3D11UAVRes must be alive + // (we do not keep strong references to d3d11 UAVs) + auto* CommittedD3D11UAVs = m_CommittedRes.D3D11UAVs[PSInd]; + auto* CommittedD3D11UAVRes = m_CommittedRes.D3D11UAVResources[PSInd]; + auto& NumCommittedPixelShaderUAVs = m_CommittedRes.NumUAVs[PSInd]; + for (Uint32 uav = 0; uav < NumCommittedPixelShaderUAVs; ++uav) + { + CommittedD3D11UAVRes[uav] = nullptr; + CommittedD3D11UAVs[uav] = nullptr; + } + m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews( + D3D11_KEEP_RENDER_TARGETS_AND_DEPTH_STENCIL, nullptr, nullptr, + 0, 0, nullptr, nullptr); + NumCommittedPixelShaderUAVs = 0; } - - TransitionAndCommitShaderResources(pPipelineState, pShaderResourceBinding, false); } -void DeviceContextD3D11Impl::CommitShaderResources(IShaderResourceBinding* pShaderResourceBinding, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) +#ifdef DILIGENT_DEVELOPMENT +void DeviceContextD3D11Impl::DvpValidateCommittedShaderResources() { - if (!DeviceContextBase::CommitShaderResources(pShaderResourceBinding, StateTransitionMode, 0 /*Dummy*/)) + if (m_BindInfo.CommittedResourcesValidated) return; - if (StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_TRANSITION) - TransitionAndCommitShaderResources(m_pPipelineState, pShaderResourceBinding, false); - else - TransitionAndCommitShaderResources(m_pPipelineState, pShaderResourceBinding, StateTransitionMode == RESOURCE_STATE_TRANSITION_MODE_VERIFY); + // AZ TODO + //m_pPipelineState->DvpVerifySRBResources(m_BindInfo.SRBs.data(), m_BindInfo.BoundResOffsets.data(), static_cast(m_BindInfo.SRBs.size())); + m_BindInfo.CommittedResourcesValidated = true; } +#endif void DeviceContextD3D11Impl::SetStencilRef(Uint32 StencilRef) { @@ -780,7 +578,9 @@ void DeviceContextD3D11Impl::PrepareForDraw(DRAW_FLAGS Flags) CommitD3D11VertexBuffers(m_pPipelineState); } -#ifdef DILIGENT_DEVELOPMENT + BindShaderResources(); + +#ifdef VERIFY_CONTEXT_BINDINGS if ((Flags & DRAW_FLAG_VERIFY_STATES) != 0) { for (UINT Slot = 0; Slot < m_NumVertexStreams; ++Slot) @@ -798,13 +598,13 @@ void DeviceContextD3D11Impl::PrepareForDraw(DRAW_FLAGS Flags) if ((m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) != 0) { // Verify bindings after all resources are set - dbgVerifyCommittedSRVs(); - dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); - dbgVerifyCommittedSamplers(); - dbgVerifyCommittedCBs(); - dbgVerifyCommittedVertexBuffers(); - dbgVerifyCommittedIndexBuffer(); - dbgVerifyCommittedShaders(); + const auto ActiveStages = m_pPipelineState->GetActiveShaderStages(); + DvpVerifyCommittedSRVs(ActiveStages); + DvpVerifyCommittedSamplers(ActiveStages); + DvpVerifyCommittedCBs(ActiveStages); + DvpVerifyCommittedVertexBuffers(); + DvpVerifyCommittedIndexBuffer(); + DvpVerifyCommittedShaders(); } } #endif @@ -900,15 +700,17 @@ void DeviceContextD3D11Impl::DispatchCompute(const DispatchComputeAttribs& Attri if (!DvpVerifyDispatchArguments(Attribs)) return; -#ifdef DILIGENT_DEVELOPMENT + BindShaderResources(); + +#ifdef VERIFY_CONTEXT_BINDINGS if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) { // Verify bindings - dbgVerifyCommittedSRVs(); - dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); - dbgVerifyCommittedSamplers(); - dbgVerifyCommittedCBs(); - dbgVerifyCommittedShaders(); + DvpVerifyCommittedSRVs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedSamplers(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedCBs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedShaders(); } #endif @@ -920,15 +722,17 @@ void DeviceContextD3D11Impl::DispatchComputeIndirect(const DispatchComputeIndire if (!DvpVerifyDispatchIndirectArguments(Attribs, pAttribsBuffer)) return; -#ifdef DILIGENT_DEVELOPMENT + BindShaderResources(); + +#ifdef VERIFY_CONTEXT_BINDINGS if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) { // Verify bindings - dbgVerifyCommittedSRVs(); - dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); - dbgVerifyCommittedSamplers(); - dbgVerifyCommittedCBs(); - dbgVerifyCommittedShaders(); + DvpVerifyCommittedSRVs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedSamplers(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedCBs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedShaders(); } #endif @@ -1320,14 +1124,14 @@ void DeviceContextD3D11Impl::CommitRenderTargets() pd3d11DSV = static_cast(m_pBoundDepthStencil->GetD3D11View()); } - auto& NumCommittedPixelShaderUAVs = m_NumCommittedUAVs[PSInd]; + auto& NumCommittedPixelShaderUAVs = m_CommittedRes.NumUAVs[PSInd]; if (NumCommittedPixelShaderUAVs > 0) { m_pd3d11DeviceContext->OMSetRenderTargetsAndUnorderedAccessViews(NumRenderTargets, NumRenderTargets > 0 ? pd3d11RTs : nullptr, pd3d11DSV, 0, D3D11_KEEP_UNORDERED_ACCESS_VIEWS, nullptr, nullptr); - auto CommittedD3D11UAVs = m_CommittedD3D11UAVs[PSInd]; - auto CommittedD3D11UAVRes = m_CommittedD3D11UAVResources[PSInd]; + auto CommittedD3D11UAVs = m_CommittedRes.D3D11UAVs[PSInd]; + auto CommittedD3D11UAVRes = m_CommittedRes.D3D11UAVResources[PSInd]; for (Uint32 slot = 0; slot < NumRenderTargets; ++slot) { CommittedD3D11UAVs[slot] = nullptr; @@ -1450,7 +1254,7 @@ void DeviceContextD3D11Impl::UnbindTextureFromInput(TextureBaseD3D11* pTexture, VERIFY(pTexture, "Null texture provided"); if (!pTexture) return; - UnbindResourceView(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, pd3d11Resource, SetSRVMethods); + UnbindResourceView(m_CommittedRes.D3D11SRVs, m_CommittedRes.D3D11SRVResources, m_CommittedRes.NumSRVs, pd3d11Resource, SetSRVMethods); pTexture->ClearState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT); } @@ -1461,7 +1265,7 @@ void DeviceContextD3D11Impl::UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3 if (pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) { - UnbindResourceView(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, pd3d11Buffer, SetSRVMethods); + UnbindResourceView(m_CommittedRes.D3D11SRVs, m_CommittedRes.D3D11SRVResources, m_CommittedRes.NumSRVs, pd3d11Buffer, SetSRVMethods); pBuffer->ClearState(RESOURCE_STATE_SHADER_RESOURCE); } @@ -1478,12 +1282,6 @@ void DeviceContextD3D11Impl::UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3 m_bCommittedD3D11IBUpToDate = false; m_pd3d11DeviceContext->IASetIndexBuffer(nullptr, DXGI_FORMAT_R32_UINT, m_CommittedD3D11IndexDataStartOffset); } -#ifdef DILIGENT_DEVELOPMENT - if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) - { - dbgVerifyCommittedIndexBuffer(); - } -#endif pBuffer->ClearState(RESOURCE_STATE_INDEX_BUFFER); } @@ -1506,12 +1304,6 @@ void DeviceContextD3D11Impl::UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3 m_pd3d11DeviceContext->IASetVertexBuffers(Slot, _countof(ppNullBuffer), ppNullBuffer, Zero, Zero); } } -#ifdef DILIGENT_DEVELOPMENT - if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) - { - dbgVerifyCommittedVertexBuffers(); - } -#endif pBuffer->ClearState(RESOURCE_STATE_VERTEX_BUFFER); } @@ -1519,8 +1311,8 @@ void DeviceContextD3D11Impl::UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3 { for (Int32 ShaderTypeInd = 0; ShaderTypeInd < NumShaderTypes; ++ShaderTypeInd) { - auto* CommittedD3D11CBs = m_CommittedD3D11CBs[ShaderTypeInd]; - auto NumSlots = m_NumCommittedCBs[ShaderTypeInd]; + auto* CommittedD3D11CBs = m_CommittedRes.D3D11CBs[ShaderTypeInd]; + auto NumSlots = m_CommittedRes.NumCBs[ShaderTypeInd]; for (Uint32 Slot = 0; Slot < NumSlots; ++Slot) { if (CommittedD3D11CBs[Slot] == pd3d11Buffer) @@ -1532,12 +1324,6 @@ void DeviceContextD3D11Impl::UnbindBufferFromInput(BufferD3D11Impl* pBuffer, ID3 } } } -#ifdef DILIGENT_DEVELOPMENT - if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) - { - dbgVerifyCommittedCBs(); - } -#endif pBuffer->ClearState(RESOURCE_STATE_CONSTANT_BUFFER); } } @@ -1547,7 +1333,7 @@ void DeviceContextD3D11Impl::UnbindResourceFromUAV(IDeviceObject* pResource, ID3 VERIFY(pResource, "Null resource provided"); if (!pResource) return; - UnbindResourceView(m_CommittedD3D11UAVs, m_CommittedD3D11UAVResources, m_NumCommittedUAVs, pd3d11Resource, SetUAVMethods); + UnbindResourceView(m_CommittedRes.D3D11UAVs, m_CommittedRes.D3D11UAVResources, m_CommittedRes.NumUAVs, pd3d11Resource, SetUAVMethods); } void DeviceContextD3D11Impl::UnbindTextureFromRenderTarget(TextureBaseD3D11* pTexture) @@ -1677,7 +1463,7 @@ void DeviceContextD3D11Impl::BeginSubpass() if (auto* pTexView = FBDesc.ppAttachments[AttachmentRef.AttachmentIndex]) { auto* pTexD3D11 = ValidatedCast(pTexView->GetTexture()); - UnbindResourceView(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, pTexD3D11->GetD3D11Texture(), SetSRVMethods); + UnbindResourceView(m_CommittedRes.D3D11SRVs, m_CommittedRes.D3D11SRVResources, m_CommittedRes.NumSRVs, pTexD3D11->GetD3D11Texture(), SetSRVMethods); } } }; @@ -1854,34 +1640,37 @@ void ReleaseCommittedPSUAVs(ID3D11UnorderedAccessView* CommittedD3D11UAVs[], void DeviceContextD3D11Impl::ReleaseCommittedShaderResources() { + m_BindInfo = {}; + for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType) { // clang-format off - ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11CBs[ShaderType], m_NumCommittedCBs[ShaderType], SetCBMethods[ShaderType], m_pd3d11DeviceContext); - ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11SRVs[ShaderType], m_NumCommittedSRVs[ShaderType], SetSRVMethods[ShaderType], m_pd3d11DeviceContext); - ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11Samplers[ShaderType], m_NumCommittedSamplers[ShaderType], SetSamplerMethods[ShaderType], m_pd3d11DeviceContext); + ReleaseCommittedShaderResourcesHelper(m_CommittedRes.D3D11CBs[ShaderType], m_CommittedRes.NumCBs[ShaderType], SetCBMethods[ShaderType], m_pd3d11DeviceContext); + ReleaseCommittedShaderResourcesHelper(m_CommittedRes.D3D11SRVs[ShaderType], m_CommittedRes.NumSRVs[ShaderType], SetSRVMethods[ShaderType], m_pd3d11DeviceContext); + ReleaseCommittedShaderResourcesHelper(m_CommittedRes.D3D11Samplers[ShaderType], m_CommittedRes.NumSamplers[ShaderType], SetSamplerMethods[ShaderType], m_pd3d11DeviceContext); // clang-format on if (ShaderType == PSInd) - ReleaseCommittedPSUAVs(m_CommittedD3D11UAVs[ShaderType], m_NumCommittedUAVs[ShaderType], m_pd3d11DeviceContext); + ReleaseCommittedPSUAVs(m_CommittedRes.D3D11UAVs[ShaderType], m_CommittedRes.NumUAVs[ShaderType], m_pd3d11DeviceContext); else - ReleaseCommittedShaderResourcesHelper(m_CommittedD3D11UAVs[ShaderType], m_NumCommittedUAVs[ShaderType], SetUAVMethods[ShaderType], m_pd3d11DeviceContext); + ReleaseCommittedShaderResourcesHelper(m_CommittedRes.D3D11UAVs[ShaderType], m_CommittedRes.NumUAVs[ShaderType], SetUAVMethods[ShaderType], m_pd3d11DeviceContext); - memset(m_CommittedD3D11SRVResources[ShaderType], 0, sizeof(m_CommittedD3D11SRVResources[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]); - memset(m_CommittedD3D11UAVResources[ShaderType], 0, sizeof(m_CommittedD3D11UAVResources[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]); - m_NumCommittedCBs[ShaderType] = 0; - m_NumCommittedSRVs[ShaderType] = 0; - m_NumCommittedSamplers[ShaderType] = 0; - m_NumCommittedUAVs[ShaderType] = 0; + memset(m_CommittedRes.D3D11SRVResources[ShaderType], 0, sizeof(m_CommittedRes.D3D11SRVResources[ShaderType][0]) * m_CommittedRes.NumSRVs[ShaderType]); + memset(m_CommittedRes.D3D11UAVResources[ShaderType], 0, sizeof(m_CommittedRes.D3D11UAVResources[ShaderType][0]) * m_CommittedRes.NumUAVs[ShaderType]); + m_CommittedRes.NumCBs[ShaderType] = 0; + m_CommittedRes.NumSRVs[ShaderType] = 0; + m_CommittedRes.NumSamplers[ShaderType] = 0; + m_CommittedRes.NumUAVs[ShaderType] = 0; } -#ifdef DILIGENT_DEVELOPMENT +#ifdef VERIFY_CONTEXT_BINDINGS if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) { - dbgVerifyCommittedSRVs(); - dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); - dbgVerifyCommittedSamplers(); - dbgVerifyCommittedCBs(); + constexpr auto AllStages = SHADER_TYPE_ALL_GRAPHICS | SHADER_TYPE_COMPUTE; + DvpVerifyCommittedSRVs(AllStages); + DvpVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedSamplers(AllStages); + DvpVerifyCommittedCBs(AllStages); } #endif // We do not unbind vertex buffers and index buffer as this can explicitly @@ -1910,17 +1699,18 @@ void DeviceContextD3D11Impl::FinishCommandList(ICommandList** ppCommandList) // Device context is now in default state InvalidateState(); -#ifdef DILIGENT_DEVELOPMENT +#ifdef VERIFY_CONTEXT_BINDINGS if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) { // Verify bindings - dbgVerifyCommittedSRVs(); - dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); - dbgVerifyCommittedSamplers(); - dbgVerifyCommittedCBs(); - dbgVerifyCommittedVertexBuffers(); - dbgVerifyCommittedIndexBuffer(); - dbgVerifyCommittedShaders(); + constexpr auto AllStages = SHADER_TYPE_ALL_GRAPHICS | SHADER_TYPE_COMPUTE; + DvpVerifyCommittedSRVs(AllStages); + DvpVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedSamplers(AllStages); + DvpVerifyCommittedCBs(AllStages); + DvpVerifyCommittedVertexBuffers(); + DvpVerifyCommittedIndexBuffer(); + DvpVerifyCommittedShaders(); } #endif } @@ -1955,17 +1745,18 @@ void DeviceContextD3D11Impl::ExecuteCommandLists(Uint32 NumCommand // Device context is now in default state InvalidateState(); -#ifdef DILIGENT_DEVELOPMENT +#ifdef VERIFY_CONTEXT_BINDINGS if (m_DebugFlags & D3D11_DEBUG_FLAG_VERIFY_COMMITTED_RESOURCE_RELEVANCE) { // Verify bindings - dbgVerifyCommittedSRVs(); - dbgVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); - dbgVerifyCommittedSamplers(); - dbgVerifyCommittedCBs(); - dbgVerifyCommittedVertexBuffers(); - dbgVerifyCommittedIndexBuffer(); - dbgVerifyCommittedShaders(); + constexpr auto AllStages = SHADER_TYPE_ALL_GRAPHICS | SHADER_TYPE_COMPUTE; + DvpVerifyCommittedSRVs(AllStages); + DvpVerifyCommittedUAVs(SHADER_TYPE_COMPUTE); + DvpVerifyCommittedSamplers(AllStages); + DvpVerifyCommittedCBs(AllStages); + DvpVerifyCommittedVertexBuffers(); + DvpVerifyCommittedIndexBuffer(); + DvpVerifyCommittedShaders(); } #endif } @@ -2068,22 +1859,10 @@ void DeviceContextD3D11Impl::ClearStateCache() { TDeviceContextBase::ClearStateCache(); + m_CommittedRes.Clear(); + for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType) { - // clang-format off - memset(m_CommittedD3D11CBs[ShaderType], 0, sizeof(m_CommittedD3D11CBs[ShaderType][0]) * m_NumCommittedCBs[ShaderType]); - memset(m_CommittedD3D11SRVs[ShaderType], 0, sizeof(m_CommittedD3D11SRVs[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]); - memset(m_CommittedD3D11Samplers[ShaderType], 0, sizeof(m_CommittedD3D11Samplers[ShaderType][0]) * m_NumCommittedSamplers[ShaderType]); - memset(m_CommittedD3D11UAVs[ShaderType], 0, sizeof(m_CommittedD3D11UAVs[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]); - memset(m_CommittedD3D11SRVResources[ShaderType], 0, sizeof(m_CommittedD3D11SRVResources[ShaderType][0]) * m_NumCommittedSRVs[ShaderType]); - memset(m_CommittedD3D11UAVResources[ShaderType], 0, sizeof(m_CommittedD3D11UAVResources[ShaderType][0]) * m_NumCommittedUAVs[ShaderType]); - // clang-format on - - m_NumCommittedCBs[ShaderType] = 0; - m_NumCommittedSRVs[ShaderType] = 0; - m_NumCommittedSamplers[ShaderType] = 0; - m_NumCommittedUAVs[ShaderType] = 0; - m_CommittedD3DShaders[ShaderType].Release(); } @@ -2179,101 +1958,109 @@ void DeviceContextD3D11Impl::TransitionResourceStates(Uint32 BarrierCount, State if (RefCntAutoPtr pTexture{Barrier.pResource, IID_TextureD3D11}) { - auto OldState = Barrier.OldState; - if (OldState == RESOURCE_STATE_UNKNOWN) - { - if (pTexture->IsInKnownState()) - { - OldState = pTexture->GetState(); - } - else - { - LOG_ERROR_MESSAGE("Failed to transition the state of texture '", pTexture->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified"); - continue; - } - } - else - { - if (pTexture->IsInKnownState() && pTexture->GetState() != OldState) - { - LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pTexture->GetState()), " of texture '", - pTexture->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState), - " specified by the barrier"); - } - } + TransitionResource(pTexture, Barrier.NewState, Barrier.OldState); + } + else if (RefCntAutoPtr pBuffer{Barrier.pResource, IID_BufferD3D11}) + { + TransitionResource(pBuffer, Barrier.NewState, Barrier.OldState); + } + else + { + UNEXPECTED("The type of resource '", Barrier.pResource->GetDesc().Name, "' is not support in D3D11"); + } + } +} - if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0) - { - DEV_CHECK_ERR((Barrier.NewState & (RESOURCE_STATE_GENERIC_READ | RESOURCE_STATE_INPUT_ATTACHMENT)) == 0, "Unordered access state is not compatible with any input state"); - UnbindTextureFromInput(pTexture, pTexture->GetD3D11Texture()); - } +void DeviceContextD3D11Impl::TransitionResource(TextureBaseD3D11* pTexture, RESOURCE_STATE NewState, RESOURCE_STATE OldState, bool UpdateResourceState) +{ + if (OldState == RESOURCE_STATE_UNKNOWN) + { + if (pTexture->IsInKnownState()) + { + OldState = pTexture->GetState(); + } + else + { + LOG_ERROR_MESSAGE("Failed to transition the state of texture '", pTexture->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified"); + return; + } + } + else + { + if (pTexture->IsInKnownState() && pTexture->GetState() != OldState) + { + LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pTexture->GetState()), " of texture '", + pTexture->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState), + " specified by the barrier"); + } + } - if ((Barrier.NewState & (RESOURCE_STATE_GENERIC_READ | RESOURCE_STATE_INPUT_ATTACHMENT)) != 0) - { - if ((OldState & RESOURCE_STATE_RENDER_TARGET) != 0) - UnbindTextureFromRenderTarget(pTexture); + if ((NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0) + { + DEV_CHECK_ERR((NewState & (RESOURCE_STATE_GENERIC_READ | RESOURCE_STATE_INPUT_ATTACHMENT)) == 0, "Unordered access state is not compatible with any input state"); + UnbindTextureFromInput(pTexture, pTexture->GetD3D11Texture()); + } - if ((OldState & RESOURCE_STATE_DEPTH_WRITE) != 0) - UnbindTextureFromDepthStencil(pTexture); + if ((NewState & (RESOURCE_STATE_GENERIC_READ | RESOURCE_STATE_INPUT_ATTACHMENT)) != 0) + { + if ((OldState & RESOURCE_STATE_RENDER_TARGET) != 0) + UnbindTextureFromRenderTarget(pTexture); - if ((OldState & RESOURCE_STATE_UNORDERED_ACCESS) != 0) - { - UnbindResourceFromUAV(pTexture, pTexture->GetD3D11Texture()); - pTexture->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); - } - } + if ((OldState & RESOURCE_STATE_DEPTH_WRITE) != 0) + UnbindTextureFromDepthStencil(pTexture); - if (Barrier.UpdateResourceState) - { - pTexture->SetState(Barrier.NewState); - } - } - else if (RefCntAutoPtr pBuffer{Barrier.pResource, IID_BufferD3D11}) + if ((OldState & RESOURCE_STATE_UNORDERED_ACCESS) != 0) { - auto OldState = Barrier.OldState; - if (OldState == RESOURCE_STATE_UNKNOWN) - { - if (pBuffer->IsInKnownState()) - { - OldState = pBuffer->GetState(); - } - else - { - LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", pBuffer->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified"); - continue; - } - } - else - { - if (pBuffer->IsInKnownState() && pBuffer->GetState() != OldState) - { - LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pBuffer->GetState()), " of buffer '", - pBuffer->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState), - " specified by the barrier"); - } - } - - if ((Barrier.NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0) - { - DEV_CHECK_ERR((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) == 0, "Unordered access state is not compatible with any input state"); - UnbindBufferFromInput(pBuffer, pBuffer->m_pd3d11Buffer); - } + UnbindResourceFromUAV(pTexture, pTexture->GetD3D11Texture()); + pTexture->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); + } + } - if ((Barrier.NewState & RESOURCE_STATE_GENERIC_READ) != 0) - { - UnbindResourceFromUAV(pBuffer, pBuffer->m_pd3d11Buffer); - } + if (UpdateResourceState) + { + pTexture->SetState(NewState); + } +} - if (Barrier.UpdateResourceState) - { - pBuffer->SetState(Barrier.NewState); - } +void DeviceContextD3D11Impl::TransitionResource(BufferD3D11Impl* pBuffer, RESOURCE_STATE NewState, RESOURCE_STATE OldState, bool UpdateResourceState) +{ + if (OldState == RESOURCE_STATE_UNKNOWN) + { + if (pBuffer->IsInKnownState()) + { + OldState = pBuffer->GetState(); } else { - UNEXPECTED("The type of resource '", Barrier.pResource->GetDesc().Name, "' is not support in D3D11"); + LOG_ERROR_MESSAGE("Failed to transition the state of buffer '", pBuffer->GetDesc().Name, "' because the buffer state is unknown and is not explicitly specified"); + return; } } + else + { + if (pBuffer->IsInKnownState() && pBuffer->GetState() != OldState) + { + LOG_ERROR_MESSAGE("The state ", GetResourceStateString(pBuffer->GetState()), " of buffer '", + pBuffer->GetDesc().Name, "' does not match the old state ", GetResourceStateString(OldState), + " specified by the barrier"); + } + } + + if ((NewState & RESOURCE_STATE_UNORDERED_ACCESS) != 0) + { + DEV_CHECK_ERR((NewState & RESOURCE_STATE_GENERIC_READ) == 0, "Unordered access state is not compatible with any input state"); + UnbindBufferFromInput(pBuffer, pBuffer->m_pd3d11Buffer); + } + + if ((NewState & RESOURCE_STATE_GENERIC_READ) != 0) + { + UnbindResourceFromUAV(pBuffer, pBuffer->m_pd3d11Buffer); + } + + if (UpdateResourceState) + { + pBuffer->SetState(NewState); + } } void DeviceContextD3D11Impl::ResolveTextureSubresource(ITexture* pSrcTexture, @@ -2377,29 +2164,25 @@ void DeviceContextD3D11Impl::TraceRays(const TraceRaysAttribs& Attribs) template -void DeviceContextD3D11Impl::dbgVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources], +void DeviceContextD3D11Impl::DvpVerifyCommittedResources(TD3D11ResourceType CommittedD3D11ResourcesArr[][MaxResources], Uint8 NumCommittedResourcesArr[], TGetD3D11ResourcesType GetD3D11ResMethods[], const Char* ResourceName, - SHADER_TYPE ShaderType) + SHADER_TYPE ShaderStages) { - int iStartInd = 0, iEndInd = NumShaderTypes; - if (ShaderType != SHADER_TYPE_UNKNOWN) - { - iStartInd = GetShaderTypeIndex(ShaderType); - iEndInd = iStartInd + 1; - } - for (int iShaderTypeInd = iStartInd; iShaderTypeInd < iEndInd; ++iShaderTypeInd) + while (ShaderStages != 0) { - const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(iShaderTypeInd)); + const auto Stage = ExtractLSB(ShaderStages); + const auto ShaderInd = GetShaderTypeIndex(Stage); + const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(ShaderInd)); TD3D11ResourceType pctxResources[MaxResources] = {}; - auto GetResMethod = GetD3D11ResMethods[iShaderTypeInd]; + auto GetResMethod = GetD3D11ResMethods[ShaderInd]; if (GetResMethod) { (m_pd3d11DeviceContext->*GetResMethod)(0, _countof(pctxResources), pctxResources); } - const auto* CommittedResources = CommittedD3D11ResourcesArr[iShaderTypeInd]; - auto NumCommittedResources = NumCommittedResourcesArr[iShaderTypeInd]; + const auto* CommittedResources = CommittedD3D11ResourcesArr[ShaderInd]; + auto NumCommittedResources = NumCommittedResourcesArr[ShaderInd]; for (Uint32 Slot = 0; Slot < _countof(pctxResources); ++Slot) { if (Slot < NumCommittedResources) @@ -2419,24 +2202,20 @@ void DeviceContextD3D11Impl::dbgVerifyCommittedResources(TD3D11ResourceType } template -void DeviceContextD3D11Impl::dbgVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources], +void DeviceContextD3D11Impl::DvpVerifyViewConsistency(TD3D11ViewType CommittedD3D11ViewArr[][MaxResources], ID3D11Resource* CommittedD3D11ResourcesArr[][MaxResources], Uint8 NumCommittedResourcesArr[], const Char* ResourceName, - SHADER_TYPE ShaderType) + SHADER_TYPE ShaderStages) { - int iStartInd = 0, iEndInd = NumShaderTypes; - if (ShaderType != SHADER_TYPE_UNKNOWN) - { - iStartInd = GetShaderTypeIndex(ShaderType); - iEndInd = iStartInd + 1; - } - for (int iShaderTypeInd = iStartInd; iShaderTypeInd < iEndInd; ++iShaderTypeInd) + while (ShaderStages != 0) { - const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(iShaderTypeInd)); - auto* Views = CommittedD3D11ViewArr[iShaderTypeInd]; - auto* Resources = CommittedD3D11ResourcesArr[iShaderTypeInd]; - auto NumCommittedResources = NumCommittedResourcesArr[iShaderTypeInd]; + const auto Stage = ExtractLSB(ShaderStages); + const auto ShaderInd = GetShaderTypeIndex(Stage); + const auto ShaderName = GetShaderTypeLiteralName(GetShaderTypeFromIndex(ShaderInd)); + auto* Views = CommittedD3D11ViewArr[ShaderInd]; + auto* Resources = CommittedD3D11ResourcesArr[ShaderInd]; + auto NumCommittedResources = NumCommittedResourcesArr[ShaderInd]; for (Uint32 Slot = 0; Slot < NumCommittedResources; ++Slot) { if (Views[Slot] != nullptr) @@ -2449,29 +2228,29 @@ void DeviceContextD3D11Impl::dbgVerifyViewConsistency(TD3D11ViewType CommittedD } } -void DeviceContextD3D11Impl::dbgVerifyCommittedSRVs(SHADER_TYPE ShaderType) +void DeviceContextD3D11Impl::DvpVerifyCommittedSRVs(SHADER_TYPE ShaderStages) { - dbgVerifyCommittedResources(m_CommittedD3D11SRVs, m_NumCommittedSRVs, GetSRVMethods, "SRV", ShaderType); - dbgVerifyViewConsistency(m_CommittedD3D11SRVs, m_CommittedD3D11SRVResources, m_NumCommittedSRVs, "SRV", ShaderType); + DvpVerifyCommittedResources(m_CommittedRes.D3D11SRVs, m_CommittedRes.NumSRVs, GetSRVMethods, "SRV", ShaderStages); + DvpVerifyViewConsistency(m_CommittedRes.D3D11SRVs, m_CommittedRes.D3D11SRVResources, m_CommittedRes.NumSRVs, "SRV", ShaderStages); } -void DeviceContextD3D11Impl::dbgVerifyCommittedUAVs(SHADER_TYPE ShaderType) +void DeviceContextD3D11Impl::DvpVerifyCommittedUAVs(SHADER_TYPE ShaderStages) { - dbgVerifyCommittedResources(m_CommittedD3D11UAVs, m_NumCommittedUAVs, GetUAVMethods, "UAV", ShaderType); - dbgVerifyViewConsistency(m_CommittedD3D11UAVs, m_CommittedD3D11UAVResources, m_NumCommittedUAVs, "UAV", ShaderType); + DvpVerifyCommittedResources(m_CommittedRes.D3D11UAVs, m_CommittedRes.NumUAVs, GetUAVMethods, "UAV", ShaderStages); + DvpVerifyViewConsistency(m_CommittedRes.D3D11UAVs, m_CommittedRes.D3D11UAVResources, m_CommittedRes.NumUAVs, "UAV", ShaderStages); } -void DeviceContextD3D11Impl::dbgVerifyCommittedSamplers(SHADER_TYPE ShaderType) +void DeviceContextD3D11Impl::DvpVerifyCommittedSamplers(SHADER_TYPE ShaderStages) { - dbgVerifyCommittedResources(m_CommittedD3D11Samplers, m_NumCommittedSamplers, GetSamplerMethods, "Sampler", ShaderType); + DvpVerifyCommittedResources(m_CommittedRes.D3D11Samplers, m_CommittedRes.NumSamplers, GetSamplerMethods, "Sampler", ShaderStages); } -void DeviceContextD3D11Impl::dbgVerifyCommittedCBs(SHADER_TYPE ShaderType) +void DeviceContextD3D11Impl::DvpVerifyCommittedCBs(SHADER_TYPE ShaderStages) { - dbgVerifyCommittedResources(m_CommittedD3D11CBs, m_NumCommittedCBs, GetCBMethods, "Constant buffer", ShaderType); + DvpVerifyCommittedResources(m_CommittedRes.D3D11CBs, m_CommittedRes.NumCBs, GetCBMethods, "Constant buffer", ShaderStages); } -void DeviceContextD3D11Impl::dbgVerifyCommittedIndexBuffer() +void DeviceContextD3D11Impl::DvpVerifyCommittedIndexBuffer() { RefCntAutoPtr pctxIndexBuffer; DXGI_FORMAT Fmt = DXGI_FORMAT_UNKNOWN; @@ -2497,7 +2276,7 @@ void DeviceContextD3D11Impl::dbgVerifyCommittedIndexBuffer() } } -void DeviceContextD3D11Impl::dbgVerifyCommittedVertexBuffers() +void DeviceContextD3D11Impl::DvpVerifyCommittedVertexBuffers() { CComPtr pInputLayout; m_pd3d11DeviceContext->IAGetInputLayout(&pInputLayout); @@ -2538,7 +2317,7 @@ void DeviceContextD3D11Impl::dbgVerifyCommittedVertexBuffers() } template -void dbgVerifyCommittedShadersHelper(SHADER_TYPE ShaderType, +void DvpVerifyCommittedShadersHelper(SHADER_TYPE ShaderType, const CComPtr BoundD3DShaders[], ID3D11DeviceContext* pCtx, TGetShaderMethodType GetShaderMethod) @@ -2548,9 +2327,9 @@ void dbgVerifyCommittedShadersHelper(SHADER_TYPE ShaderType const auto& BoundShader = BoundD3DShaders[GetShaderTypeIndex(ShaderType)]; VERIFY(BoundShader == pctxShader, GetShaderTypeLiteralName(ShaderType), " binding mismatch detected"); } -void DeviceContextD3D11Impl::dbgVerifyCommittedShaders() +void DeviceContextD3D11Impl::DvpVerifyCommittedShaders() { -# define VERIFY_SHADER(NAME, Name, N) dbgVerifyCommittedShadersHelper(SHADER_TYPE_##NAME, m_CommittedD3DShaders, m_pd3d11DeviceContext, &ID3D11DeviceContext::N##SGetShader) +# define VERIFY_SHADER(NAME, Name, N) DvpVerifyCommittedShadersHelper(SHADER_TYPE_##NAME, m_CommittedD3DShaders, m_pd3d11DeviceContext, &ID3D11DeviceContext::N##SGetShader) // These shaders which are not set will be unbound from the D3D11 device context VERIFY_SHADER(VERTEX, Vertex, V); VERIFY_SHADER(PIXEL, Pixel, P); diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineResourceSignatureD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineResourceSignatureD3D11Impl.cpp new file mode 100644 index 00000000..aab59266 --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/src/PipelineResourceSignatureD3D11Impl.cpp @@ -0,0 +1,489 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" +#include "PipelineResourceSignatureD3D11Impl.hpp" +#include "RenderDeviceD3D11Impl.hpp" + +namespace Diligent +{ + +DESCRIPTOR_RANGE ShaderResourceToDescriptorRange(SHADER_RESOURCE_TYPE Type) +{ + static_assert(SHADER_RESOURCE_TYPE_LAST == 8, "Please update the switch below to handle the new shader resource type"); + switch (Type) + { + // clang-format off + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: return DESCRIPTOR_RANGE_CBV; + case SHADER_RESOURCE_TYPE_TEXTURE_SRV: return DESCRIPTOR_RANGE_SRV; + case SHADER_RESOURCE_TYPE_BUFFER_SRV: return DESCRIPTOR_RANGE_SRV; + case SHADER_RESOURCE_TYPE_TEXTURE_UAV: return DESCRIPTOR_RANGE_UAV; + case SHADER_RESOURCE_TYPE_BUFFER_UAV: return DESCRIPTOR_RANGE_UAV; + case SHADER_RESOURCE_TYPE_SAMPLER: return DESCRIPTOR_RANGE_SAMPLER; + case SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT: return DESCRIPTOR_RANGE_SRV; + // clang-format on + default: + UNEXPECTED("Unsupported resource type"); + return DESCRIPTOR_RANGE_UNKNOWN; + } +} + + +PipelineResourceSignatureD3D11Impl::PipelineResourceSignatureD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pDeviceD3D11, + const PipelineResourceSignatureDesc& Desc, + bool bIsDeviceInternal) : + TPipelineResourceSignatureBase{pRefCounters, pDeviceD3D11, Desc, bIsDeviceInternal} +{ + try + { + auto& RawAllocator{GetRawAllocator()}; + auto MemPool = AllocateInternalObjects(RawAllocator, Desc, + [&Desc](FixedLinearAllocator& MemPool) // + { + MemPool.AddSpace(Desc.NumResources); + MemPool.AddSpace(Desc.NumImmutableSamplers); + }); + + static_assert(std::is_trivially_destructible::value, + "ResourceAttribs objects must be constructed to be properly destructed in case an excpetion is thrown"); + m_pResourceAttribs = MemPool.Allocate(m_Desc.NumResources); + m_ImmutableSamplers = MemPool.ConstructArray(m_Desc.NumImmutableSamplers); + + CreateLayout(); + + const auto NumStaticResStages = GetNumStaticResStages(); + if (NumStaticResStages > 0) + { + constexpr SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; + for (Uint32 i = 0; i < m_StaticResStageIndex.size(); ++i) + { + Int8 Idx = m_StaticResStageIndex[i]; + if (Idx >= 0) + { + VERIFY_EXPR(static_cast(Idx) < NumStaticResStages); + const auto ShaderType = GetShaderTypeFromPipelineIndex(i, GetPipelineType()); + m_StaticVarsMgrs[Idx].Initialize(*this, GetRawAllocator(), AllowedVarTypes, _countof(AllowedVarTypes), ShaderType); + } + } + } + + if (m_Desc.SRBAllocationGranularity > 1) + { + std::array ShaderVariableDataSizes = {}; + for (Uint32 s = 0; s < GetNumActiveShaderStages(); ++s) + { + constexpr SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; + + ShaderVariableDataSizes[s] = ShaderVariableManagerD3D11::GetRequiredMemorySize(*this, AllowedVarTypes, _countof(AllowedVarTypes), GetActiveShaderStageType(s)); + } + + const size_t CacheMemorySize = ShaderResourceCacheD3D11::GetRequriedMemorySize(m_ResourceCount); + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumActiveShaderStages(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize); + } + + CalculateHash(); + } + catch (...) + { + Destruct(); + throw; + } +} + +void PipelineResourceSignatureD3D11Impl::CreateLayout() +{ + using TBindings32 = std::array; + using TBindingsPerStage32 = std::array; + + if (m_pStaticResCache) + { + TBindings32 StaticCounter32 = {}; + const auto ResIdxRange = GetResourceIndexRange(SHADER_RESOURCE_VARIABLE_TYPE_STATIC); + for (Uint32 r = ResIdxRange.first; r < ResIdxRange.second; ++r) + { + const auto& ResDesc = m_Desc.Resources[r]; + const auto Range = ShaderResourceToDescriptorRange(ResDesc.ResourceType); + StaticCounter32[Range] += ResDesc.ArraySize; + } + + TBindings StaticCounter8 = {}; + for (Uint32 i = 0; i < StaticCounter8.size(); ++i) + { + VERIFY_EXPR(StaticCounter8[i] < std::numeric_limits::max()); + StaticCounter8[i] = static_cast(StaticCounter32[i]); + } + + m_pStaticResCache->Initialize(StaticCounter8, GetRawAllocator()); + } + + // 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 or texture in m_Desc.Resources, or InvalidImmutableSamplerIndex. + std::vector ResourceToImmutableSamplerInd(m_Desc.NumResources, InvalidImmutableSamplerIndex); + for (Uint32 i = 0; i < m_Desc.NumResources; ++i) + { + const auto& ResDesc = m_Desc.Resources[i]; + + if (ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER || + ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV) + { + const char* SamplerSuffix = ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER ? GetCombinedSamplerSuffix() : nullptr; + const auto SrcImmutableSamplerInd = Diligent::FindImmutableSampler(m_Desc.ImmutableSamplers, m_Desc.NumImmutableSamplers, ResDesc.ShaderStages, ResDesc.Name, SamplerSuffix); + if (SrcImmutableSamplerInd != InvalidImmutableSamplerIndex) + { + 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 + const auto ImtblSampArraySize = std::max(DstImtblSampAttribs.ArraySize, ResDesc.ArraySize); + DstImtblSampAttribs.ArraySize = ImtblSampArraySize; + VERIFY(DstImtblSampAttribs.ArraySize == ImtblSampArraySize, "Immutable sampler array size exceeds maximum representable value"); + } + } + + if (ResourceToImmutableSamplerInd[i] == InvalidImmutableSamplerIndex && + ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV) + { + TextureSrvToAssignedSamplerInd[i] = FindAssignedSampler(ResDesc, ResourceAttribs::InvalidSamplerInd); + } + } + + TBindings32 ResourceCount = {}; + TBindingsPerStage32 BindingPerStage = {}; + const auto AllocBindPoints = [&BindingPerStage](TBindPoints& BindPoints, SHADER_TYPE ShaderStages, Uint32 ArraySize, DESCRIPTOR_RANGE Range) // + { + while (ShaderStages != 0) + { + auto Stage = ExtractLSB(ShaderStages); + Uint32 ShaderInd = GetShaderTypeIndex(Stage); + + BindPoints[ShaderInd] = static_cast(BindingPerStage[ShaderInd][Range]); + VERIFY_EXPR(BindPoints[ShaderInd] == BindingPerStage[ShaderInd][Range]); + BindingPerStage[ShaderInd][Range] += ArraySize; + } + }; + + for (Uint32 i = 0; i < m_Desc.NumResources; ++i) + { + const auto& ResDesc = m_Desc.Resources[i]; + const auto Range = ShaderResourceToDescriptorRange(ResDesc.ResourceType); + VERIFY(i == 0 || ResDesc.VarType >= m_Desc.Resources[i - 1].VarType, "Resources must be sorted by variable type"); + + auto AssignedSamplerInd = TextureSrvToAssignedSamplerInd[i]; + auto SrcImmutableSamplerInd = ResourceToImmutableSamplerInd[i]; + if (AssignedSamplerInd != ResourceAttribs::InvalidSamplerInd) + { + VERIFY_EXPR(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV); + SrcImmutableSamplerInd = ResourceToImmutableSamplerInd[AssignedSamplerInd]; + } + + constexpr SHADER_TYPE UAVStages = SHADER_TYPE_PIXEL | SHADER_TYPE_COMPUTE; + if (Range == DESCRIPTOR_RANGE_UAV && (ResDesc.ShaderStages & ~UAVStages) != 0) + { + LOG_ERROR_AND_THROW("Description of a pipeline resource signature '", m_Desc.Name, "' is invalid: ", + "Desc.Resources[", i, "].ResourceType (", GetShaderResourceTypeLiteralName(ResDesc.ResourceType), + ") - UAV resource is not supported in shader stages ", GetShaderStagesString(ResDesc.ShaderStages & ~UAVStages)); + } + + // Allocate space for immutable sampler which is assigned to sampler or texture resource. + if (SrcImmutableSamplerInd != InvalidImmutableSamplerIndex) + { + const auto& ImtblSamp = GetImmutableSamplerDesc(SrcImmutableSamplerInd); + auto& ImtblSampAttribs = m_ImmutableSamplers[SrcImmutableSamplerInd]; + VERIFY_EXPR(ResDesc.ArraySize <= ImtblSampAttribs.ArraySize); + + if (!ImtblSampAttribs.IsAllocated()) + { + ImtblSampAttribs.CacheOffset = ResourceCount[DESCRIPTOR_RANGE_SAMPLER]; + AllocBindPoints(ImtblSampAttribs.BindPoints, ImtblSamp.ShaderStages, ImtblSampAttribs.ArraySize, DESCRIPTOR_RANGE_SAMPLER); + ResourceCount[DESCRIPTOR_RANGE_SAMPLER] += ImtblSampAttribs.ArraySize; + } + } + + if (!(ResDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER && SrcImmutableSamplerInd != InvalidImmutableSamplerIndex)) + { + auto* pAttrib = new (m_pResourceAttribs + i) ResourceAttribs // + { + ResourceCount[Range], + AssignedSamplerInd, + SrcImmutableSamplerInd != InvalidImmutableSamplerIndex // + }; + AllocBindPoints(pAttrib->BindPoints, ResDesc.ShaderStages, ResDesc.ArraySize, Range); + ResourceCount[Range] += ResDesc.ArraySize; + } + else + { + VERIFY_EXPR(AssignedSamplerInd == ResourceAttribs::InvalidSamplerInd); + + auto& ImtblSampAttribs = m_ImmutableSamplers[SrcImmutableSamplerInd]; + auto* pAttrib = new (m_pResourceAttribs + i) ResourceAttribs // + { + ImtblSampAttribs.CacheOffset, + ResourceAttribs::InvalidSamplerInd, + SrcImmutableSamplerInd != InvalidImmutableSamplerIndex // + }; + pAttrib->BindPoints = ImtblSampAttribs.BindPoints; + } + } + + // Add bindings for immutable samplers that is not assigned to texture or separate sampler. + for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i) + { + const auto Range = DESCRIPTOR_RANGE_SAMPLER; + const auto& ImtblSamp = GetImmutableSamplerDesc(i); + auto& ImtblSampAttribs = m_ImmutableSamplers[i]; + + if (IsUsingCombinedSamplers() && !ImtblSampAttribs.IsAllocated()) + continue; + + GetDevice()->CreateSampler(ImtblSamp.Desc, &ImtblSampAttribs.pSampler); + + // Add as separate sampler. + if (!ImtblSampAttribs.IsAllocated()) + { + ImtblSampAttribs.ArraySize = 1; + ImtblSampAttribs.CacheOffset = ResourceCount[Range]; + ResourceCount[Range] += ImtblSampAttribs.ArraySize; + AllocBindPoints(ImtblSampAttribs.BindPoints, ImtblSamp.ShaderStages, ImtblSampAttribs.ArraySize, Range); + } + } + + for (Uint32 i = 0; i < ResourceCount.size(); ++i) + { + using T = std::remove_reference::type; + VERIFY_EXPR(ResourceCount[i] < std::numeric_limits::max()); + m_ResourceCount[i] = static_cast(ResourceCount[i]); + } + + for (Uint32 s = 0; s < BindingPerStage.size(); ++s) + { + for (Uint32 i = 0; i < BindingPerStage[s].size(); ++i) + { + using T = std::remove_reference::type; + VERIFY_EXPR(BindingPerStage[s][i] < std::numeric_limits::max()); + m_BindingCountPerStage[s][i] = static_cast(BindingPerStage[s][i]); + } + } +} + +PipelineResourceSignatureD3D11Impl::~PipelineResourceSignatureD3D11Impl() +{ + Destruct(); +} + +void PipelineResourceSignatureD3D11Impl::Destruct() +{ + if (m_ImmutableSamplers != nullptr) + { + for (Uint32 s = 0; s < m_Desc.NumImmutableSamplers; ++s) + m_ImmutableSamplers[s].~ImmutableSamplerAttribs(); + + m_ImmutableSamplers = nullptr; + } + + m_pResourceAttribs = nullptr; + + TPipelineResourceSignatureBase::Destruct(); +} + +void PipelineResourceSignatureD3D11Impl::CopyStaticResources(ShaderResourceCacheD3D11& DstResourceCache) const +{ + if (m_pStaticResCache == nullptr) + return; + + // SrcResourceCache contains only static resources. + // DstResourceCache contains static, mutable and dynamic resources. + const auto& SrcResourceCache = *m_pStaticResCache; + const auto ResIdxRange = GetResourceIndexRange(SHADER_RESOURCE_VARIABLE_TYPE_STATIC); + + VERIFY_EXPR(SrcResourceCache.GetContentType() == ResourceCacheContentType::Signature); + VERIFY_EXPR(DstResourceCache.GetContentType() == ResourceCacheContentType::SRB); + + for (Uint32 r = ResIdxRange.first; r < ResIdxRange.second; ++r) + { + const auto& ResDesc = GetResourceDesc(r); + const auto& ResAttr = GetResourceAttribs(r); + VERIFY_EXPR(ResDesc.VarType == SHADER_RESOURCE_VARIABLE_TYPE_STATIC); + + static_assert(DESCRIPTOR_RANGE_COUNT == 4, "Please update the switch below to handle the new descriptor range"); + switch (ShaderResourceToDescriptorRange(ResDesc.ResourceType)) + { + case DESCRIPTOR_RANGE_CBV: + for (Uint32 ArrInd = 0; ArrInd < ResDesc.ArraySize; ++ArrInd) + { + const auto& SrcCachedRes = SrcResourceCache.GetCB(ResAttr.CacheOffset + ArrInd); + if (!SrcCachedRes.pBuff) + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetShaderResourcePrintName(ResDesc, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'."); + + DstResourceCache.SetCB(ResAttr.CacheOffset, ArrInd, ResAttr.BindPoints, RefCntAutoPtr{SrcCachedRes.pBuff}); + } + break; + case DESCRIPTOR_RANGE_SRV: + for (Uint32 ArrInd = 0; ArrInd < ResDesc.ArraySize; ++ArrInd) + { + const auto& SrcCachedRes = SrcResourceCache.GetSRV(ResAttr.CacheOffset + ArrInd); + if (!SrcCachedRes.pBuffer && !SrcCachedRes.pTexture) + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetShaderResourcePrintName(ResDesc, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'."); + + if (SrcCachedRes.pTexture) + DstResourceCache.SetTexSRV(ResAttr.CacheOffset, ArrInd, ResAttr.BindPoints, RefCntAutoPtr{SrcCachedRes.pView.RawPtr()}); + else + DstResourceCache.SetBufSRV(ResAttr.CacheOffset, ArrInd, ResAttr.BindPoints, RefCntAutoPtr{SrcCachedRes.pView.RawPtr()}); + } + break; + case DESCRIPTOR_RANGE_SAMPLER: + // Immutable samplers will be copied in InitSRBResourceCache(). + if (!ResAttr.IsImmutableSamplerAssigned()) + { + for (Uint32 ArrInd = 0; ArrInd < ResDesc.ArraySize; ++ArrInd) + { + const auto& SrcCachedRes = SrcResourceCache.GetSampler(ResAttr.CacheOffset + ArrInd); + if (!SrcCachedRes.pSampler) + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetShaderResourcePrintName(ResDesc, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'."); + + DstResourceCache.SetSampler(ResAttr.CacheOffset, ArrInd, ResAttr.BindPoints, RefCntAutoPtr{SrcCachedRes.pSampler}); + } + } + break; + case DESCRIPTOR_RANGE_UAV: + for (Uint32 ArrInd = 0; ArrInd < ResDesc.ArraySize; ++ArrInd) + { + const auto& SrcCachedRes = SrcResourceCache.GetUAV(ResAttr.CacheOffset + ArrInd); + if (!SrcCachedRes.pBuffer && !SrcCachedRes.pTexture) + LOG_ERROR_MESSAGE("No resource is assigned to static shader variable '", GetShaderResourcePrintName(ResDesc, ArrInd), "' in pipeline resource signature '", m_Desc.Name, "'."); + + if (SrcCachedRes.pTexture) + DstResourceCache.SetTexUAV(ResAttr.CacheOffset, ArrInd, ResAttr.BindPoints, RefCntAutoPtr{SrcCachedRes.pView.RawPtr()}); + else + DstResourceCache.SetBufUAV(ResAttr.CacheOffset, ArrInd, ResAttr.BindPoints, RefCntAutoPtr{SrcCachedRes.pView.RawPtr()}); + } + break; + default: + UNEXPECTED("Unsupported descriptor range type."); + } + } +} + +void PipelineResourceSignatureD3D11Impl::InitSRBResourceCache(ShaderResourceCacheD3D11& ResourceCache) +{ + ResourceCache.Initialize(m_ResourceCount, m_SRBMemAllocator.GetResourceCacheDataAllocator(0)); + + // Copy immutable samplers. + for (Uint32 i = 0; i < m_Desc.NumImmutableSamplers; ++i) + { + const auto& ImtblSampAttr = GetImmutableSamplerAttribs(i); + + if (ImtblSampAttr.IsAllocated()) + { + SamplerD3D11Impl* pSampler = ImtblSampAttr.GetSamplerD3D11(); + VERIFY_EXPR(pSampler != nullptr); + VERIFY_EXPR(ImtblSampAttr.ArraySize > 0); + + for (Uint32 ArrInd = 0; ArrInd < ImtblSampAttr.ArraySize; ++ArrInd) + ResourceCache.SetSampler(ImtblSampAttr.CacheOffset, ArrInd, ImtblSampAttr.BindPoints, pSampler); + } + } +} + +void PipelineResourceSignatureD3D11Impl::UpdateShaderResourceBindingMap(ResourceBinding::TMap& ResourceMap, SHADER_TYPE ShaderStage, const TBindingsPerStage& BaseBindings) const +{ + VERIFY(ShaderStage != SHADER_TYPE_UNKNOWN && IsPowerOfTwo(ShaderStage), "Only single shader stage must be provided."); + const auto ShaderInd = GetShaderTypeIndex(ShaderStage); + + for (Uint32 r = 0, ResCount = GetTotalResourceCount(); r < ResCount; ++r) + { + const auto& ResDesc = GetResourceDesc(r); + const auto& ResAttr = GetResourceAttribs(r); + const auto Range = ShaderResourceToDescriptorRange(ResDesc.ResourceType); + + if ((ResDesc.ShaderStages & ShaderStage) != 0) + { + VERIFY_EXPR(ResAttr.BindPoints[ShaderInd] != InvalidBindPoint); + ResourceBinding::BindInfo BindInfo // + { + Uint32{BaseBindings[ShaderInd][Range]} + ResAttr.BindPoints[ShaderInd], + 0u, // register space is not supported + ResDesc.ArraySize, + ResDesc.ResourceType // + }; + auto IsUnique = ResourceMap.emplace(HashMapStringKey{ResDesc.Name}, BindInfo).second; + VERIFY(IsUnique, "Shader resource '", ResDesc.Name, + "' already present in the binding map. Every shader resource in PSO must be unambiguously defined by " + "only one resource signature. This error should've been caught by ValidatePipelineResourceSignatures()."); + } + } + + for (Uint32 samp = 0, SampCount = GetImmutableSamplerCount(); samp < SampCount; ++samp) + { + const auto& ImtblSam = GetImmutableSamplerDesc(samp); + const auto& SampAttr = GetImmutableSamplerAttribs(samp); + const auto Range = DESCRIPTOR_RANGE_SAMPLER; + + if ((ImtblSam.ShaderStages & ShaderStage) != 0 && SampAttr.IsAllocated()) + { + VERIFY_EXPR(SampAttr.BindPoints[ShaderInd] != InvalidBindPoint); + + String SampName{ImtblSam.SamplerOrTextureName}; + if (IsUsingCombinedSamplers()) + SampName += GetCombinedSamplerSuffix(); + + ResourceBinding::BindInfo BindInfo // + { + Uint32{BaseBindings[ShaderInd][Range]} + SampAttr.BindPoints[ShaderInd], + 0u, // register space is not supported + SampAttr.ArraySize, + SHADER_RESOURCE_TYPE_SAMPLER // + }; + + 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."); + } +#endif + } + } +} + +// AZ TODO +#if 0 //def DILIGENT_DEVELOPMENT +bool PipelineResourceSignatureGLImpl::DvpValidateCommittedResource(const D3DShaderResourceAttribs& D3DAttribs, + RESOURCE_DIMENSION ResourceDim, + bool IsMultisample, + Uint32 ResIndex, + const ShaderResourceCacheD3D11& ResourceCache, + const char* ShaderName, + const char* PSOName) const +{ +} +#endif // DILIGENT_DEVELOPMENT + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 933e2978..2cedc96a 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -27,100 +27,360 @@ #include "pch.h" #include +#include + #include "PipelineStateD3D11Impl.hpp" #include "RenderDeviceD3D11Impl.hpp" #include "ShaderResourceBindingD3D11Impl.hpp" #include "EngineMemory.h" +#include "DXBCUtils.hpp" namespace Diligent { +namespace +{ +void GetShaderResourceTypeAndFlags(const D3DShaderResourceAttribs& Attribs, + SHADER_RESOURCE_TYPE& OutType, + PIPELINE_RESOURCE_FLAGS& OutFlags) +{ + OutFlags = PIPELINE_RESOURCE_FLAG_UNKNOWN; -template -void PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo) + switch (int{Attribs.GetInputType()}) + { + case D3D_SIT_CBUFFER: + OutType = SHADER_RESOURCE_TYPE_CONSTANT_BUFFER; + break; + case D3D_SIT_TBUFFER: + UNSUPPORTED("TBuffers are not supported"); + OutType = SHADER_RESOURCE_TYPE_TEXTURE_SRV; + break; + case D3D_SIT_TEXTURE: + if (Attribs.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER) + { + OutType = SHADER_RESOURCE_TYPE_BUFFER_SRV; + OutFlags = PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER; + } + else + OutType = SHADER_RESOURCE_TYPE_TEXTURE_SRV; + break; + case D3D_SIT_SAMPLER: + OutType = SHADER_RESOURCE_TYPE_SAMPLER; + break; + case D3D_SIT_UAV_RWTYPED: + if (Attribs.GetSRVDimension() == D3D_SRV_DIMENSION_BUFFER) + { + OutType = SHADER_RESOURCE_TYPE_BUFFER_UAV; + OutFlags = PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER; + } + else + OutType = SHADER_RESOURCE_TYPE_TEXTURE_UAV; + break; + case D3D_SIT_STRUCTURED: + case D3D_SIT_BYTEADDRESS: + OutType = SHADER_RESOURCE_TYPE_BUFFER_SRV; + break; + case D3D_SIT_UAV_RWSTRUCTURED: + case D3D_SIT_UAV_RWBYTEADDRESS: + case D3D_SIT_UAV_APPEND_STRUCTURED: + case D3D_SIT_UAV_CONSUME_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER: + OutType = SHADER_RESOURCE_TYPE_BUFFER_UAV; + break; + default: + UNEXPECTED("Unknown HLSL resource type"); + OutType = SHADER_RESOURCE_TYPE_UNKNOWN; + break; + } +} + +void VerifyResourceMerge(const PipelineStateDesc& PSODesc, + const D3DShaderResourceAttribs& ExistingRes, + const D3DShaderResourceAttribs& NewResAttribs) +{ +#define LOG_RESOURCE_MERGE_ERROR_AND_THROW(PropertyName) \ + LOG_ERROR_AND_THROW("Shader variable '", NewResAttribs.Name, \ + "' is shared between multiple shaders in pipeline '", (PSODesc.Name ? PSODesc.Name : ""), \ + "', but its " PropertyName " varies. A variable shared between multiple shaders " \ + "must be defined identically in all shaders. Either use separate variables for " \ + "different shader stages, change resource name or make sure that " PropertyName " is consistent."); + + if (ExistingRes.GetInputType() != NewResAttribs.GetInputType()) + LOG_RESOURCE_MERGE_ERROR_AND_THROW("input type"); + + if (ExistingRes.GetSRVDimension() != NewResAttribs.GetSRVDimension()) + LOG_RESOURCE_MERGE_ERROR_AND_THROW("resource dimension"); + + if (ExistingRes.BindCount != NewResAttribs.BindCount) + LOG_RESOURCE_MERGE_ERROR_AND_THROW("array size"); + + if (ExistingRes.IsMultisample() != NewResAttribs.IsMultisample()) + LOG_RESOURCE_MERGE_ERROR_AND_THROW("mutlisample state"); +#undef LOG_RESOURCE_MERGE_ERROR_AND_THROW +} + +} // namespace + + +RefCntAutoPtr PipelineStateD3D11Impl::CreateDefaultResourceSignature( + const PipelineStateCreateInfo& CreateInfo, + const std::vector& Shaders) { - m_ResourceLayoutIndex.fill(-1); + const auto& LayoutDesc = CreateInfo.PSODesc.ResourceLayout; + + struct UniqueResource + { + const D3DShaderResourceAttribs& Attribs; + const SHADER_TYPE ShaderStages; + + bool operator==(const UniqueResource& Res) const + { + return strcmp(Attribs.Name, Res.Attribs.Name) == 0 && ShaderStages == Res.ShaderStages; + } + + struct Hasher + { + size_t operator()(const UniqueResource& Res) const + { + return ComputeHash(CStringHash{}(Res.Attribs.Name), Uint32{Res.ShaderStages}); + } + }; + }; + std::unordered_set UniqueResources; + + std::vector Resources; + const char* pCombinedSamplerSuffix = nullptr; + + for (auto* pShader : Shaders) + { + const auto& ShaderResources = *pShader->GetShaderResources(); + + ShaderResources.ProcessResources( + [&](const D3DShaderResourceAttribs& Attribs, Uint32) // + { + const char* const SamplerSuffix = + (ShaderResources.IsUsingCombinedTextureSamplers() && Attribs.GetInputType() == D3D_SIT_SAMPLER) ? + ShaderResources.GetCombinedSamplerSuffix() : + nullptr; + + // Use default variable type and current shader stages + auto ShaderStages = pShader->GetDesc().ShaderType; + auto VarType = LayoutDesc.DefaultVariableType; + + const auto VarIndex = FindPipelineResourceLayoutVariable(LayoutDesc, Attribs.Name, ShaderStages, SamplerSuffix); + if (VarIndex != InvalidPipelineResourceLayoutVariableIndex) + { + const auto& Var = LayoutDesc.Variables[VarIndex]; + // Use shader stages and variable type from the variable desc + ShaderStages = Var.ShaderStages; + VarType = Var.Type; + } + + auto IterAndAssigned = UniqueResources.emplace(UniqueResource{Attribs, ShaderStages}); + if (IterAndAssigned.second) + { + SHADER_RESOURCE_TYPE ResType = SHADER_RESOURCE_TYPE_UNKNOWN; + PIPELINE_RESOURCE_FLAGS Flags = PIPELINE_RESOURCE_FLAG_UNKNOWN; + GetShaderResourceTypeAndFlags(Attribs, ResType, Flags); + + if (Attribs.BindCount == 0) + { + LOG_ERROR_AND_THROW("Resource '", Attribs.Name, "' in shader '", pShader->GetDesc().Name, "' is a runtime-sized array. ", + "Use explicit resource signature to specify the array size."); + } + + Resources.emplace_back(ShaderStages, Attribs.Name, Attribs.BindCount, ResType, VarType, Flags); + } + else + { + VerifyResourceMerge(CreateInfo.PSODesc, IterAndAssigned.first->Attribs, Attribs); + } + } // + ); + + // merge combined sampler suffixes + if (ShaderResources.IsUsingCombinedTextureSamplers() && ShaderResources.GetNumSamplers() > 0) + { + if (pCombinedSamplerSuffix != nullptr) + { + if (strcmp(pCombinedSamplerSuffix, ShaderResources.GetCombinedSamplerSuffix()) != 0) + LOG_ERROR_AND_THROW("CombinedSamplerSuffix is not compatible between shaders"); + } + else + { + pCombinedSamplerSuffix = ShaderResources.GetCombinedSamplerSuffix(); + } + } + } + + RefCntAutoPtr pSignature; + if (Resources.size()) + { + PipelineResourceSignatureDesc ResSignDesc; + ResSignDesc.Resources = Resources.data(); + ResSignDesc.NumResources = static_cast(Resources.size()); + ResSignDesc.ImmutableSamplers = LayoutDesc.ImmutableSamplers; + ResSignDesc.NumImmutableSamplers = LayoutDesc.NumImmutableSamplers; + ResSignDesc.BindingIndex = 0; + ResSignDesc.SRBAllocationGranularity = CreateInfo.PSODesc.SRBAllocationGranularity; + ResSignDesc.UseCombinedTextureSamplers = pCombinedSamplerSuffix != nullptr; + ResSignDesc.CombinedSamplerSuffix = pCombinedSamplerSuffix; + + constexpr bool bIsDeviceInternal = true; + GetDevice()->CreatePipelineResourceSignature(ResSignDesc, pSignature.DblPtr(), bIsDeviceInternal); + + if (!pSignature) + LOG_ERROR_AND_THROW("Failed to create implicit resource signature for pipeline state '", (CreateInfo.PSODesc.Name ? CreateInfo.PSODesc.Name : ""), "'."); + } + + return pSignature; +} + +void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, + const std::vector& Shaders, + std::vector>& ByteCodes) +{ + if (m_UsingImplicitSignature) + { + VERIFY_EXPR(m_SignatureCount == 1); + m_Signatures[0] = CreateDefaultResourceSignature(CreateInfo, Shaders); + VERIFY_EXPR(!m_Signatures[0] || m_Signatures[0]->GetDesc().BindingIndex == 0); + } + // Verify that pipeline layout is compatible with shader resources and remap resource bindings. + ByteCodes.resize(Shaders.size()); + for (size_t s = 0; s < Shaders.size(); ++s) + { + const auto* const pShader = Shaders[s]; + const auto ShaderType = pShader->GetDesc().ShaderType; + auto* pBytecode = Shaders[s]->GetBytecode(); + + PipelineResourceSignatureD3D11Impl::TBindingsPerStage BindingsPerStage = {}; + if (m_Desc.IsAnyGraphicsPipeline()) + BindingsPerStage[PSInd][DESCRIPTOR_RANGE_UAV] = GetGraphicsPipelineDesc().NumRenderTargets; + + ResourceBinding::TMap ResourceMap; + for (Uint32 sign = 0; sign < m_SignatureCount; ++sign) + { + const PipelineResourceSignatureD3D11Impl* const pSignature = m_Signatures[sign]; + if (pSignature == nullptr) + continue; + + VERIFY_EXPR(pSignature->GetDesc().BindingIndex == sign); + pSignature->UpdateShaderResourceBindingMap(ResourceMap, ShaderType, BindingsPerStage); + pSignature->AddBindings(BindingsPerStage); + } + + ValidateShaderResources(pShader); + + CComPtr pBlob; + D3DCreateBlob(pBytecode->GetBufferSize(), &pBlob); + memcpy(pBlob->GetBufferPointer(), pBytecode->GetBufferPointer(), pBytecode->GetBufferSize()); + + if (!DXBCUtils::RemapResourceBindings(ResourceMap, pBlob->GetBufferPointer(), pBlob->GetBufferSize())) + LOG_ERROR_AND_THROW("Failed to remap resource bindings in shader '", pShader->GetDesc().Name, "'."); + + ByteCodes[s] = pBlob; + } + +#ifdef DILIGENT_DEVELOPMENT + PipelineResourceSignatureD3D11Impl::TBindingsPerStage BindingsPerStage = {}; + + if (m_Desc.IsAnyGraphicsPipeline()) + BindingsPerStage[PSInd][DESCRIPTOR_RANGE_UAV] = GetGraphicsPipelineDesc().NumRenderTargets; + + for (Uint32 sign = 0; sign < m_SignatureCount; ++sign) + { + const auto& pSignature = m_Signatures[sign]; + if (pSignature != nullptr) + pSignature->AddBindings(BindingsPerStage); + } + + for (Uint32 s = 0; s < BindingsPerStage.size(); ++s) + { + const auto& BindCount = BindingsPerStage[s]; + + DEV_CHECK_ERR(BindCount[DESCRIPTOR_RANGE_CBV] <= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, + "Constant buffer count ", Uint32{BindCount[DESCRIPTOR_RANGE_CBV]}, " exceeds D3D11 limit ", D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); + DEV_CHECK_ERR(BindCount[DESCRIPTOR_RANGE_SRV] <= D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, + "SRV count ", Uint32{BindCount[DESCRIPTOR_RANGE_SRV]}, " exceeds D3D11 limit ", D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT); + DEV_CHECK_ERR(BindCount[DESCRIPTOR_RANGE_SAMPLER] <= D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, + "Sampler count ", Uint32{BindCount[DESCRIPTOR_RANGE_SAMPLER]}, " exceeds D3D11 limit ", D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT); + DEV_CHECK_ERR(BindCount[DESCRIPTOR_RANGE_UAV] <= D3D11_PS_CS_UAV_REGISTER_COUNT, + "UAV count ", Uint32{BindCount[DESCRIPTOR_RANGE_UAV]}, " exceeds D3D11 limit ", D3D11_PS_CS_UAV_REGISTER_COUNT); + } +#endif +} + +template +void PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector>& ByteCodes) +{ std::vector Shaders; ExtractShaders(CreateInfo, Shaders); - const auto NumShaderStages = GetNumShaderStages(); - VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == Shaders.size()); + m_NumShaders = static_cast(Shaders.size()); - FixedLinearAllocator MemPool{GetRawAllocator()}; + for (Uint32 s = 0; s < Shaders.size(); ++s) + { + auto ShaderType = Shaders[s]->GetDesc().ShaderType; + m_ShaderTypes[s] = static_cast(GetShaderTypeIndex(ShaderType)); + VERIFY_EXPR(ShaderType == GetShaderTypeFromIndex(m_ShaderTypes[s])); + } - MemPool.AddSpace(NumShaderStages); - MemPool.AddSpace(NumShaderStages); + FixedLinearAllocator MemPool{GetRawAllocator()}; ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - m_pStaticResourceCaches = MemPool.ConstructArray(NumShaderStages); - - // The memory is now owned by PipelineStateD3D11Impl and will be freed by Destruct(). - auto* Ptr = MemPool.ReleaseOwnership(); - VERIFY_EXPR(Ptr == m_pStaticResourceCaches); - (void)Ptr; - - m_pStaticResourceLayouts = MemPool.Allocate(NumShaderStages); - for (Uint32 i = 0; i < NumShaderStages; ++i) - new (m_pStaticResourceLayouts + i) ShaderResourceLayoutD3D11{*this, m_pStaticResourceCaches[i]}; // noexcept - InitializePipelineDesc(CreateInfo, MemPool); - // It is important to construct all objects before initializing them because if an exception is thrown, - // destructors will be called for all objects + InitResourceLayouts(CreateInfo, Shaders, ByteCodes); - InitResourceLayouts(CreateInfo, Shaders); + auto* pDeviceD3D11 = GetDevice()->GetD3D11Device(); + for (Uint32 s = 0; s < Shaders.size(); ++s) + { + auto ShaderType = Shaders[s]->GetDesc().ShaderType; + const auto& pByteCode = ByteCodes[s]; + switch (ShaderType) + { +#define CREATE_SHADER(SHADER_NAME, ShaderName, pShader) \ + case SHADER_TYPE_##SHADER_NAME: \ + { \ + HRESULT hr = pDeviceD3D11->Create##ShaderName##Shader(pByteCode->GetBufferPointer(), pByteCode->GetBufferSize(), NULL, &pShader); \ + CHECK_D3D_RESULT_THROW(hr, "Failed to create D3D11 shader"); \ + break; \ + } + // clang-format off + CREATE_SHADER(VERTEX, Vertex, m_pVS) + CREATE_SHADER(PIXEL, Pixel, m_pPS) + CREATE_SHADER(GEOMETRY, Geometry, m_pGS) + CREATE_SHADER(DOMAIN, Domain, m_pDS) + CREATE_SHADER(HULL, Hull, m_pHS) + CREATE_SHADER(COMPUTE, Compute, m_pCS) + // clang-format on + default: LOG_ERROR_AND_THROW("Unknown shader type"); + } +#undef CREATE_SHADER + } } PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pRenderDeviceD3D11, const GraphicsPipelineStateCreateInfo& CreateInfo) : - // clang-format off - TPipelineStateBase - { - pRefCounters, - pRenderDeviceD3D11, - CreateInfo - }, - m_SRBMemAllocator{GetRawAllocator()}, - m_ImmutableSamplers (STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) -// clang-format on + TPipelineStateBase{pRefCounters, pRenderDeviceD3D11, CreateInfo} { try { - InitInternalObjects(CreateInfo); - - auto& GraphicsPipeline = GetGraphicsPipelineDesc(); - -#define INIT_SHADER(ShortName, ExpectedType) \ - do \ - { \ - auto* pShader = ValidatedCast(CreateInfo.p##ShortName); \ - m_p##ShortName = pShader; \ - if (m_p##ShortName && m_p##ShortName->GetDesc().ShaderType != ExpectedType) \ - { \ - LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(ExpectedType), " shader is expeceted while ", GetShaderTypeLiteralName(m_p##ShortName->GetDesc().ShaderType), " provided"); \ - } \ - if (pShader != nullptr) \ - HashCombine(m_ShaderResourceLayoutHash, pShader->GetD3D11Resources()->GetHash()); \ - } while (false) - - INIT_SHADER(VS, SHADER_TYPE_VERTEX); - INIT_SHADER(PS, SHADER_TYPE_PIXEL); - INIT_SHADER(GS, SHADER_TYPE_GEOMETRY); - INIT_SHADER(DS, SHADER_TYPE_DOMAIN); - INIT_SHADER(HS, SHADER_TYPE_HULL); -#undef INIT_SHADER + std::vector> ByteCodes; + InitInternalObjects(CreateInfo, ByteCodes); if (m_pVS == nullptr) - { LOG_ERROR_AND_THROW("Vertex shader is null"); - } - auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); + auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); D3D11_BLEND_DESC D3D11BSDesc = {}; BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc); @@ -144,10 +404,7 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* std::vector> d311InputElements(STD_ALLOCATOR_RAW_MEM(D3D11_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); LayoutElements_To_D3D11_INPUT_ELEMENT_DESCs(InputLayout, d311InputElements); - ID3DBlob* pVSByteCode = m_pVS.RawPtr()->GetBytecode(); - if (!pVSByteCode) - LOG_ERROR_AND_THROW("Vertex Shader byte code does not exist"); - + ID3DBlob* pVSByteCode = ByteCodes.front(); CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateInputLayout(d311InputElements.data(), static_cast(d311InputElements.size()), pVSByteCode->GetBufferPointer(), pVSByteCode->GetBufferSize(), &m_pd3d11InputLayout), "Failed to create the Direct3D11 input layout"); } @@ -162,32 +419,12 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D11Impl* pRenderDeviceD3D11, const ComputePipelineStateCreateInfo& CreateInfo) : - // clang-format off - TPipelineStateBase - { - pRefCounters, - pRenderDeviceD3D11, - CreateInfo - }, - m_SRBMemAllocator{GetRawAllocator()}, - m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) -// clang-format on + TPipelineStateBase{pRefCounters, pRenderDeviceD3D11, CreateInfo} { try { - InitInternalObjects(CreateInfo); - - m_pCS = ValidatedCast(CreateInfo.pCS); - if (m_pCS == nullptr) - { - LOG_ERROR_AND_THROW("Compute shader is null"); - } - - if (m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE) - { - LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(SHADER_TYPE_COMPUTE), " shader is expeceted while ", GetShaderTypeLiteralName(m_pCS->GetDesc().ShaderType), " provided"); - } - m_ShaderResourceLayoutHash = m_pCS->GetD3D11Resources()->GetHash(); + std::vector> ByteCodes; + InitInternalObjects(CreateInfo, ByteCodes); } catch (...) { @@ -203,26 +440,19 @@ PipelineStateD3D11Impl::~PipelineStateD3D11Impl() void PipelineStateD3D11Impl::Destruct() { - if (m_pStaticResourceLayouts != nullptr) - { - for (Uint32 l = 0; l < GetNumShaderStages(); ++l) - { - m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); - } - } - - if (m_pStaticResourceCaches != nullptr) - { - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) - { - m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); - m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); - } - } - - // All subobjects are allocated in contiguous chunks of memory. - if (auto* pRawMem = m_pStaticResourceCaches) - GetRawAllocator().Free(pRawMem); + m_ShaderTypes = {}; + m_NumShaders = 0; + + m_pd3d11BlendState = nullptr; + m_pd3d11RasterizerState = nullptr; + m_pd3d11DepthStencilState = nullptr; + m_pd3d11InputLayout = nullptr; + m_pVS = nullptr; + m_pPS = nullptr; + m_pGS = nullptr; + m_pDS = nullptr; + m_pHS = nullptr; + m_pCS = nullptr; TPipelineStateBase::Destruct(); } @@ -230,275 +460,115 @@ void PipelineStateD3D11Impl::Destruct() IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase) -void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, - const std::vector& Shaders) -{ - const auto& ResourceLayout = m_Desc.ResourceLayout; - -#ifdef DILIGENT_DEVELOPMENT - { - const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {}; - for (Uint32 s = 0; s < Shaders.size(); ++s) - { - pResources[s] = Shaders[s]->GetD3D11Resources().get(); - } - ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(), - (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, - (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0); - } -#endif - - decltype(m_ImmutableSamplers) ImmutableSamplers{STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")}; - - std::array ShaderResLayoutDataSizes = {}; - std::array ShaderResCacheDataSizes = {}; - for (Uint32 s = 0; s < Shaders.size(); ++s) - { - const auto* pShader = Shaders[s]; - const auto& ShaderDesc = pShader->GetDesc(); - const auto& Resources = *pShader->GetD3D11Resources(); - VERIFY_EXPR(ShaderDesc.ShaderType == Resources.GetShaderType()); - - // The cache will be initialized by the resource layout - - // Shader resource layout will only contain dynamic and mutable variables - const SHADER_RESOURCE_VARIABLE_TYPE StaticVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; - m_pStaticResourceLayouts[s].Initialize( - pShader->GetD3D11Resources(), - m_Desc.ResourceLayout, - StaticVarTypes, - _countof(StaticVarTypes), - GetRawAllocator(), - GetRawAllocator() // - ); - - // Initialize immutable samplers - for (Uint32 sam = 0; sam < Resources.GetNumSamplers(); ++sam) - { - const auto& SamplerAttribs = Resources.GetSampler(sam); - constexpr bool LogImtblSamplerArrayError = true; - auto SrcImtblSamplerInd = Resources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); - if (SrcImtblSamplerInd >= 0) - { - const auto& SrcImtblSamplerInfo = ResourceLayout.ImmutableSamplers[SrcImtblSamplerInd]; - - RefCntAutoPtr pImbtlSampler; - GetDevice()->CreateSampler(SrcImtblSamplerInfo.Desc, &pImbtlSampler); - ImmutableSamplers.emplace_back(SamplerAttribs, std::move(pImbtlSampler)); - } - } - m_ImmutableSamplerOffsets[s + 1] = static_cast(ImmutableSamplers.size()); - - if (m_Desc.SRBAllocationGranularity > 1) - { - const SHADER_RESOURCE_VARIABLE_TYPE SRBVarTypes[] = // - { - SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, - SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC // - }; - ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(Resources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes)); - ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(Resources); - } - - auto ShaderInd = GetShaderTypePipelineIndex(ShaderDesc.ShaderType, m_Desc.PipelineType); - m_ResourceLayoutIndex[ShaderInd] = static_cast(s); - } - - if (m_Desc.SRBAllocationGranularity > 1) - { - m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderResLayoutDataSizes.data(), GetNumShaderStages(), ShaderResCacheDataSizes.data()); - } - - m_ImmutableSamplers.reserve(ImmutableSamplers.size()); - for (auto& ImtblSam : ImmutableSamplers) - m_ImmutableSamplers.emplace_back(std::move(ImtblSam)); - - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) - { - // Initialize immutable samplers in the static resource cache to avoid warning messages - SetImmutableSamplers(m_pStaticResourceCaches[s], s); - } -} - -ID3D11BlendState* PipelineStateD3D11Impl::GetD3D11BlendState() -{ - return m_pd3d11BlendState; -} - -ID3D11RasterizerState* PipelineStateD3D11Impl::GetD3D11RasterizerState() -{ - return m_pd3d11RasterizerState; -} - -ID3D11DepthStencilState* PipelineStateD3D11Impl::GetD3D11DepthStencilState() -{ - return m_pd3d11DepthStencilState; -} - -ID3D11InputLayout* PipelineStateD3D11Impl::GetD3D11InputLayout() -{ - return m_pd3d11InputLayout; -} - -void PipelineStateD3D11Impl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) -{ - auto& SRBAllocator = GetDevice()->GetSRBAllocator(); - auto pShaderResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingD3D11Impl instance", ShaderResourceBindingD3D11Impl)(this, false); - if (InitStaticResources) - pShaderResBinding->InitializeStaticResources(nullptr); - pShaderResBinding->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast(static_cast(ppShaderResourceBinding))); -} - bool PipelineStateD3D11Impl::IsCompatibleWith(const IPipelineState* pPSO) const { - VERIFY_EXPR(pPSO != nullptr); - - if (pPSO == this) - return true; - - const PipelineStateD3D11Impl* pPSOD3D11 = ValidatedCast(pPSO); - if (m_ShaderResourceLayoutHash != pPSOD3D11->m_ShaderResourceLayoutHash) + if (!TPipelineStateBase::IsCompatibleWith(pPSO)) return false; - if (GetNumShaderStages() != pPSOD3D11->GetNumShaderStages()) + const auto& rhs = *ValidatedCast(pPSO); + if (m_NumShaders != rhs.m_NumShaders || m_ShaderTypes != rhs.m_ShaderTypes) return false; - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) - { - auto* pShader0 = GetShader(s); - auto* pShader1 = pPSOD3D11->GetShader(s); - if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType) - return false; - const auto& Res0 = *pShader0->GetD3D11Resources(); - const auto& Res1 = *pShader1->GetD3D11Resources(); - if (!Res0.IsCompatibleWith(Res1)) - return false; - } - return true; } -ID3D11VertexShader* PipelineStateD3D11Impl::GetD3D11VertexShader() -{ - if (!m_pVS) return nullptr; - auto* pVSD3D11 = m_pVS.RawPtr(); - return static_cast(pVSD3D11->GetD3D11Shader()); -} - -ID3D11PixelShader* PipelineStateD3D11Impl::GetD3D11PixelShader() +SHADER_TYPE PipelineStateD3D11Impl::GetShaderStageType(Uint32 Index) const { - if (!m_pPS) return nullptr; - auto* pPSD3D11 = m_pPS.RawPtr(); - return static_cast(pPSD3D11->GetD3D11Shader()); + return GetShaderTypeFromIndex(m_ShaderTypes[Index]); } -ID3D11GeometryShader* PipelineStateD3D11Impl::GetD3D11GeometryShader() +void PipelineStateD3D11Impl::ValidateShaderResources(const ShaderD3D11Impl* pShader) { - if (!m_pGS) return nullptr; - auto* pGSD3D11 = m_pGS.RawPtr(); - return static_cast(pGSD3D11->GetD3D11Shader()); -} + const auto& pShaderResources = pShader->GetShaderResources(); + const auto ShaderType = pShader->GetDesc().ShaderType; -ID3D11DomainShader* PipelineStateD3D11Impl::GetD3D11DomainShader() -{ - if (!m_pDS) return nullptr; - auto* pDSD3D11 = m_pDS.RawPtr(); - return static_cast(pDSD3D11->GetD3D11Shader()); -} - -ID3D11HullShader* PipelineStateD3D11Impl::GetD3D11HullShader() -{ - if (!m_pHS) return nullptr; - auto* pHSD3D11 = m_pHS.RawPtr(); - return static_cast(pHSD3D11->GetD3D11Shader()); -} - -ID3D11ComputeShader* PipelineStateD3D11Impl::GetD3D11ComputeShader() -{ - if (!m_pCS) return nullptr; - auto* pCSD3D11 = m_pCS.RawPtr(); - return static_cast(pCSD3D11->GetD3D11Shader()); -} - - -void PipelineStateD3D11Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) -{ - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) - { - auto& StaticResLayout = m_pStaticResourceLayouts[s]; - if ((ShaderFlags & StaticResLayout.GetShaderType()) != 0) - StaticResLayout.BindResources(pResourceMapping, Flags, m_pStaticResourceCaches[s]); - } -} - -Uint32 PipelineStateD3D11Impl::GetStaticVariableCount(SHADER_TYPE ShaderType) const -{ - const auto LayoutInd = GetStaticVariableCountHelper(ShaderType, m_ResourceLayoutIndex); - if (LayoutInd < 0) - return 0; - - VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderStages()); - return m_pStaticResourceLayouts[LayoutInd].GetTotalResourceCount(); -} +#ifdef DILIGENT_DEVELOPMENT + m_ShaderResources.emplace_back(pShaderResources); +#endif -IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByName(SHADER_TYPE ShaderType, const Char* Name) -{ - const auto LayoutInd = GetStaticVariableByNameHelper(ShaderType, Name, m_ResourceLayoutIndex); - if (LayoutInd < 0) - return nullptr; + // Check compatibility between shader resources and resource signature. + pShaderResources->ProcessResources( + [&](const D3DShaderResourceAttribs& Attribs, Uint32) // + { +#ifdef DILIGENT_DEVELOPMENT + m_ResourceAttibutions.emplace_back(); +#endif - VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderStages()); - return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Name); -} + const auto IsSampler = Attribs.GetInputType() == D3D_SIT_SAMPLER; + if (IsSampler && pShaderResources->IsUsingCombinedTextureSamplers()) + return; -IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) -{ - const auto LayoutInd = GetStaticVariableByIndexHelper(ShaderType, Index, m_ResourceLayoutIndex); - if (LayoutInd < 0) - return nullptr; +#ifdef DILIGENT_DEVELOPMENT + auto& ResAttribution = m_ResourceAttibutions.back(); +#else + ResourceAttribution ResAttribution; +#endif + ResAttribution = GetResourceAttribution(Attribs.Name, ShaderType); + if (!ResAttribution) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name, + "' that is not present in any pipeline resource signature used to create pipeline state '", + m_Desc.Name, "'."); + } - VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderStages()); - return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Index); -} + SHADER_RESOURCE_TYPE Type = SHADER_RESOURCE_TYPE_UNKNOWN; + PIPELINE_RESOURCE_FLAGS Flags = PIPELINE_RESOURCE_FLAG_UNKNOWN; + GetShaderResourceTypeAndFlags(Attribs, Type, Flags); -void PipelineStateD3D11Impl::SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const -{ - auto NumCachedSamplers = ResourceCache.GetSamplerCount(); - for (Uint32 s = m_ImmutableSamplerOffsets[ShaderInd]; s < m_ImmutableSamplerOffsets[ShaderInd + 1]; ++s) - { - auto& SamplerInfo = m_ImmutableSamplers[s]; - const auto& SamAttribs = SamplerInfo.Attribs; - auto* pSamplerD3D11Impl = SamplerInfo.pSampler.RawPtr(); - // Limiting EndBindPoint is required when initializing immutable samplers in a Shader's static cache - auto EndBindPoint = std::min(static_cast(SamAttribs.BindPoint) + SamAttribs.BindCount, NumCachedSamplers); - for (Uint32 BindPoint = SamAttribs.BindPoint; BindPoint < EndBindPoint; ++BindPoint) - ResourceCache.SetSampler(BindPoint, pSamplerD3D11Impl); - } -} + const auto* const pSignature = ResAttribution.pSignature; + VERIFY_EXPR(pSignature != nullptr); -const ShaderD3D11Impl* PipelineStateD3D11Impl::GetShaderByType(SHADER_TYPE ShaderType) const -{ - switch (ShaderType) - { - // clang-format off - case SHADER_TYPE_VERTEX: return m_pVS; - case SHADER_TYPE_PIXEL: return m_pPS; - case SHADER_TYPE_GEOMETRY: return m_pGS; - case SHADER_TYPE_HULL: return m_pHS; - case SHADER_TYPE_DOMAIN: return m_pDS; - case SHADER_TYPE_COMPUTE: return m_pCS; - default: UNEXPECTED("unsupported shader type"); return nullptr; - // clang-format on - } -} + if (ResAttribution.ResourceIndex != ResourceAttribution::InvalidResourceIndex) + { + const auto& ResDesc = pSignature->GetResourceDesc(ResAttribution.ResourceIndex); -const ShaderD3D11Impl* PipelineStateD3D11Impl::GetShader(Uint32 Index) const -{ - if (Index < GetNumShaderStages()) - return GetShaderByType(GetShaderStageType(Index)); + auto ResourceType = ResDesc.ResourceType; + if (ResourceType == SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT) + ResourceType = SHADER_RESOURCE_TYPE_TEXTURE_SRV; + if (Type != ResourceType) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, + "' and type '", GetShaderResourceTypeLiteralName(Type), "' that is not compatible with type '", + GetShaderResourceTypeLiteralName(ResDesc.ResourceType), "' in pipeline resource signature '", pSignature->GetDesc().Name, "'."); + } - UNEXPECTED("Shader index is out of range"); - return nullptr; + if ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) != (ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER)) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name, + "' that is", ((Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), + " labeled as formatted buffer, while the same resource specified by the pipeline resource signature '", + pSignature->GetDesc().Name, "' is", ((ResDesc.Flags & PIPELINE_RESOURCE_FLAG_FORMATTED_BUFFER) ? "" : " not"), + " labeled as such."); + } + + VERIFY(Attribs.BindCount != 0, + "Runtime-sized array is not supported in Direct3D11, shader must not be compiled."); + VERIFY((ResDesc.Flags & PIPELINE_RESOURCE_FLAG_RUNTIME_ARRAY) == 0, + "Runtime-sized array flag is not supported in Direct3D11, this error must be handled by ValidatePipelineResourceSignatureDesc()"); + + if (ResDesc.ArraySize < Attribs.BindCount) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource '", Attribs.Name, + "' whose array size (", Attribs.BindCount, ") is greater than the array size (", + ResDesc.ArraySize, ") specified by the pipeline resource signature '", pSignature->GetDesc().Name, "'."); + } + } + else if (ResAttribution.ImmutableSamplerIndex != ResourceAttribution::InvalidResourceIndex) + { + if (Type != SHADER_RESOURCE_TYPE_SAMPLER) + { + LOG_ERROR_AND_THROW("Shader '", pShader->GetDesc().Name, "' contains resource with name '", Attribs.Name, + "' and type '", GetShaderResourceTypeLiteralName(Type), + "' that is not compatible with immutable sampler defined in pipeline resource signature '", + pSignature->GetDesc().Name, "'."); + } + } + else + { + UNEXPECTED("Either immutable sampler or resource index should be valid"); + } + } // + ); } } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index e8bf17ef..3523e5b4 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -38,6 +38,7 @@ #include "TextureViewD3D11Impl.hpp" #include "PipelineStateD3D11Impl.hpp" #include "ShaderResourceBindingD3D11Impl.hpp" +#include "PipelineResourceSignatureD3D11Impl.hpp" #include "FenceD3D11Impl.hpp" #include "QueryD3D11Impl.hpp" #include "RenderPassD3D11Impl.hpp" @@ -47,6 +48,13 @@ namespace Diligent { +class BottomLevelASD3D11Impl +{}; +class TopLevelASD3D11Impl +{}; +class ShaderBindingTableD3D11Impl +{}; + static CComPtr DXGIAdapterFromD3D11Device(ID3D11Device* pd3d11Device) { CComPtr pDXGIDevice; @@ -87,32 +95,12 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo pRefCounters, RawMemAllocator, pEngineFactory, - NumDeferredContexts, - DeviceObjectSizes - { - sizeof(TextureBaseD3D11), - sizeof(TextureViewD3D11Impl), - sizeof(BufferD3D11Impl), - sizeof(BufferViewD3D11Impl), - sizeof(ShaderD3D11Impl), - sizeof(SamplerD3D11Impl), - sizeof(PipelineStateD3D11Impl), - sizeof(ShaderResourceBindingD3D11Impl), - sizeof(FenceD3D11Impl), - sizeof(QueryD3D11Impl), - sizeof(RenderPassD3D11Impl), - sizeof(FramebufferD3D11Impl), - 0, - 0, - 0 - } + NumDeferredContexts }, m_EngineAttribs{EngineAttribs}, m_pd3d11Device {pd3d11Device } // clang-format on { - static_assert(sizeof(DeviceObjectSizes) == sizeof(size_t) * 15, "Please add new objects to DeviceObjectSizes constructor"); - m_DeviceCaps.DevType = RENDER_DEVICE_TYPE_D3D11; auto FeatureLevel = m_pd3d11Device->GetFeatureLevel(); switch (FeatureLevel) @@ -149,10 +137,13 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo // Direct3D11 only supports shader model 5.0 even if the device feature level is // above 11.0 (for example, 11.1 or 12.0), so bindless resources are never available. // https://docs.microsoft.com/en-us/windows/win32/direct3d11/overviews-direct3d-11-devices-downlevel-intro#overview-for-each-feature-level - UNSUPPORTED_FEATURE(BindlessResources, "Bindless resources are"); + // clang-format off + UNSUPPORTED_FEATURE(BindlessResources, "Bindless resources are"); UNSUPPORTED_FEATURE(VertexPipelineUAVWritesAndAtomics, "Vertex pipeline UAV writes and atomics are"); - UNSUPPORTED_FEATURE(MeshShaders, "Mesh shaders are"); - UNSUPPORTED_FEATURE(RayTracing, "Ray tracing is"); + UNSUPPORTED_FEATURE(MeshShaders, "Mesh shaders are"); + UNSUPPORTED_FEATURE(RayTracing, "Ray tracing is"); + UNSUPPORTED_FEATURE(ShaderResourceRuntimeArray, "Runtime-sized array is"); + // clang-format on { bool ShaderFloat16Supported = false; @@ -182,7 +173,7 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo #undef UNSUPPORTED_FEATURE #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 33, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif auto& TexCaps = m_DeviceCaps.TexCaps; @@ -257,38 +248,17 @@ IMPLEMENT_QUERY_INTERFACE(RenderDeviceD3D11Impl, IID_RenderDeviceD3D11, TRenderD void RenderDeviceD3D11Impl::CreateBufferFromD3DResource(ID3D11Buffer* pd3d11Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) { - CreateDeviceObject("buffer", BuffDesc, ppBuffer, - [&]() // - { - BufferD3D11Impl* pBufferD3D11{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d11Buffer)}; - pBufferD3D11->QueryInterface(IID_Buffer, reinterpret_cast(ppBuffer)); - pBufferD3D11->CreateDefaultViews(); - OnCreateDeviceObject(pBufferD3D11); - }); + CreateBufferImpl(ppBuffer, BuffDesc, InitialState, pd3d11Buffer); } void RenderDeviceD3D11Impl::CreateBuffer(const BufferDesc& BuffDesc, const BufferData* pBuffData, IBuffer** ppBuffer) { - CreateDeviceObject("buffer", BuffDesc, ppBuffer, - [&]() // - { - BufferD3D11Impl* pBufferD3D11{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData)}; - pBufferD3D11->QueryInterface(IID_Buffer, reinterpret_cast(ppBuffer)); - pBufferD3D11->CreateDefaultViews(); - OnCreateDeviceObject(pBufferD3D11); - }); + CreateBufferImpl(ppBuffer, BuffDesc, pBuffData); } void RenderDeviceD3D11Impl::CreateShader(const ShaderCreateInfo& ShaderCI, IShader** ppShader) { - CreateDeviceObject("shader", ShaderCI.Desc, ppShader, - [&]() // - { - ShaderD3D11Impl* pShaderD3D11{NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D11Impl instance", ShaderD3D11Impl)(this, ShaderCI)}; - pShaderD3D11->QueryInterface(IID_Shader, reinterpret_cast(ppShader)); - - OnCreateDeviceObject(pShaderD3D11); - }); + CreateShaderImpl(ppShader, ShaderCI); } void RenderDeviceD3D11Impl::CreateTexture1DFromD3DResource(ID3D11Texture1D* pd3d11Texture, RESOURCE_STATE InitialState, ITexture** ppTexture) @@ -304,7 +274,6 @@ void RenderDeviceD3D11Impl::CreateTexture1DFromD3DResource(ID3D11Texture1D* pd3d TextureBaseD3D11* pTextureD3D11{NEW_RC_OBJ(m_TexObjAllocator, "Texture1D_D3D11 instance", Texture1D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture)}; pTextureD3D11->QueryInterface(IID_Texture, reinterpret_cast(ppTexture)); pTextureD3D11->CreateDefaultViews(); - OnCreateDeviceObject(pTextureD3D11); }); } @@ -321,7 +290,6 @@ void RenderDeviceD3D11Impl::CreateTexture2DFromD3DResource(ID3D11Texture2D* pd3d TextureBaseD3D11* pTextureD3D11{NEW_RC_OBJ(m_TexObjAllocator, "Texture2D_D3D11 instance", Texture2D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture)}; pTextureD3D11->QueryInterface(IID_Texture, reinterpret_cast(ppTexture)); pTextureD3D11->CreateDefaultViews(); - OnCreateDeviceObject(pTextureD3D11); }); } @@ -338,7 +306,6 @@ void RenderDeviceD3D11Impl::CreateTexture3DFromD3DResource(ID3D11Texture3D* pd3d TextureBaseD3D11* pTextureD3D11{NEW_RC_OBJ(m_TexObjAllocator, "Texture3D_D3D11 instance", Texture3D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture)}; pTextureD3D11->QueryInterface(IID_Texture, reinterpret_cast(ppTexture)); pTextureD3D11->CreateDefaultViews(); - OnCreateDeviceObject(pTextureD3D11); }); } @@ -371,47 +338,22 @@ void RenderDeviceD3D11Impl::CreateTexture(const TextureDesc& TexDesc, const Text } pTextureD3D11->QueryInterface(IID_Texture, reinterpret_cast(ppTexture)); pTextureD3D11->CreateDefaultViews(); - OnCreateDeviceObject(pTextureD3D11); }); } void RenderDeviceD3D11Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler) { - CreateDeviceObject("sampler", SamplerDesc, ppSampler, - [&]() // - { - m_SamplersRegistry.Find(SamplerDesc, reinterpret_cast(ppSampler)); - if (*ppSampler == nullptr) - { - SamplerD3D11Impl* pSamplerD3D11{NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D11Impl instance", SamplerD3D11Impl)(this, SamplerDesc)}; - pSamplerD3D11->QueryInterface(IID_Sampler, reinterpret_cast(ppSampler)); - OnCreateDeviceObject(pSamplerD3D11); - m_SamplersRegistry.Add(SamplerDesc, *ppSampler); - } - }); -} - -template -void RenderDeviceD3D11Impl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState) -{ - CreateDeviceObject("Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState, - [&]() // - { - PipelineStateD3D11Impl* pPipelineStateD3D11{NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D11Impl instance", PipelineStateD3D11Impl)(this, PSOCreateInfo)}; - pPipelineStateD3D11->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); - OnCreateDeviceObject(pPipelineStateD3D11); - }); + CreateSamplerImpl(ppSampler, SamplerDesc); } - void RenderDeviceD3D11Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) { - CreatePipelineState(PSOCreateInfo, ppPipelineState); + CreatePipelineStateImpl(ppPipelineState, PSOCreateInfo); } void RenderDeviceD3D11Impl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) { - CreatePipelineState(PSOCreateInfo, ppPipelineState); + CreatePipelineStateImpl(ppPipelineState, PSOCreateInfo); } void RenderDeviceD3D11Impl::CreateRayTracingPipelineState(const RayTracingPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) @@ -422,46 +364,22 @@ void RenderDeviceD3D11Impl::CreateRayTracingPipelineState(const RayTracingPipeli void RenderDeviceD3D11Impl::CreateFence(const FenceDesc& Desc, IFence** ppFence) { - CreateDeviceObject("Fence", Desc, ppFence, - [&]() // - { - FenceD3D11Impl* pFenceD3D11{NEW_RC_OBJ(m_FenceAllocator, "FenceD3D11Impl instance", FenceD3D11Impl)(this, Desc)}; - pFenceD3D11->QueryInterface(IID_Fence, reinterpret_cast(ppFence)); - OnCreateDeviceObject(pFenceD3D11); - }); + CreateFenceImpl(ppFence, Desc); } void RenderDeviceD3D11Impl::CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) { - CreateDeviceObject("Query", Desc, ppQuery, - [&]() // - { - QueryD3D11Impl* pQueryD3D11{NEW_RC_OBJ(m_QueryAllocator, "QueryD3D11Impl instance", QueryD3D11Impl)(this, Desc)}; - pQueryD3D11->QueryInterface(IID_Query, reinterpret_cast(ppQuery)); - OnCreateDeviceObject(pQueryD3D11); - }); + CreateQueryImpl(ppQuery, Desc); } void RenderDeviceD3D11Impl::CreateRenderPass(const RenderPassDesc& Desc, IRenderPass** ppRenderPass) { - CreateDeviceObject("RenderPass", Desc, ppRenderPass, - [&]() // - { - RenderPassD3D11Impl* pRenderPassD3D11{NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D11Impl instance", RenderPassD3D11Impl)(this, Desc)}; - pRenderPassD3D11->QueryInterface(IID_RenderPass, reinterpret_cast(ppRenderPass)); - OnCreateDeviceObject(pRenderPassD3D11); - }); + CreateRenderPassImpl(ppRenderPass, Desc); } void RenderDeviceD3D11Impl::CreateFramebuffer(const FramebufferDesc& Desc, IFramebuffer** ppFramebuffer) { - CreateDeviceObject("Framebuffer", Desc, ppFramebuffer, - [&]() // - { - FramebufferD3D11Impl* pFramebufferD3D11{NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D11Impl instance", FramebufferD3D11Impl)(this, Desc)}; - pFramebufferD3D11->QueryInterface(IID_Framebuffer, reinterpret_cast(ppFramebuffer)); - OnCreateDeviceObject(pFramebufferD3D11); - }); + CreateFramebufferImpl(ppFramebuffer, Desc); } void RenderDeviceD3D11Impl::CreateBLAS(const BottomLevelASDesc& Desc, @@ -485,6 +403,19 @@ void RenderDeviceD3D11Impl::CreateSBT(const ShaderBindingTableDesc& Desc, *ppSBT = nullptr; } +void RenderDeviceD3D11Impl::CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc, + IPipelineResourceSignature** ppSignature) +{ + CreatePipelineResourceSignature(Desc, ppSignature, false); +} + +void RenderDeviceD3D11Impl::CreatePipelineResourceSignature(const PipelineResourceSignatureDesc& Desc, + IPipelineResourceSignature** ppSignature, + bool IsDeviceInternal) +{ + CreatePipelineResourceSignatureImpl(ppSignature, Desc, IsDeviceInternal); +} + void RenderDeviceD3D11Impl::IdleGPU() { if (auto pImmediateCtx = m_wpImmediateContext.Lock()) diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp index 05ece281..9191c9ce 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderD3D11Impl.cpp @@ -140,10 +140,6 @@ ShaderD3D11Impl::ShaderD3D11Impl(IReferenceCounters* pRefCounters, auto* pRawMem = ALLOCATE(Allocator, "Allocator for ShaderResources", ShaderResourcesD3D11, 1); auto* pResources = new (pRawMem) ShaderResourcesD3D11(pRenderDeviceD3D11, m_pShaderByteCode, m_Desc, ShaderCI.UseCombinedTextureSamplers ? ShaderCI.CombinedSamplerSuffix : nullptr); m_pShaderResources.reset(pResources, STDDeleterRawMem(Allocator)); - - // Byte code is only required for the vertex shader to create input layout - if (ShaderCI.Desc.ShaderType != SHADER_TYPE_VERTEX) - m_pShaderByteCode.Release(); } ShaderD3D11Impl::~ShaderD3D11Impl() diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 59c9072b..8bf8f59a 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -26,222 +26,25 @@ */ #include "pch.h" + #include "ShaderResourceBindingD3D11Impl.hpp" -#include "PipelineStateD3D11Impl.hpp" -#include "DeviceContextD3D11Impl.hpp" + #include "RenderDeviceD3D11Impl.hpp" -#include "ShaderD3D11Impl.hpp" -#include "FixedLinearAllocator.hpp" +#include "PipelineResourceSignatureD3D11Impl.hpp" namespace Diligent { - -ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounters* pRefCounters, - PipelineStateD3D11Impl* pPSO, - bool IsInternal) : - // clang-format off - TBase - { - pRefCounters, - pPSO, - IsInternal - }, - m_bIsStaticResourcesBound{false} -// clang-format on +ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounters* pRefCounters, + PipelineResourceSignatureD3D11Impl* pPRS) : + TBase{pRefCounters, pPRS} { - try - { - m_ResourceLayoutIndex.fill(-1); - m_NumActiveShaders = static_cast(pPSO->GetNumShaderStages()); - - FixedLinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddSpace(m_NumActiveShaders); - MemPool.AddSpace(m_NumActiveShaders); - - MemPool.Reserve(); - - m_pBoundResourceCaches = MemPool.ConstructArray(m_NumActiveShaders); - - // The memory is now owned by ShaderResourceBindingD3D11Impl and will be freed by Destruct(). - auto* Ptr = MemPool.ReleaseOwnership(); - VERIFY_EXPR(Ptr == m_pBoundResourceCaches); - (void)Ptr; - - m_pResourceLayouts = MemPool.Allocate(m_NumActiveShaders); - for (Uint8 s = 0; s < m_NumActiveShaders; ++s) - new (m_pResourceLayouts + s) ShaderResourceLayoutD3D11{*this, m_pBoundResourceCaches[s]}; // noexcept - - // It is important to construct all objects before initializing them because if an exception is thrown, - // destructors will be called for all objects - - const auto& PSODesc = pPSO->GetDesc(); - - // Reserve memory for resource layouts - for (Uint8 s = 0; s < m_NumActiveShaders; ++s) - { - auto* pShaderD3D11 = pPSO->GetShader(s); - - auto& SRBMemAllocator = pPSO->GetSRBMemoryAllocator(); - auto& ResCacheDataAllocator = SRBMemAllocator.GetResourceCacheDataAllocator(s); - auto& ResLayoutDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s); - - // Initialize resource cache to have enough space to contain all shader resources, including static ones - // Static resources are copied before resources are committed - const auto& Resources = *pShaderD3D11->GetD3D11Resources(); - m_pBoundResourceCaches[s].Initialize(Resources, ResCacheDataAllocator); - - // Shader resource layout will only contain dynamic and mutable variables - // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache#Shader-Resource-Cache-Initialization - SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; - m_pResourceLayouts[s].Initialize( - pShaderD3D11->GetD3D11Resources(), - PSODesc.ResourceLayout, - VarTypes, - _countof(VarTypes), - ResCacheDataAllocator, - ResLayoutDataAllocator // - ); - - const auto ShaderType = pShaderD3D11->GetDesc().ShaderType; - const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PSODesc.PipelineType); - VERIFY_EXPR(ShaderType == m_pResourceLayouts[s].GetShaderType()); - m_ShaderTypes[s] = ShaderType; - - m_ResourceLayoutIndex[ShaderInd] = s; - } - } - catch (...) - { - Destruct(); - throw; - } } ShaderResourceBindingD3D11Impl::~ShaderResourceBindingD3D11Impl() { - Destruct(); -} - -void ShaderResourceBindingD3D11Impl::Destruct() -{ - if (m_pResourceLayouts != nullptr) - { - for (Int32 l = 0; l < m_NumActiveShaders; ++l) - { - m_pResourceLayouts[l].~ShaderResourceLayoutD3D11(); - } - } - - if (m_pBoundResourceCaches != nullptr) - { - auto& SRBMemAllocator = m_pPSO->GetSRBMemoryAllocator(); - for (Uint32 s = 0; s < m_NumActiveShaders; ++s) - { - auto& Allocator = SRBMemAllocator.GetResourceCacheDataAllocator(s); - m_pBoundResourceCaches[s].Destroy(Allocator); - m_pBoundResourceCaches[s].~ShaderResourceCacheD3D11(); - } - } - - if (void* pRawMem = m_pBoundResourceCaches) - { - GetRawAllocator().Free(pRawMem); - } } IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingD3D11Impl, IID_ShaderResourceBindingD3D11, TBase) -void ShaderResourceBindingD3D11Impl::BindResources(Uint32 ShaderFlags, IResourceMapping* pResMapping, Uint32 Flags) -{ - for (Uint32 ResLayoutInd = 0; ResLayoutInd < m_NumActiveShaders; ++ResLayoutInd) - { - auto& ResLayout = m_pResourceLayouts[ResLayoutInd]; - if (ShaderFlags & ResLayout.GetShaderType()) - { - ResLayout.BindResources(pResMapping, Flags, m_pBoundResourceCaches[ResLayoutInd]); - } - } -} - -void ShaderResourceBindingD3D11Impl::InitializeStaticResources(const IPipelineState* pPipelineState) -{ - if (m_bIsStaticResourcesBound) - { - LOG_WARNING_MESSAGE("Static resources have already been initialized in this shader resource binding object. The operation will be ignored."); - return; - } - - if (pPipelineState == nullptr) - { - pPipelineState = GetPipelineState(); - } - else - { - DEV_CHECK_ERR(pPipelineState->IsCompatibleWith(GetPipelineState()), "The pipeline state is not compatible with this SRB"); - } - - const auto* pPSOD3D11 = ValidatedCast(pPipelineState); - auto NumShaders = pPSOD3D11->GetNumShaderStages(); - VERIFY_EXPR(NumShaders == m_NumActiveShaders); - - for (Uint32 shader = 0; shader < NumShaders; ++shader) - { - const auto& StaticResLayout = pPSOD3D11->GetStaticResourceLayout(shader); - auto* pShaderD3D11 = pPSOD3D11->GetShader(shader); -#ifdef DILIGENT_DEVELOPMENT - if (!StaticResLayout.dvpVerifyBindings()) - { - LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", pPSOD3D11->GetDesc().Name, - "' will not be successfully initialized because not all static resource bindings in shader '", - pShaderD3D11->GetDesc().Name, - "' are valid. Please make sure you bind all static resources to PSO before calling InitializeStaticResources() " - "directly or indirectly by passing InitStaticResources=true to CreateShaderResourceBinding() method."); - } -#endif - -#ifdef DILIGENT_DEBUG - { - auto ShaderTypeInd = GetShaderTypePipelineIndex(pShaderD3D11->GetDesc().ShaderType, pPSOD3D11->GetDesc().PipelineType); - auto ResourceLayoutInd = m_ResourceLayoutIndex[ShaderTypeInd]; - VERIFY_EXPR(ResourceLayoutInd == static_cast(shader)); - } -#endif - StaticResLayout.CopyResources(m_pBoundResourceCaches[shader]); - pPSOD3D11->SetImmutableSamplers(m_pBoundResourceCaches[shader], shader); - } - - m_bIsStaticResourcesBound = true; -} - -IShaderResourceVariable* ShaderResourceBindingD3D11Impl::GetVariableByName(SHADER_TYPE ShaderType, const char* Name) -{ - auto ResLayoutInd = GetVariableByNameHelper(ShaderType, Name, m_ResourceLayoutIndex); - if (ResLayoutInd < 0) - return nullptr; - - VERIFY_EXPR(static_cast(ResLayoutInd) < Uint32{m_NumActiveShaders}); - return m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Name); -} - -Uint32 ShaderResourceBindingD3D11Impl::GetVariableCount(SHADER_TYPE ShaderType) const -{ - auto ResLayoutInd = GetVariableCountHelper(ShaderType, m_ResourceLayoutIndex); - if (ResLayoutInd < 0) - return 0; - - VERIFY_EXPR(static_cast(ResLayoutInd) < Uint32{m_NumActiveShaders}); - return m_pResourceLayouts[ResLayoutInd].GetTotalResourceCount(); -} - -IShaderResourceVariable* ShaderResourceBindingD3D11Impl::GetVariableByIndex(SHADER_TYPE ShaderType, Uint32 Index) -{ - auto ResLayoutInd = GetVariableByIndexHelper(ShaderType, Index, m_ResourceLayoutIndex); - if (ResLayoutInd < 0) - return nullptr; - - VERIFY_EXPR(static_cast(ResLayoutInd) < Uint32{m_NumActiveShaders}); - return m_pResourceLayouts[ResLayoutInd].GetShaderVariable(Index); -} - } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp index 9a7a21ba..9985c56d 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp @@ -28,42 +28,33 @@ #include "pch.h" #include "ShaderResourceCacheD3D11.hpp" -#include "ShaderResourceLayoutD3D11.hpp" #include "TextureBaseD3D11.hpp" #include "BufferD3D11Impl.hpp" #include "SamplerD3D11Impl.hpp" +#include "DeviceContextD3D11Impl.hpp" #include "MemoryAllocator.h" +#include "Align.hpp" namespace Diligent { -size_t ShaderResourceCacheD3D11::GetRequriedMemorySize(const ShaderResourcesD3D11& Resources) +size_t ShaderResourceCacheD3D11::GetRequriedMemorySize(const TResourceCount& ResCount) { // clang-format off - auto CBCount = Resources.GetMaxCBBindPoint() + 1; - auto SRVCount = Resources.GetMaxSRVBindPoint() + 1; - auto SamplerCount = Resources.GetMaxSamplerBindPoint()+ 1; - auto UAVCount = Resources.GetMaxUAVBindPoint() + 1; - auto MemSize = - (sizeof(CachedCB) + sizeof(ID3D11Buffer*)) * CBCount + - (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*)) * SRVCount + - (sizeof(CachedSampler) + sizeof(ID3D11SamplerState*)) * SamplerCount + - (sizeof(CachedResource) + sizeof(ID3D11UnorderedAccessView*)) * UAVCount; + auto CBCount = ResCount[DESCRIPTOR_RANGE_CBV]; + auto SRVCount = ResCount[DESCRIPTOR_RANGE_SRV]; + auto SamplerCount = ResCount[DESCRIPTOR_RANGE_SAMPLER]; + auto UAVCount = ResCount[DESCRIPTOR_RANGE_UAV]; + size_t MemSize = 0; + MemSize = Align(MemSize + (sizeof(CachedCB) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11Buffer*)) * CBCount, MaxAlignment); + MemSize = Align(MemSize + (sizeof(CachedResource) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11ShaderResourceView*)) * SRVCount, MaxAlignment); + MemSize = Align(MemSize + (sizeof(CachedSampler) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11SamplerState*)) * SamplerCount, MaxAlignment); + MemSize = Align(MemSize + (sizeof(CachedResource) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11UnorderedAccessView*)) * UAVCount, MaxAlignment); // clang-format on + VERIFY(MemSize < InvalidResourceOffset, "Memory size exeed the maximum allowed size."); return MemSize; } -void ShaderResourceCacheD3D11::Initialize(const ShaderResourcesD3D11& Resources, IMemoryAllocator& MemAllocator) -{ - // clang-format off - auto CBCount = Resources.GetMaxCBBindPoint() + 1; - auto SRVCount = Resources.GetMaxSRVBindPoint() + 1; - auto SamplerCount = Resources.GetMaxSamplerBindPoint()+ 1; - auto UAVCount = Resources.GetMaxUAVBindPoint() + 1; - // clang-format on - Initialize(CBCount, SRVCount, SamplerCount, UAVCount, MemAllocator); -} - -void ShaderResourceCacheD3D11::Initialize(Uint32 CBCount, Uint32 SRVCount, Uint32 SamplerCount, Uint32 UAVCount, IMemoryAllocator& MemAllocator) +void ShaderResourceCacheD3D11::Initialize(const TResourceCount& ResCount, IMemoryAllocator& MemAllocator) { // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache/ if (IsInitialized()) @@ -72,144 +63,164 @@ void ShaderResourceCacheD3D11::Initialize(Uint32 CBCount, Uint32 SRVCount, Uint3 return; } + const Uint32 CBCount = ResCount[DESCRIPTOR_RANGE_CBV]; + const Uint32 SRVCount = ResCount[DESCRIPTOR_RANGE_SRV]; + const Uint32 SamplerCount = ResCount[DESCRIPTOR_RANGE_SAMPLER]; + const Uint32 UAVCount = ResCount[DESCRIPTOR_RANGE_UAV]; + // clang-format off - VERIFY(CBCount <= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT, "Constant buffer count ", CBCount, " exceeds D3D11 limit ", D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT ); - VERIFY(SRVCount <= D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "SRV count ", SRVCount, " exceeds D3D11 limit ", D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT ); - VERIFY(SamplerCount <= D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "Sampler count ", SamplerCount, " exceeds D3D11 limit ", D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT ); - VERIFY(UAVCount <= D3D11_PS_CS_UAV_REGISTER_COUNT, "UAV count ", UAVCount, " exceeds D3D11 limit ", D3D11_PS_CS_UAV_REGISTER_COUNT ); + m_CBCount = static_cast(CBCount); + m_SRVCount = static_cast(SRVCount); + m_SamplerCount = static_cast(SamplerCount); + m_UAVCount = static_cast(UAVCount); - // m_CBOffset = 0 - m_SRVOffset = static_cast(m_CBOffset + CBCount * (sizeof(CachedCB) + sizeof(ID3D11Buffer*))); - m_SamplerOffset = static_cast(m_SRVOffset + SRVCount * (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*))); - m_UAVOffset = static_cast(m_SamplerOffset + SamplerCount * (sizeof(CachedSampler) + sizeof(ID3D11SamplerState*))); - m_MemoryEndOffset = static_cast(m_UAVOffset + UAVCount * (sizeof(CachedResource) + sizeof(ID3D11UnorderedAccessView*))); + VERIFY(CBCount == m_CBCount, "Constant buffer count (", CBCount, ") exceeds maximum representable value"); + VERIFY(SRVCount == m_SRVCount, "Shader resources count (", SRVCount, ") exceeds maximum representable value"); + VERIFY(SamplerCount == m_SamplerCount, "Sampler count (", SamplerCount, ") exceeds maximum representable value"); + VERIFY(UAVCount == m_UAVCount, "UAVs count (", UAVCount, ") exceeds maximum representable value"); - VERIFY_EXPR(GetCBCount() == static_cast(CBCount)); - VERIFY_EXPR(GetSRVCount() == static_cast(SRVCount)); - VERIFY_EXPR(GetSamplerCount() == static_cast(SamplerCount)); - VERIFY_EXPR(GetUAVCount() == static_cast(UAVCount)); + // m_CBOffset = 0 + m_SRVOffset = static_cast(Align(m_CBOffset + (sizeof(CachedCB) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11Buffer*)) * CBCount, MaxAlignment)); + m_SamplerOffset = static_cast(Align(m_SRVOffset + (sizeof(CachedResource) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11ShaderResourceView*)) * SRVCount, MaxAlignment)); + m_UAVOffset = static_cast(Align(m_SamplerOffset + (sizeof(CachedSampler) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11SamplerState*)) * SamplerCount, MaxAlignment)); + size_t BufferSize = static_cast(Align(m_UAVOffset + (sizeof(CachedResource) + sizeof(TBindPointsAndActiveBits) + sizeof(ID3D11UnorderedAccessView*)) * UAVCount, MaxAlignment)); + // clang-format on VERIFY_EXPR(m_pResourceData == nullptr); - size_t BufferSize = m_MemoryEndOffset; - - VERIFY_EXPR( BufferSize == - (sizeof(CachedCB) + sizeof(ID3D11Buffer*)) * CBCount + - (sizeof(CachedResource) + sizeof(ID3D11ShaderResourceView*)) * SRVCount + - (sizeof(CachedSampler) + sizeof(ID3D11SamplerState*)) * SamplerCount + - (sizeof(CachedResource) + sizeof(ID3D11UnorderedAccessView*)) * UAVCount ); - // clang-format on + VERIFY_EXPR(BufferSize == GetRequriedMemorySize(ResCount)); -#ifdef DILIGENT_DEBUG - m_pdbgMemoryAllocator = &MemAllocator; -#endif if (BufferSize > 0) { m_pResourceData = ALLOCATE(MemAllocator, "Shader resource cache data buffer", Uint8, BufferSize); memset(m_pResourceData, 0, BufferSize); + m_pAllocator = &MemAllocator; } + const TBindPointsAndActiveBits InvalidBindPoints = {0, InvalidBindPoint, InvalidBindPoint, InvalidBindPoint, InvalidBindPoint, InvalidBindPoint, InvalidBindPoint}; + // Explicitly construct all objects if (CBCount != 0) { - CachedCB* CBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - GetCBArrays(CBs, d3d11CBs); + CachedCB* CBs = nullptr; + ID3D11Buffer** d3d11CBs = nullptr; + TBindPointsAndActiveBits* bindPoints = nullptr; + GetCBArrays(CBs, d3d11CBs, bindPoints); for (Uint32 cb = 0; cb < CBCount; ++cb) - new (CBs + cb) CachedCB; + { + new (CBs + cb) CachedCB{}; + bindPoints[cb] = InvalidBindPoints; + } } if (SRVCount != 0) { CachedResource* SRVResources = nullptr; ID3D11ShaderResourceView** d3d11SRVs = nullptr; - GetSRVArrays(SRVResources, d3d11SRVs); + TBindPointsAndActiveBits* bindPoints = nullptr; + GetSRVArrays(SRVResources, d3d11SRVs, bindPoints); for (Uint32 srv = 0; srv < SRVCount; ++srv) - new (SRVResources + srv) CachedResource; + { + new (SRVResources + srv) CachedResource{}; + bindPoints[srv] = InvalidBindPoints; + } } if (SamplerCount != 0) { - CachedSampler* Samplers = nullptr; - ID3D11SamplerState** d3d11Samplers = nullptr; - GetSamplerArrays(Samplers, d3d11Samplers); + CachedSampler* Samplers = nullptr; + ID3D11SamplerState** d3d11Samplers = nullptr; + TBindPointsAndActiveBits* bindPoints = nullptr; + GetSamplerArrays(Samplers, d3d11Samplers, bindPoints); for (Uint32 sam = 0; sam < SamplerCount; ++sam) - new (Samplers + sam) CachedSampler; + { + new (Samplers + sam) CachedSampler{}; + bindPoints[sam] = InvalidBindPoints; + } } if (UAVCount != 0) { CachedResource* UAVResources = nullptr; ID3D11UnorderedAccessView** d3d11UAVs = nullptr; - GetUAVArrays(UAVResources, d3d11UAVs); + TBindPointsAndActiveBits* bindPoints = nullptr; + GetUAVArrays(UAVResources, d3d11UAVs, bindPoints); for (Uint32 uav = 0; uav < UAVCount; ++uav) - new (UAVResources + uav) CachedResource; + { + new (UAVResources + uav) CachedResource{}; + bindPoints[uav] = InvalidBindPoints; + } } } -void ShaderResourceCacheD3D11::Destroy(IMemoryAllocator& MemAllocator) +ShaderResourceCacheD3D11::~ShaderResourceCacheD3D11() { - if (!IsInitialized()) - return; - - VERIFY(m_pdbgMemoryAllocator == &MemAllocator, "The allocator does not match the one used to create resources"); - - // Explicitly destory all objects - auto CBCount = GetCBCount(); - if (CBCount != 0) + if (IsInitialized()) { - CachedCB* CBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - GetCBArrays(CBs, d3d11CBs); - for (size_t cb = 0; cb < CBCount; ++cb) - CBs[cb].~CachedCB(); - } + // Explicitly destory all objects + auto CBCount = GetCBCount(); + if (CBCount != 0) + { + CachedCB* CBs = nullptr; + ID3D11Buffer** d3d11CBs = nullptr; + TBindPointsAndActiveBits* bindPoints = nullptr; + GetCBArrays(CBs, d3d11CBs, bindPoints); + for (size_t cb = 0; cb < CBCount; ++cb) + CBs[cb].~CachedCB(); + } - auto SRVCount = GetSRVCount(); - if (SRVCount != 0) - { - CachedResource* SRVResources = nullptr; - ID3D11ShaderResourceView** d3d11SRVs = nullptr; - GetSRVArrays(SRVResources, d3d11SRVs); - for (size_t srv = 0; srv < SRVCount; ++srv) - SRVResources[srv].~CachedResource(); - } + auto SRVCount = GetSRVCount(); + if (SRVCount != 0) + { + CachedResource* SRVResources = nullptr; + ID3D11ShaderResourceView** d3d11SRVs = nullptr; + TBindPointsAndActiveBits* bindPoints = nullptr; + GetSRVArrays(SRVResources, d3d11SRVs, bindPoints); + for (size_t srv = 0; srv < SRVCount; ++srv) + SRVResources[srv].~CachedResource(); + } - auto SamplerCount = GetSamplerCount(); - if (SamplerCount != 0) - { - CachedSampler* Samplers = nullptr; - ID3D11SamplerState** d3d11Samplers = nullptr; - GetSamplerArrays(Samplers, d3d11Samplers); - for (size_t sam = 0; sam < SamplerCount; ++sam) - Samplers[sam].~CachedSampler(); - } + auto SamplerCount = GetSamplerCount(); + if (SamplerCount != 0) + { + CachedSampler* Samplers = nullptr; + ID3D11SamplerState** d3d11Samplers = nullptr; + TBindPointsAndActiveBits* bindPoints = nullptr; + GetSamplerArrays(Samplers, d3d11Samplers, bindPoints); + for (size_t sam = 0; sam < SamplerCount; ++sam) + Samplers[sam].~CachedSampler(); + } - auto UAVCount = GetUAVCount(); - if (UAVCount != 0) - { - CachedResource* UAVResources = nullptr; - ID3D11UnorderedAccessView** d3d11UAVs = nullptr; - GetUAVArrays(UAVResources, d3d11UAVs); - for (size_t uav = 0; uav < UAVCount; ++uav) - UAVResources[uav].~CachedResource(); - } + auto UAVCount = GetUAVCount(); + if (UAVCount != 0) + { + CachedResource* UAVResources = nullptr; + ID3D11UnorderedAccessView** d3d11UAVs = nullptr; + TBindPointsAndActiveBits* bindPoints = nullptr; + GetUAVArrays(UAVResources, d3d11UAVs, bindPoints); + for (size_t uav = 0; uav < UAVCount; ++uav) + UAVResources[uav].~CachedResource(); + } - m_SRVOffset = InvalidResourceOffset; - m_SamplerOffset = InvalidResourceOffset; - m_UAVOffset = InvalidResourceOffset; - m_MemoryEndOffset = InvalidResourceOffset; + m_SRVOffset = InvalidResourceOffset; + m_SamplerOffset = InvalidResourceOffset; + m_UAVOffset = InvalidResourceOffset; + m_CBCount = 0; + m_SRVCount = 0; + m_SamplerCount = 0; + m_UAVCount = 0; - if (m_pResourceData != nullptr) - MemAllocator.Free(m_pResourceData); - m_pResourceData = nullptr; -} + if (m_pResourceData != nullptr) + m_pAllocator->Free(m_pResourceData); -ShaderResourceCacheD3D11::~ShaderResourceCacheD3D11() -{ - VERIFY(!IsInitialized(), "Shader resource cache memory must be released with ShaderResourceCacheD3D11::Destroy()"); + m_pResourceData = nullptr; + m_pAllocator = nullptr; + } } -void dbgVerifyResource(ShaderResourceCacheD3D11::CachedResource& Res, ID3D11View* pd3d11View, const char* ViewType) +#ifdef DILIGENT_DEVELOPMENT +namespace +{ +void DvpVerifyResource(ShaderResourceCacheD3D11::CachedResource& Res, ID3D11View* pd3d11View, const char* ViewType) { if (pd3d11View != nullptr) { @@ -251,8 +262,9 @@ void dbgVerifyResource(ShaderResourceCacheD3D11::CachedResource& Res, ID3D11View VERIFY(Res.pd3d11Resource == nullptr, "Unexepected D3D11 resource"); } } +} // namespace -void ShaderResourceCacheD3D11::dbgVerifyCacheConsistency() +void ShaderResourceCacheD3D11::DvpVerifyCacheConsistency() { VERIFY(IsInitialized(), "Cache is not initialized"); @@ -264,11 +276,12 @@ void ShaderResourceCacheD3D11::dbgVerifyCacheConsistency() ID3D11SamplerState** d3d11Samplers = nullptr; CachedResource* UAVResources = nullptr; ID3D11UnorderedAccessView** d3d11UAVs = nullptr; + TBindPointsAndActiveBits* bindPoints = nullptr; - GetCBArrays(CBs, d3d11CBs); - GetSRVArrays(SRVResources, d3d11SRVs); - GetSamplerArrays(Samplers, d3d11Samplers); - GetUAVArrays(UAVResources, d3d11UAVs); + GetCBArrays(CBs, d3d11CBs, bindPoints); + GetSRVArrays(SRVResources, d3d11SRVs, bindPoints); + GetSamplerArrays(Samplers, d3d11Samplers, bindPoints); + GetUAVArrays(UAVResources, d3d11UAVs, bindPoints); auto CBCount = GetCBCount(); for (size_t cb = 0; cb < CBCount; ++cb) @@ -287,7 +300,7 @@ void ShaderResourceCacheD3D11::dbgVerifyCacheConsistency() { auto& Res = SRVResources[srv]; auto* pd3d11SRV = d3d11SRVs[srv]; - dbgVerifyResource(Res, pd3d11SRV, "SRV"); + DvpVerifyResource(Res, pd3d11SRV, "SRV"); } auto UAVCount = GetUAVCount(); @@ -295,7 +308,7 @@ void ShaderResourceCacheD3D11::dbgVerifyCacheConsistency() { auto& Res = UAVResources[uav]; auto* pd3d11UAV = d3d11UAVs[uav]; - dbgVerifyResource(Res, pd3d11UAV, "UAV"); + DvpVerifyResource(Res, pd3d11UAV, "UAV"); } auto SamplerCount = GetSamplerCount(); @@ -310,4 +323,393 @@ void ShaderResourceCacheD3D11::dbgVerifyCacheConsistency() } } } +#endif + +template +void ShaderResourceCacheD3D11::ProcessResources(THandleResource HandleResources) +{ + { + ShaderResourceCacheD3D11::CachedCB* CachedCBs; + ID3D11Buffer** d3d11CBs; + TBindPointsAndActiveBits* bindPoints; + GetCBArrays(CachedCBs, d3d11CBs, bindPoints); + HandleResources(GetCBCount(), CachedCBs, d3d11CBs); + } + { + ShaderResourceCacheD3D11::CachedResource* CachedSRVResources; + ID3D11ShaderResourceView** d3d11SRVs; + TBindPointsAndActiveBits* bindPoints; + GetSRVArrays(CachedSRVResources, d3d11SRVs, bindPoints); + HandleResources(GetSRVCount(), CachedSRVResources, d3d11SRVs); + } + { + ShaderResourceCacheD3D11::CachedSampler* CachedSamplers; + ID3D11SamplerState** d3d11Samplers; + TBindPointsAndActiveBits* bindPoints; + GetSamplerArrays(CachedSamplers, d3d11Samplers, bindPoints); + HandleResources(GetSamplerCount(), CachedSamplers, d3d11Samplers); + } + { + ShaderResourceCacheD3D11::CachedResource* CachedUAVResources; + ID3D11UnorderedAccessView** d3d11UAVs; + TBindPointsAndActiveBits* bindPoints; + GetUAVArrays(CachedUAVResources, d3d11UAVs, bindPoints); + HandleResources(GetUAVCount(), CachedUAVResources, d3d11UAVs); + } +} + +void ShaderResourceCacheD3D11::TransitionResourceStates(DeviceContextD3D11Impl& Ctx, StateTransitionMode Mode) +{ + VERIFY_EXPR(IsInitialized()); + + switch (Mode) + { + case StateTransitionMode::Transition: + { + ProcessResources([&](Uint32 Count, auto* Resources, auto* Views) { TransitionResource(Ctx, Count, Resources, Views); }); + break; + } + case StateTransitionMode::Verify: + { +#ifdef DILIGENT_DEVELOPMENT + ProcessResources([&](Uint32 Count, auto* Resources, auto* Views) { DvpVerifyResourceState(Ctx, Count, Resources, Views); }); +#endif + break; + } + default: + UNEXPECTED("Unexpected mode"); + } +} + +void ShaderResourceCacheD3D11::TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedCB* CBs, ID3D11Buffer** pd3d11CBs) +{ + for (Uint32 i = 0; i < Count; ++i) + { + if (auto* pBuffer = CBs[i].pBuff.RawPtr()) + { + if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) + { /* + if (pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { + // Even though we have unbound resources from UAV, we only checked shader + // stages active in current PSO, so we still may need to unbind the resource + // from UAV (for instance, unbind resource from CS UAV when running draw command). + Ctx.UnbindResourceFromUAV(pBuffer, pd3d11CBs[i]); + pBuffer->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); + } + pBuffer->AddState(RESOURCE_STATE_CONSTANT_BUFFER);*/ + Ctx.TransitionResource(pBuffer, RESOURCE_STATE_CONSTANT_BUFFER); + } + } + } +} + +void ShaderResourceCacheD3D11::TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedResource* SRVResources, ID3D11ShaderResourceView** d3d11SRVs) +{ + for (Uint32 i = 0; i < Count; ++i) + { + auto& SRVRes = SRVResources[i]; + if (auto* pTexture = SRVRes.pTexture) + { + if (pTexture->IsInKnownState() && !pTexture->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) + { /* + if (pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { + // Even though we have unbound resources from UAV, we only checked shader + // stages active in current PSO, so we still may need to unbind the resource + // from UAV (for instance, unbind resource from CS UAV when running draw command). + Ctx.UnbindResourceFromUAV(pTexture, SRVRes.pd3d11Resource); + pTexture->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); + } + + if (pTexture->CheckState(RESOURCE_STATE_RENDER_TARGET)) + Ctx.UnbindTextureFromRenderTarget(pTexture); + + if (pTexture->CheckState(RESOURCE_STATE_DEPTH_WRITE)) + Ctx.UnbindTextureFromDepthStencil(pTexture); + + pTexture->SetState(RESOURCE_STATE_SHADER_RESOURCE);*/ + Ctx.TransitionResource(pTexture, RESOURCE_STATE_SHADER_RESOURCE); + } + } + else if (auto* pBuffer = SRVRes.pBuffer) + { + if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) + { /* + if (pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { + Ctx.UnbindResourceFromUAV(pBuffer, SRVRes.pd3d11Resource); + pBuffer->ClearState(RESOURCE_STATE_UNORDERED_ACCESS); + } + pBuffer->AddState(RESOURCE_STATE_SHADER_RESOURCE);*/ + Ctx.TransitionResource(pBuffer, RESOURCE_STATE_SHADER_RESOURCE); + } + } + } +} + +void ShaderResourceCacheD3D11::TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedSampler* Samplers, ID3D11SamplerState** pd3d11Samplers) +{ +} + +void ShaderResourceCacheD3D11::TransitionResource(DeviceContextD3D11Impl& Ctx, Uint32 Count, CachedResource* UAVResources, ID3D11UnorderedAccessView** pd3d11UAVs) +{ + for (Uint32 i = 0; i < Count; ++i) + { + auto& UAVRes = UAVResources[i]; + if (auto* pTexture = UAVRes.pTexture) + { + if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { /* + if (pTexture->CheckAnyState(RESOURCE_STATE_SHADER_RESOURCE | RESOURCE_STATE_INPUT_ATTACHMENT)) + Ctx.UnbindTextureFromInput(pTexture, UAVRes.pd3d11Resource); + pTexture->SetState(RESOURCE_STATE_UNORDERED_ACCESS);*/ + Ctx.TransitionResource(pTexture, RESOURCE_STATE_UNORDERED_ACCESS); + } + } + else if (auto* pBuffer = UAVRes.pBuffer) + { + if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { /* + if ((pBuffer->GetState() & RESOURCE_STATE_GENERIC_READ) != 0) + Ctx.UnbindBufferFromInput(pBuffer, UAVRes.pd3d11Resource); + pBuffer->SetState(RESOURCE_STATE_UNORDERED_ACCESS);*/ + Ctx.TransitionResource(pBuffer, RESOURCE_STATE_UNORDERED_ACCESS); + } + } + } +} + +#ifdef DILIGENT_DEVELOPMENT +void ShaderResourceCacheD3D11::DvpVerifyResourceState(DeviceContextD3D11Impl&, Uint32 Count, const CachedCB* CBs, ID3D11Buffer**) +{ + for (Uint32 i = 0; i < Count; ++i) + { + if (const auto* pBuff = CBs[i].pBuff.RawPtr()) + { + if (pBuff->IsInKnownState() && !pBuff->CheckState(RESOURCE_STATE_CONSTANT_BUFFER)) + { + LOG_ERROR_MESSAGE("Buffer '", pBuff->GetDesc().Name, "' has not been transitioned to Constant Buffer state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state."); + } + } + } +} + +void ShaderResourceCacheD3D11::DvpVerifyResourceState(DeviceContextD3D11Impl& Ctx, Uint32 Count, const CachedResource* SRVResources, ID3D11ShaderResourceView**) +{ + for (Uint32 i = 0; i < Count; ++i) + { + auto& SRVRes = SRVResources[i]; + if (const auto* pTexture = SRVRes.pTexture) + { + if (pTexture->IsInKnownState() && + !(pTexture->CheckState(RESOURCE_STATE_SHADER_RESOURCE) || Ctx.HasActiveRenderPass() && pTexture->CheckState(RESOURCE_STATE_INPUT_ATTACHMENT))) + { + LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state."); + } + } + else if (const auto* pBuffer = SRVRes.pBuffer) + { + if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_SHADER_RESOURCE)) + { + LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Shader Resource state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state."); + } + } + } +} + +void ShaderResourceCacheD3D11::DvpVerifyResourceState(DeviceContextD3D11Impl& Ctx, Uint32 Count, const CachedSampler* Samplers, ID3D11SamplerState**) +{ +} + +void ShaderResourceCacheD3D11::DvpVerifyResourceState(DeviceContextD3D11Impl&, Uint32 Count, const CachedResource* UAVResources, ID3D11UnorderedAccessView**) +{ + for (Uint32 i = 0; i < Count; ++i) + { + auto& UAVRes = UAVResources[i]; + if (const auto* pTexture = UAVRes.pTexture) + { + if (pTexture->IsInKnownState() && !pTexture->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("Texture '", pTexture->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the texture to required state."); + } + } + else if (const auto* pBuffer = UAVRes.pBuffer) + { + if (pBuffer->IsInKnownState() && !pBuffer->CheckState(RESOURCE_STATE_UNORDERED_ACCESS)) + { + LOG_ERROR_MESSAGE("Buffer '", pBuffer->GetDesc().Name, "' has not been transitioned to Unordered Access state. Call TransitionShaderResources(), use RESOURCE_STATE_TRANSITION_MODE_TRANSITION mode or explicitly transition the buffer to required state."); + } + } + } +} +#endif // DILIGENT_DEVELOPMENT + +void ShaderResourceCacheD3D11::BindResources(DeviceContextD3D11Impl& Ctx, const TBindingsPerStage& BaseBindings, TMinMaxSlotPerStage& MinMaxSlot, TCommittedResources& CommittedRes, SHADER_TYPE ActiveStages) const +{ + const auto CBCount = GetCBCount(); + if (CBCount != 0) + { + const auto Range = DESCRIPTOR_RANGE_CBV; + ShaderResourceCacheD3D11::CachedCB const* CBs; + ID3D11Buffer* const* d3d11CBs; + TBindPointsAndActiveBits const* bindPoints; + GetConstCBArrays(CBs, d3d11CBs, bindPoints); + + for (Uint32 cb = 0; cb < CBCount; ++cb) + { + Uint32 ActiveBits = bindPoints[cb][0] & ActiveStages; + const auto* BindPoints = &bindPoints[cb][1]; + VERIFY(ActiveBits != 0, "resource is not initialized"); + while (ActiveBits != 0) + { + const Uint32 ShaderInd = PlatformMisc::GetLSB(ActiveBits); + ActiveBits &= ~(1u << ShaderInd); + VERIFY_EXPR(BindPoints[ShaderInd] != InvalidBindPoint); + + auto* CommittedD3D11CBs = CommittedRes.D3D11CBs[ShaderInd]; + UINT& MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + UINT& MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + const UINT Slot = BaseBindings[ShaderInd][Range] + BindPoints[ShaderInd]; + const bool IsNewCB = CommittedD3D11CBs[Slot] != d3d11CBs[cb]; + MinSlot = IsNewCB ? std::min(MinSlot, Slot) : MinSlot; + MaxSlot = IsNewCB ? Slot : MaxSlot; + + VERIFY_EXPR(!IsNewCB || (Slot >= MinSlot && Slot <= MaxSlot)); + VERIFY_EXPR(d3d11CBs[cb] != nullptr); + CommittedD3D11CBs[Slot] = d3d11CBs[cb]; + } + } + } + + const auto SRVCount = GetSRVCount(); + if (SRVCount != 0) + { + const auto Range = DESCRIPTOR_RANGE_SRV; + ShaderResourceCacheD3D11::CachedResource const* SRVResources; + ID3D11ShaderResourceView* const* d3d11SRVs; + TBindPointsAndActiveBits const* bindPoints; + GetConstSRVArrays(SRVResources, d3d11SRVs, bindPoints); + + for (Uint32 srv = 0; srv < SRVCount; ++srv) + { + Uint32 ActiveBits = bindPoints[srv][0] & ActiveStages; + const auto* BindPoints = &bindPoints[srv][1]; + VERIFY(ActiveBits != 0, "resource is not initialized"); + while (ActiveBits != 0) + { + const Uint32 ShaderInd = PlatformMisc::GetLSB(ActiveBits); + ActiveBits &= ~(1u << ShaderInd); + VERIFY_EXPR(BindPoints[ShaderInd] != InvalidBindPoint); + + auto* CommittedD3D11SRVs = CommittedRes.D3D11SRVs[ShaderInd]; + auto* CommittedD3D11SRVRes = CommittedRes.D3D11SRVResources[ShaderInd]; + UINT& MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + UINT& MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + const UINT Slot = BaseBindings[ShaderInd][Range] + BindPoints[ShaderInd]; + const bool IsNewSRV = CommittedD3D11SRVs[Slot] != d3d11SRVs[srv]; + MinSlot = IsNewSRV ? std::min(MinSlot, Slot) : MinSlot; + MaxSlot = IsNewSRV ? Slot : MaxSlot; + + VERIFY_EXPR(!IsNewSRV || (Slot >= MinSlot && Slot <= MaxSlot)); + VERIFY_EXPR(d3d11SRVs[srv] != nullptr); + CommittedD3D11SRVRes[Slot] = SRVResources[srv].pd3d11Resource; + CommittedD3D11SRVs[Slot] = d3d11SRVs[srv]; + } + } + } + + const auto SamplerCount = GetSamplerCount(); + if (SamplerCount != 0) + { + const auto Range = DESCRIPTOR_RANGE_SAMPLER; + ShaderResourceCacheD3D11::CachedSampler const* Samplers; + ID3D11SamplerState* const* d3d11Samplers; + TBindPointsAndActiveBits const* bindPoints; + GetConstSamplerArrays(Samplers, d3d11Samplers, bindPoints); + + for (Uint32 sam = 0; sam < SamplerCount; ++sam) + { + Uint32 ActiveBits = bindPoints[sam][0] & ActiveStages; + const auto* BindPoints = &bindPoints[sam][1]; + VERIFY(ActiveBits != 0, "resource is not initialized"); + while (ActiveBits != 0) + { + const Uint32 ShaderInd = PlatformMisc::GetLSB(ActiveBits); + ActiveBits &= ~(1u << ShaderInd); + VERIFY_EXPR(BindPoints[ShaderInd] != InvalidBindPoint); + + auto* CommittedD3D11Samplers = CommittedRes.D3D11Samplers[ShaderInd]; + UINT& MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + UINT& MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + const UINT Slot = BaseBindings[ShaderInd][Range] + BindPoints[ShaderInd]; + const bool IsNewSam = CommittedD3D11Samplers[Slot] != d3d11Samplers[sam]; + MinSlot = IsNewSam ? std::min(MinSlot, Slot) : MinSlot; + MaxSlot = IsNewSam ? Slot : MaxSlot; + + VERIFY_EXPR(!IsNewSam || (Slot >= MinSlot && Slot <= MaxSlot)); + VERIFY_EXPR(d3d11Samplers[sam] != nullptr); + CommittedD3D11Samplers[Slot] = d3d11Samplers[sam]; + } + } + } + + const auto UAVCount = GetUAVCount(); + if (UAVCount != 0) + { + const auto Range = DESCRIPTOR_RANGE_UAV; + ShaderResourceCacheD3D11::CachedResource const* UAVResources; + ID3D11UnorderedAccessView* const* d3d11UAVs; + TBindPointsAndActiveBits const* bindPoints; + GetConstUAVArrays(UAVResources, d3d11UAVs, bindPoints); + + for (Uint32 uav = 0; uav < UAVCount; ++uav) + { + Uint32 ActiveBits = bindPoints[uav][0] & ActiveStages; + const auto* BindPoints = &bindPoints[uav][1]; + VERIFY(ActiveBits != 0, "resource is not initialized"); + while (ActiveBits != 0) + { + const Uint32 ShaderInd = PlatformMisc::GetLSB(ActiveBits); + ActiveBits &= ~(1u << ShaderInd); + VERIFY_EXPR(BindPoints[ShaderInd] != InvalidBindPoint); + + auto* CommittedD3D11UAVs = CommittedRes.D3D11UAVs[ShaderInd]; + auto* CommittedD3D11UAVRes = CommittedRes.D3D11UAVResources[ShaderInd]; + UINT& MinSlot = MinMaxSlot[ShaderInd][Range].MinSlot; + UINT& MaxSlot = MinMaxSlot[ShaderInd][Range].MaxSlot; + const UINT Slot = BaseBindings[ShaderInd][Range] + BindPoints[ShaderInd]; + const bool IsNewUAV = CommittedD3D11UAVs[Slot] != d3d11UAVs[uav]; + MinSlot = IsNewUAV ? std::min(MinSlot, Slot) : MinSlot; + MaxSlot = IsNewUAV ? Slot : MaxSlot; + + VERIFY_EXPR(!IsNewUAV || (Slot >= MinSlot && Slot <= MaxSlot)); + VERIFY_EXPR(d3d11UAVs[uav] != nullptr); + CommittedD3D11UAVRes[Slot] = UAVResources[uav].pd3d11Resource; + CommittedD3D11UAVs[Slot] = d3d11UAVs[uav]; + } + } + } +} + +void ShaderResourceCacheD3D11::TCommittedResources::Clear() +{ + for (int ShaderType = 0; ShaderType < NumShaderTypes; ++ShaderType) + { + // clang-format off + memset(D3D11CBs[ShaderType], 0, sizeof(D3D11CBs[ShaderType][0]) * NumCBs[ShaderType]); + memset(D3D11SRVs[ShaderType], 0, sizeof(D3D11SRVs[ShaderType][0]) * NumSRVs[ShaderType]); + memset(D3D11Samplers[ShaderType], 0, sizeof(D3D11Samplers[ShaderType][0]) * NumSamplers[ShaderType]); + memset(D3D11UAVs[ShaderType], 0, sizeof(D3D11UAVs[ShaderType][0]) * NumUAVs[ShaderType]); + memset(D3D11SRVResources[ShaderType], 0, sizeof(D3D11SRVResources[ShaderType][0]) * NumSRVs[ShaderType]); + memset(D3D11UAVResources[ShaderType], 0, sizeof(D3D11UAVResources[ShaderType][0]) * NumUAVs[ShaderType]); + // clang-format on + + NumCBs[ShaderType] = 0; + NumSRVs[ShaderType] = 0; + NumSamplers[ShaderType] = 0; + NumUAVs[ShaderType] = 0; + } +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp deleted file mode 100755 index 6e577314..00000000 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ /dev/null @@ -1,1022 +0,0 @@ -/* - * Copyright 2019-2021 Diligent Graphics LLC - * Copyright 2015-2019 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#include "pch.h" - -#include - -#include "ShaderResourceLayoutD3D11.hpp" -#include "ShaderResourceCacheD3D11.hpp" -#include "BufferD3D11Impl.hpp" -#include "BufferViewD3D11Impl.hpp" -#include "TextureBaseD3D11.hpp" -#include "TextureViewD3D11.h" -#include "SamplerD3D11Impl.hpp" -#include "ShaderD3D11Impl.hpp" -#include "ShaderResourceVariableBase.hpp" - -namespace Diligent -{ - - -ShaderResourceLayoutD3D11::~ShaderResourceLayoutD3D11() -{ - // clang-format off - HandleResources( - [&](ConstBuffBindInfo& cb) - { - cb.~ConstBuffBindInfo(); - }, - - [&](TexSRVBindInfo& ts) - { - ts.~TexSRVBindInfo(); - }, - - [&](TexUAVBindInfo& uav) - { - uav.~TexUAVBindInfo(); - }, - - [&](BuffSRVBindInfo& srv) - { - srv.~BuffSRVBindInfo(); - }, - - [&](BuffUAVBindInfo& uav) - { - uav.~BuffUAVBindInfo(); - }, - - [&](SamplerBindInfo& sam) - { - sam.~SamplerBindInfo(); - } - ); - // clang-format on -} - - -size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes) noexcept -{ - // Skip immutable samplers as they are initialized directly in the resource cache by the PSO - constexpr bool CountImtblSamplers = false; - auto ResCounters = SrcResources.CountResources(ResourceLayout, AllowedVarTypes, NumAllowedTypes, CountImtblSamplers); - // clang-format off - auto MemSize = ResCounters.NumCBs * sizeof(ConstBuffBindInfo) + - ResCounters.NumTexSRVs * sizeof(TexSRVBindInfo) + - ResCounters.NumTexUAVs * sizeof(TexUAVBindInfo) + - ResCounters.NumBufSRVs * sizeof(BuffSRVBindInfo) + - ResCounters.NumBufUAVs * sizeof(BuffUAVBindInfo) + - ResCounters.NumSamplers * sizeof(SamplerBindInfo); - // clang-format on - return MemSize; -} - - -void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr pSrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, - Uint32 NumVarTypes, - IMemoryAllocator& ResCacheDataAllocator, - IMemoryAllocator& ResLayoutDataAllocator) -{ - m_pResources = std::move(pSrcResources); - - // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-layout#Shader-Resource-Layout-Initialization - - const auto AllowedTypeBits = GetAllowedTypeBits(VarTypes, NumVarTypes); - - // Count total number of resources of allowed types - // Skip immutable samplers as they are initialized directly in the resource cache by the PSO - constexpr bool CountImtblSamplers = false; - auto ResCounters = m_pResources->CountResources(ResourceLayout, VarTypes, NumVarTypes, CountImtblSamplers); - - // Initialize offsets - size_t CurrentOffset = 0; - - auto AdvanceOffset = [&CurrentOffset](size_t NumBytes) // - { - constexpr size_t MaxOffset = std::numeric_limits::max(); - VERIFY(CurrentOffset <= MaxOffset, "Current offser (", CurrentOffset, ") exceeds max allowed value (", MaxOffset, ")"); - auto Offset = static_cast(CurrentOffset); - CurrentOffset += NumBytes; - return Offset; - }; - - // clang-format off - auto CBOffset = AdvanceOffset(ResCounters.NumCBs * sizeof(ConstBuffBindInfo)); (void)CBOffset; // To suppress warning - m_TexSRVsOffset = AdvanceOffset(ResCounters.NumTexSRVs * sizeof(TexSRVBindInfo) ); - m_TexUAVsOffset = AdvanceOffset(ResCounters.NumTexUAVs * sizeof(TexUAVBindInfo) ); - m_BuffSRVsOffset = AdvanceOffset(ResCounters.NumBufSRVs * sizeof(BuffSRVBindInfo) ); - m_BuffUAVsOffset = AdvanceOffset(ResCounters.NumBufUAVs * sizeof(BuffUAVBindInfo) ); - m_SamplerOffset = AdvanceOffset(ResCounters.NumSamplers * sizeof(SamplerBindInfo) ); - m_MemorySize = AdvanceOffset(0); - // clang-format on - - VERIFY_EXPR(m_MemorySize == GetRequiredMemorySize(*m_pResources, ResourceLayout, VarTypes, NumVarTypes)); - - if (m_MemorySize) - { - auto* pRawMem = ALLOCATE_RAW(ResLayoutDataAllocator, "Raw memory buffer for shader resource layout resources", m_MemorySize); - m_ResourceBuffer = std::unique_ptr>(pRawMem, ResLayoutDataAllocator); - } - - // clang-format off - VERIFY_EXPR(ResCounters.NumCBs == GetNumCBs() ); - VERIFY_EXPR(ResCounters.NumTexSRVs == GetNumTexSRVs() ); - VERIFY_EXPR(ResCounters.NumTexUAVs == GetNumTexUAVs() ); - VERIFY_EXPR(ResCounters.NumBufSRVs == GetNumBufSRVs() ); - VERIFY_EXPR(ResCounters.NumBufUAVs == GetNumBufUAVs() ); - VERIFY_EXPR(ResCounters.NumSamplers== GetNumSamplers()); - // clang-format on - - // Current resource index for every resource type - Uint32 cb = 0; - Uint32 texSrv = 0; - Uint32 texUav = 0; - Uint32 bufSrv = 0; - Uint32 bufUav = 0; - Uint32 sam = 0; - - Uint32 NumCBSlots = 0; - Uint32 NumSRVSlots = 0; - Uint32 NumSamplerSlots = 0; - Uint32 NumUAVSlots = 0; - m_pResources->ProcessResources( - [&](const D3DShaderResourceAttribs& CB, Uint32) // - { - auto VarType = m_pResources->FindVariableType(CB, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - // Initialize current CB in place, increment CB counter - new (&GetResource(cb++)) ConstBuffBindInfo(CB, *this, VarType); - NumCBSlots = std::max(NumCBSlots, Uint32{CB.BindPoint} + Uint32{CB.BindCount}); - } - }, - - [&](const D3DShaderResourceAttribs& Sampler, Uint32) // - { - auto VarType = m_pResources->FindVariableType(Sampler, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - // Constructor of PipelineStateD3D11Impl initializes immutable samplers and will log the error, if any - constexpr bool LogImtblSamplerArrayError = false; - auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sampler, ResourceLayout, LogImtblSamplerArrayError); - if (ImtblSamplerInd >= 0) - { - // Skip immutble samplers as they are initialized directly in the resource cache by the PSO - return; - } - // Initialize current sampler in place, increment sampler counter - new (&GetResource(sam++)) SamplerBindInfo(Sampler, *this, VarType); - NumSamplerSlots = std::max(NumSamplerSlots, Uint32{Sampler.BindPoint} + Uint32{Sampler.BindCount}); - } - }, - - [&](const D3DShaderResourceAttribs& TexSRV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(TexSRV, ResourceLayout); - if (!IsAllowedType(VarType, AllowedTypeBits)) - return; - - auto NumSamplers = GetNumSamplers(); - VERIFY(sam == NumSamplers, "All samplers must be initialized before texture SRVs"); - - Uint32 AssignedSamplerIndex = TexSRVBindInfo::InvalidSamplerIndex; - if (TexSRV.IsCombinedWithSampler()) - { - const auto& AssignedSamplerAttribs = m_pResources->GetCombinedSampler(TexSRV); - auto AssignedSamplerType = m_pResources->FindVariableType(AssignedSamplerAttribs, ResourceLayout); - VERIFY(AssignedSamplerType == VarType, - "The type (", GetShaderVariableTypeLiteralName(VarType), ") of texture SRV variable '", TexSRV.Name, - "' is not consistent with the type (", GetShaderVariableTypeLiteralName(AssignedSamplerType), - ") of the sampler '", AssignedSamplerAttribs.Name, - "' that is assigned to it. This should never happen as when combined texture samplers are used, " - "the type of the sampler is derived from the type of the texture it is assigned to SRV."); - - bool SamplerFound = false; - for (AssignedSamplerIndex = 0; AssignedSamplerIndex < NumSamplers; ++AssignedSamplerIndex) - { - const auto& Sampler = GetResource(AssignedSamplerIndex); - SamplerFound = strcmp(Sampler.m_Attribs.Name, AssignedSamplerAttribs.Name) == 0; - if (SamplerFound) - break; // Otherwise AssignedSamplerIndex will be incremented - } - - if (!SamplerFound) - { - AssignedSamplerIndex = TexSRVBindInfo::InvalidSamplerIndex; -#ifdef DILIGENT_DEBUG - // Shader error will be logged by the PipelineStateD3D11Impl - constexpr bool LogImtblSamplerArrayError = false; - if (m_pResources->FindImmutableSampler(AssignedSamplerAttribs, ResourceLayout, LogImtblSamplerArrayError) < 0) - { - UNEXPECTED("Unable to find non-immutable sampler assigned to texture SRV '", TexSRV.Name, "'."); - } -#endif - } - else - { -#ifdef DILIGENT_DEBUG - // Shader error will be logged by the PipelineStateD3D11Impl - constexpr bool LogImtblSamplerArrayError = false; - if (m_pResources->FindImmutableSampler(AssignedSamplerAttribs, ResourceLayout, LogImtblSamplerArrayError) >= 0) - { - UNEXPECTED("Immutable sampler '", AssignedSamplerAttribs.Name, "' is assigned to texture SRV '", TexSRV.Name, "'."); - } -#endif - } - } - - // Initialize tex SRV in place, increment counter of tex SRVs - new (&GetResource(texSrv++)) TexSRVBindInfo(TexSRV, AssignedSamplerIndex, *this, VarType); - NumSRVSlots = std::max(NumSRVSlots, Uint32{TexSRV.BindPoint} + Uint32{TexSRV.BindCount}); - }, - - [&](const D3DShaderResourceAttribs& TexUAV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(TexUAV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - // Initialize tex UAV in place, increment counter of tex UAVs - new (&GetResource(texUav++)) TexUAVBindInfo(TexUAV, *this, VarType); - NumUAVSlots = std::max(NumUAVSlots, Uint32{TexUAV.BindPoint} + Uint32{TexUAV.BindCount}); - } - }, - - [&](const D3DShaderResourceAttribs& BuffSRV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(BuffSRV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - // Initialize buff SRV in place, increment counter of buff SRVs - new (&GetResource(bufSrv++)) BuffSRVBindInfo(BuffSRV, *this, VarType); - NumSRVSlots = std::max(NumSRVSlots, Uint32{BuffSRV.BindPoint} + Uint32{BuffSRV.BindCount}); - } - }, - - [&](const D3DShaderResourceAttribs& BuffUAV, Uint32) // - { - auto VarType = m_pResources->FindVariableType(BuffUAV, ResourceLayout); - if (IsAllowedType(VarType, AllowedTypeBits)) - { - // Initialize buff UAV in place, increment counter of buff UAVs - new (&GetResource(bufUav++)) BuffUAVBindInfo(BuffUAV, *this, VarType); - NumUAVSlots = std::max(NumUAVSlots, Uint32{BuffUAV.BindPoint} + Uint32{BuffUAV.BindCount}); - } - }, - - [&](const D3DShaderResourceAttribs&, Uint32) // - { - UNEXPECTED("acceleration structure is not supported in DirectX 11"); - }); - - // clang-format off - VERIFY(cb == GetNumCBs(), "Not all CBs are initialized which will cause a crash when dtor is called"); - VERIFY(texSrv == GetNumTexSRVs(), "Not all Tex SRVs are initialized which will cause a crash when dtor is called"); - VERIFY(texUav == GetNumTexUAVs(), "Not all Tex UAVs are initialized which will cause a crash when dtor is called"); - VERIFY(bufSrv == GetNumBufSRVs(), "Not all Buf SRVs are initialized which will cause a crash when dtor is called"); - VERIFY(bufUav == GetNumBufUAVs(), "Not all Buf UAVs are initialized which will cause a crash when dtor is called"); - VERIFY(sam == GetNumSamplers(), "Not all samplers are initialized which will cause a crash when dtor is called"); - // clang-format on - - // Shader resource cache in the SRB is initialized by the constructor of ShaderResourceBindingD3D11Impl to - // hold all variable types. The corresponding layout in the SRB is initialized to keep mutable and dynamic - // variables only - // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache#Shader-Resource-Cache-Initialization - if (!m_ResourceCache.IsInitialized()) - { - // NOTE that here we are using max bind points required to cache only the shader variables of allowed types! - m_ResourceCache.Initialize(NumCBSlots, NumSRVSlots, NumSamplerSlots, NumUAVSlots, ResCacheDataAllocator); - } -} - -void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache) const -{ - // clang-format off - VERIFY( DstCache.GetCBCount() >= m_ResourceCache.GetCBCount(), "Dst cache is not large enough to contain all CBs" ); - VERIFY( DstCache.GetSRVCount() >= m_ResourceCache.GetSRVCount(), "Dst cache is not large enough to contain all SRVs" ); - VERIFY( DstCache.GetSamplerCount() >= m_ResourceCache.GetSamplerCount(), "Dst cache is not large enough to contain all samplers" ); - VERIFY( DstCache.GetUAVCount() >= m_ResourceCache.GetUAVCount(), "Dst cache is not large enough to contain all UAVs" ); - // clang-format on - - ShaderResourceCacheD3D11::CachedCB* CachedCBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - ShaderResourceCacheD3D11::CachedResource* CachedSRVResources = nullptr; - ID3D11ShaderResourceView** d3d11SRVs = nullptr; - ShaderResourceCacheD3D11::CachedSampler* CachedSamplers = nullptr; - ID3D11SamplerState** d3d11Samplers = nullptr; - ShaderResourceCacheD3D11::CachedResource* CachedUAVResources = nullptr; - ID3D11UnorderedAccessView** d3d11UAVs = nullptr; - // clang-format off - m_ResourceCache.GetCBArrays (CachedCBs, d3d11CBs); - m_ResourceCache.GetSRVArrays (CachedSRVResources, d3d11SRVs); - m_ResourceCache.GetSamplerArrays(CachedSamplers, d3d11Samplers); - m_ResourceCache.GetUAVArrays (CachedUAVResources, d3d11UAVs); - // clang-format on - - - ShaderResourceCacheD3D11::CachedCB* DstCBs = nullptr; - ID3D11Buffer** DstD3D11CBs = nullptr; - ShaderResourceCacheD3D11::CachedResource* DstSRVResources = nullptr; - ID3D11ShaderResourceView** DstD3D11SRVs = nullptr; - ShaderResourceCacheD3D11::CachedSampler* DstSamplers = nullptr; - ID3D11SamplerState** DstD3D11Samplers = nullptr; - ShaderResourceCacheD3D11::CachedResource* DstUAVResources = nullptr; - ID3D11UnorderedAccessView** DstD3D11UAVs = nullptr; - // clang-format off - DstCache.GetCBArrays (DstCBs, DstD3D11CBs); - DstCache.GetSRVArrays (DstSRVResources, DstD3D11SRVs); - DstCache.GetSamplerArrays(DstSamplers, DstD3D11Samplers); - DstCache.GetUAVArrays (DstUAVResources, DstD3D11UAVs); - // clang-format on - - HandleConstResources( - [&](const ConstBuffBindInfo& cb) // - { - for (auto CBSlot = cb.m_Attribs.BindPoint; CBSlot < cb.m_Attribs.BindPoint + cb.m_Attribs.BindCount; ++CBSlot) - { - VERIFY_EXPR(CBSlot < m_ResourceCache.GetCBCount() && CBSlot < DstCache.GetCBCount()); - DstCBs[CBSlot] = CachedCBs[CBSlot]; - DstD3D11CBs[CBSlot] = d3d11CBs[CBSlot]; - } - }, - - [&](const TexSRVBindInfo& ts) // - { - for (auto SRVSlot = ts.m_Attribs.BindPoint; SRVSlot < ts.m_Attribs.BindPoint + ts.m_Attribs.BindCount; ++SRVSlot) - { - VERIFY_EXPR(SRVSlot < m_ResourceCache.GetSRVCount() && SRVSlot < DstCache.GetSRVCount()); - DstSRVResources[SRVSlot] = CachedSRVResources[SRVSlot]; - DstD3D11SRVs[SRVSlot] = d3d11SRVs[SRVSlot]; - } - }, - - [&](const TexUAVBindInfo& uav) // - { - for (auto UAVSlot = uav.m_Attribs.BindPoint; UAVSlot < uav.m_Attribs.BindPoint + uav.m_Attribs.BindCount; ++UAVSlot) - { - VERIFY_EXPR(UAVSlot < m_ResourceCache.GetUAVCount() && UAVSlot < DstCache.GetUAVCount()); - DstUAVResources[UAVSlot] = CachedUAVResources[UAVSlot]; - DstD3D11UAVs[UAVSlot] = d3d11UAVs[UAVSlot]; - } - }, - - [&](const BuffSRVBindInfo& srv) // - { - for (auto SRVSlot = srv.m_Attribs.BindPoint; SRVSlot < srv.m_Attribs.BindPoint + srv.m_Attribs.BindCount; ++SRVSlot) - { - VERIFY_EXPR(SRVSlot < m_ResourceCache.GetSRVCount() && SRVSlot < DstCache.GetSRVCount()); - DstSRVResources[SRVSlot] = CachedSRVResources[SRVSlot]; - DstD3D11SRVs[SRVSlot] = d3d11SRVs[SRVSlot]; - } - }, - - [&](const BuffUAVBindInfo& uav) // - { - for (auto UAVSlot = uav.m_Attribs.BindPoint; UAVSlot < uav.m_Attribs.BindPoint + uav.m_Attribs.BindCount; ++UAVSlot) - { - VERIFY_EXPR(UAVSlot < m_ResourceCache.GetUAVCount() && UAVSlot < DstCache.GetUAVCount()); - DstUAVResources[UAVSlot] = CachedUAVResources[UAVSlot]; - DstD3D11UAVs[UAVSlot] = d3d11UAVs[UAVSlot]; - } - }, - - [&](const SamplerBindInfo& sam) // - { - //VERIFY(!sam.IsImmutableSampler, "Variables are not created for immutable samplers"); - for (auto SamSlot = sam.m_Attribs.BindPoint; SamSlot < sam.m_Attribs.BindPoint + sam.m_Attribs.BindCount; ++SamSlot) - { - VERIFY_EXPR(SamSlot < m_ResourceCache.GetSamplerCount() && SamSlot < DstCache.GetSamplerCount()); - DstSamplers[SamSlot] = CachedSamplers[SamSlot]; - DstD3D11Samplers[SamSlot] = d3d11Samplers[SamSlot]; - } - }); -} - -void ShaderResourceLayoutD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* pBuffer, - Uint32 ArrayIndex) -{ - DEV_CHECK_ERR(ArrayIndex < m_Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", m_Attribs.Name, "'. Max allowed index: ", m_Attribs.BindCount - 1); - - // We cannot use ValidatedCast<> here as the resource retrieved from the - // resource mapping can be of wrong type - RefCntAutoPtr pBuffD3D11Impl{pBuffer, IID_BufferD3D11}; -#ifdef DILIGENT_DEVELOPMENT - { - auto& CachedCB = m_ParentResLayout.m_ResourceCache.GetCB(m_Attribs.BindPoint + ArrayIndex); - VerifyConstantBufferBinding(m_Attribs, GetType(), ArrayIndex, pBuffer, pBuffD3D11Impl.RawPtr(), CachedCB.pBuff.RawPtr(), m_ParentResLayout.GetShaderName()); - } -#endif - m_ParentResLayout.m_ResourceCache.SetCB(m_Attribs.BindPoint + ArrayIndex, std::move(pBuffD3D11Impl)); -} - - -void ShaderResourceLayoutD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pView, - Uint32 ArrayIndex) -{ - DEV_CHECK_ERR(ArrayIndex < m_Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", m_Attribs.Name, "'. Max allowed index: ", m_Attribs.BindCount - 1); - auto& ResourceCache = m_ParentResLayout.m_ResourceCache; - - // We cannot use ValidatedCast<> here as the resource retrieved from the - // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11{pView, IID_TextureViewD3D11}; -#ifdef DILIGENT_DEVELOPMENT - { - auto& CachedSRV = ResourceCache.GetSRV(m_Attribs.BindPoint + ArrayIndex); - VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, - CachedSRV.pView.RawPtr(), m_ParentResLayout.GetShaderName()); - } -#endif - - if (ValidSamplerAssigned()) - { - auto& Sampler = m_ParentResLayout.GetResource(SamplerIndex); - //VERIFY(!Sampler.IsImmutableSampler, "Immutable samplers are not assigned to texture SRVs as they are initialized directly in the shader resource cache"); - VERIFY_EXPR(Sampler.m_Attribs.BindCount == m_Attribs.BindCount || Sampler.m_Attribs.BindCount == 1); - auto SamplerBindPoint = Sampler.m_Attribs.BindPoint + (Sampler.m_Attribs.BindCount != 1 ? ArrayIndex : 0); - - SamplerD3D11Impl* pSamplerD3D11Impl = nullptr; - if (pViewD3D11) - { - pSamplerD3D11Impl = ValidatedCast(pViewD3D11->GetSampler()); -#ifdef DILIGENT_DEVELOPMENT - if (pSamplerD3D11Impl == nullptr) - { - if (Sampler.m_Attribs.BindCount > 1) - LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", Sampler.m_Attribs.Name, "[", ArrayIndex, "]'. Sampler is not set in the texture view '", pViewD3D11->GetDesc().Name, "'"); - else - LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", Sampler.m_Attribs.Name, "'. Sampler is not set in the texture view '", pViewD3D11->GetDesc().Name, "'"); - } -#endif - } -#ifdef DILIGENT_DEVELOPMENT - if (Sampler.GetType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) - { - auto& CachedSampler = ResourceCache.GetSampler(SamplerBindPoint); - if (CachedSampler.pSampler != nullptr && CachedSampler.pSampler != pSamplerD3D11Impl) - { - auto VarTypeStr = GetShaderVariableTypeLiteralName(GetType()); - LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", Sampler.m_Attribs.GetPrintName(ArrayIndex), "' in shader '", m_ParentResLayout.GetShaderName(), "'. Attempting to bind another sampler or null is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."); - } - } -#endif - ResourceCache.SetSampler(SamplerBindPoint, pSamplerD3D11Impl); - } - - ResourceCache.SetTexSRV(m_Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); -} - -void ShaderResourceLayoutD3D11::SamplerBindInfo::BindResource(IDeviceObject* pSampler, - Uint32 ArrayIndex) -{ - DEV_CHECK_ERR(ArrayIndex < m_Attribs.BindCount, - "Array index (", ArrayIndex, ") is out of range for variable '", m_Attribs.Name, - "'. Max allowed index: ", m_Attribs.BindCount - 1); - auto& ResourceCache = m_ParentResLayout.m_ResourceCache; - //VERIFY(!IsImmutableSampler, "Cannot bind sampler to an immutable sampler"); - - // We cannot use ValidatedCast<> here as the resource retrieved from the - // resource mapping can be of wrong type - RefCntAutoPtr pSamplerD3D11{pSampler, IID_SamplerD3D11}; - -#ifdef DILIGENT_DEVELOPMENT - if (pSampler && !pSamplerD3D11) - { - LOG_ERROR_MESSAGE("Failed to bind object '", pSampler->GetDesc().Name, "' to variable '", m_Attribs.GetPrintName(ArrayIndex), - "' in shader '", m_ParentResLayout.GetShaderName(), "'. Incorect object type: sampler is expected."); - } - - if (m_Attribs.IsCombinedWithTexSRV()) - { - auto* TexSRVName = m_ParentResLayout.m_pResources->GetCombinedTextureSRV(m_Attribs).Name; - LOG_WARNING_MESSAGE("Texture sampler sampler '", m_Attribs.Name, "' is assigned to texture SRV '", - TexSRVName, "' and should not be accessed directly. The sampler is initialized when texture SRV is set to '", - TexSRVName, "' variable."); - } - - if (GetType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) - { - auto& CachedSampler = ResourceCache.GetSampler(m_Attribs.BindPoint + ArrayIndex); - if (CachedSampler.pSampler != nullptr && CachedSampler.pSampler != pSamplerD3D11) - { - auto VarTypeStr = GetShaderVariableTypeLiteralName(GetType()); - LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", - m_Attribs.GetPrintName(ArrayIndex), "' in shader '", m_ParentResLayout.GetShaderName(), - "'. Attempting to bind another sampler or null is an error and may cause unpredicted behavior. " - "Use another shader resource binding instance or label the variable as dynamic."); - } - } -#endif - - ResourceCache.SetSampler(m_Attribs.BindPoint + ArrayIndex, std::move(pSamplerD3D11)); -} - -void ShaderResourceLayoutD3D11::BuffSRVBindInfo::BindResource(IDeviceObject* pView, - Uint32 ArrayIndex) -{ - DEV_CHECK_ERR(ArrayIndex < m_Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", - m_Attribs.Name, "'. Max allowed index: ", m_Attribs.BindCount - 1); - auto& ResourceCache = m_ParentResLayout.m_ResourceCache; - - // We cannot use ValidatedCast<> here as the resource retrieved from the - // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11{pView, IID_BufferViewD3D11}; -#ifdef DILIGENT_DEVELOPMENT - { - auto& CachedSRV = ResourceCache.GetSRV(m_Attribs.BindPoint + ArrayIndex); - VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE}, - CachedSRV.pView.RawPtr(), m_ParentResLayout.GetShaderName()); - VerifyBufferViewModeD3D(pViewD3D11.RawPtr(), m_Attribs, m_ParentResLayout.GetShaderName()); - } -#endif - ResourceCache.SetBufSRV(m_Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); -} - - -void ShaderResourceLayoutD3D11::TexUAVBindInfo::BindResource(IDeviceObject* pView, - Uint32 ArrayIndex) -{ - DEV_CHECK_ERR(ArrayIndex < m_Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", - m_Attribs.Name, "'. Max allowed index: ", m_Attribs.BindCount - 1); - auto& ResourceCache = m_ParentResLayout.m_ResourceCache; - - // We cannot use ValidatedCast<> here as the resource retrieved from the - // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11{pView, IID_TextureViewD3D11}; -#ifdef DILIGENT_DEVELOPMENT - { - auto& CachedUAV = ResourceCache.GetUAV(m_Attribs.BindPoint + ArrayIndex); - VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_UNORDERED_ACCESS}, - CachedUAV.pView.RawPtr(), m_ParentResLayout.GetShaderName()); - } -#endif - ResourceCache.SetTexUAV(m_Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); -} - - -void ShaderResourceLayoutD3D11::BuffUAVBindInfo::BindResource(IDeviceObject* pView, - Uint32 ArrayIndex) -{ - DEV_CHECK_ERR(ArrayIndex < m_Attribs.BindCount, "Array index (", ArrayIndex, ") is out of range for variable '", - m_Attribs.Name, "'. Max allowed index: ", m_Attribs.BindCount - 1); - auto& ResourceCache = m_ParentResLayout.m_ResourceCache; - - // We cannot use ValidatedCast<> here as the resource retrieved from the - // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11{pView, IID_BufferViewD3D11}; -#ifdef DILIGENT_DEVELOPMENT - { - auto& CachedUAV = ResourceCache.GetUAV(m_Attribs.BindPoint + ArrayIndex); - VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_UNORDERED_ACCESS}, - CachedUAV.pView.RawPtr(), m_ParentResLayout.GetShaderName()); - VerifyBufferViewModeD3D(pViewD3D11.RawPtr(), m_Attribs, m_ParentResLayout.GetShaderName()); - } -#endif - ResourceCache.SetBufUAV(m_Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11)); -} - - - -// Helper template class that facilitates binding CBs, SRVs, and UAVs -class BindResourceHelper -{ -public: - BindResourceHelper(IResourceMapping& RM, Uint32 Fl) : - ResourceMapping{RM}, - Flags{Fl} - { - } - - template - void Bind(ResourceType& Res) - { - if ((Flags & (1 << Res.GetType())) == 0) - return; - - for (Uint16 elem = 0; elem < Res.m_Attribs.BindCount; ++elem) - { - if ((Flags & BIND_SHADER_RESOURCES_KEEP_EXISTING) && Res.IsBound(elem)) - continue; - - const auto* VarName = Res.m_Attribs.Name; - RefCntAutoPtr pRes; - ResourceMapping.GetResource(VarName, &pRes, elem); - if (pRes) - { - // Call non-virtual function - Res.BindResource(pRes, elem); - } - else - { - if ((Flags & BIND_SHADER_RESOURCES_VERIFY_ALL_RESOLVED) && !Res.IsBound(elem)) - { - LOG_ERROR_MESSAGE("Unable to bind resource to shader variable '", VarName, - "': resource is not found in the resource mapping"); - } - } - } - } - -private: - IResourceMapping& ResourceMapping; - const Uint32 Flags; -}; - -void ShaderResourceLayoutD3D11::BindResources(IResourceMapping* pResourceMapping, - Uint32 Flags, - const ShaderResourceCacheD3D11& dbgResourceCache) -{ - VERIFY(&dbgResourceCache == &m_ResourceCache, "Resource cache does not match the cache provided at initialization"); - - if (pResourceMapping == nullptr) - { - LOG_ERROR_MESSAGE("Failed to bind resources in shader '", GetShaderName(), "': resource mapping is null"); - return; - } - - if ((Flags & BIND_SHADER_RESOURCES_UPDATE_ALL) == 0) - Flags |= BIND_SHADER_RESOURCES_UPDATE_ALL; - - BindResourceHelper BindResHelper(*pResourceMapping, Flags); - - // clang-format off - HandleResources( - [&](ConstBuffBindInfo& cb) - { - BindResHelper.Bind(cb); - }, - - [&](TexSRVBindInfo& ts) - { - BindResHelper.Bind(ts); - }, - - [&](TexUAVBindInfo& uav) - { - BindResHelper.Bind(uav); - }, - - [&](BuffSRVBindInfo& srv) - { - BindResHelper.Bind(srv); - }, - - [&](BuffUAVBindInfo& uav) - { - BindResHelper.Bind(uav); - }, - - [&](SamplerBindInfo& sam) - { - if (!m_pResources->IsUsingCombinedTextureSamplers()) - BindResHelper.Bind(sam); - } - ); - // clang-format on -} - -template -IShaderResourceVariable* ShaderResourceLayoutD3D11::GetResourceByName(const Char* Name) -{ - auto NumResources = GetNumResources(); - for (Uint32 res = 0; res < NumResources; ++res) - { - auto& Resource = GetResource(res); - if (strcmp(Resource.m_Attribs.Name, Name) == 0) - return &Resource; - } - - return nullptr; -} - -IShaderResourceVariable* ShaderResourceLayoutD3D11::GetShaderVariable(const Char* Name) -{ - if (auto* pCB = GetResourceByName(Name)) - return pCB; - - if (auto* pTexSRV = GetResourceByName(Name)) - return pTexSRV; - - if (auto* pTexUAV = GetResourceByName(Name)) - return pTexUAV; - - if (auto* pBuffSRV = GetResourceByName(Name)) - return pBuffSRV; - - if (auto* pBuffUAV = GetResourceByName(Name)) - return pBuffUAV; - - if (!m_pResources->IsUsingCombinedTextureSamplers()) - { - // Immutable samplers are never created in the resource layout - if (auto* pSampler = GetResourceByName(Name)) - return pSampler; - } - - return nullptr; -} - -class ShaderVariableIndexLocator -{ -public: - ShaderVariableIndexLocator(const ShaderResourceLayoutD3D11& _Layout, const ShaderResourceLayoutD3D11::ShaderVariableD3D11Base& Variable) : - // clang-format off - Layout {_Layout}, - VarOffset(reinterpret_cast(&Variable) - reinterpret_cast(_Layout.m_ResourceBuffer.get())) - // clang-format on - {} - - template - bool TryResource(ShaderResourceLayoutD3D11::OffsetType NextResourceTypeOffset) - { -#ifdef DILIGENT_DEBUG - { - VERIFY(Layout.GetResourceOffset() >= dbgPreviousResourceOffset, "Resource types are processed out of order!"); - dbgPreviousResourceOffset = Layout.GetResourceOffset(); - VERIFY_EXPR(NextResourceTypeOffset >= Layout.GetResourceOffset()); - } -#endif - if (VarOffset < NextResourceTypeOffset) - { - auto RelativeOffset = VarOffset - Layout.GetResourceOffset(); - DEV_CHECK_ERR(RelativeOffset % sizeof(ResourceType) == 0, "Offset is not multiple of resource type (", sizeof(ResourceType), ")"); - Index += static_cast(RelativeOffset / sizeof(ResourceType)); - return true; - } - else - { - Index += Layout.GetNumResources(); - return false; - } - } - - Uint32 GetIndex() const { return Index; } - -private: - const ShaderResourceLayoutD3D11& Layout; - const size_t VarOffset; - Uint32 Index = 0; -#ifdef DILIGENT_DEBUG - Uint32 dbgPreviousResourceOffset = 0; -#endif -}; - -Uint32 ShaderResourceLayoutD3D11::GetVariableIndex(const ShaderVariableD3D11Base& Variable) const -{ - if (!m_ResourceBuffer) - { - LOG_ERROR("This shader resource layout does not have resources"); - return static_cast(-1); - } - - ShaderVariableIndexLocator IdxLocator(*this, Variable); - if (IdxLocator.TryResource(m_TexSRVsOffset)) - return IdxLocator.GetIndex(); - - if (IdxLocator.TryResource(m_TexUAVsOffset)) - return IdxLocator.GetIndex(); - - if (IdxLocator.TryResource(m_BuffSRVsOffset)) - return IdxLocator.GetIndex(); - - if (IdxLocator.TryResource(m_BuffUAVsOffset)) - return IdxLocator.GetIndex(); - - if (IdxLocator.TryResource(m_SamplerOffset)) - return IdxLocator.GetIndex(); - - if (!m_pResources->IsUsingCombinedTextureSamplers()) - { - if (IdxLocator.TryResource(m_MemorySize)) - return IdxLocator.GetIndex(); - } - - LOG_ERROR("Failed to get variable index. The variable ", &Variable, " does not belong to this shader resource layout"); - return static_cast(-1); -} - -class ShaderVariableLocator -{ -public: - ShaderVariableLocator(ShaderResourceLayoutD3D11& _Layout, Uint32 _Index) : - // clang-format off - Layout{_Layout}, - Index {_Index } - // clang-format on - { - } - - template - IShaderResourceVariable* TryResource() - { -#ifdef DILIGENT_DEBUG - { - VERIFY(Layout.GetResourceOffset() >= dbgPreviousResourceOffset, "Resource types are processed out of order!"); - dbgPreviousResourceOffset = Layout.GetResourceOffset(); - } -#endif - auto NumResources = Layout.GetNumResources(); - if (Index < NumResources) - return &Layout.GetResource(Index); - else - { - Index -= NumResources; - return nullptr; - } - } - -private: - ShaderResourceLayoutD3D11& Layout; - Uint32 Index = 0; -#ifdef DILIGENT_DEBUG - Uint32 dbgPreviousResourceOffset = 0; -#endif -}; - -IShaderResourceVariable* ShaderResourceLayoutD3D11::GetShaderVariable(Uint32 Index) -{ - ShaderVariableLocator VarLocator(*this, Index); - - if (auto* pCB = VarLocator.TryResource()) - return pCB; - - if (auto* pTexSRV = VarLocator.TryResource()) - return pTexSRV; - - if (auto* pTexUAV = VarLocator.TryResource()) - return pTexUAV; - - if (auto* pBuffSRV = VarLocator.TryResource()) - return pBuffSRV; - - if (auto* pBuffUAV = VarLocator.TryResource()) - return pBuffUAV; - - if (!m_pResources->IsUsingCombinedTextureSamplers()) - { - if (auto* pSampler = VarLocator.TryResource()) - return pSampler; - } - - auto TotalResCount = GetTotalResourceCount(); - LOG_ERROR(Index, " is not a valid variable index. Total resource count: ", TotalResCount); - return nullptr; -} - - -#ifdef DILIGENT_DEVELOPMENT -bool ShaderResourceLayoutD3D11::dvpVerifyBindings() const -{ - -# define LOG_MISSING_BINDING(VarType, Attrs, BindPt) \ - do \ - { \ - if (Attrs.BindCount == 1) \ - LOG_ERROR_MESSAGE("No resource is bound to ", VarType, " variable '", Attrs.Name, "' in shader '", GetShaderName(), "'"); \ - else \ - LOG_ERROR_MESSAGE("No resource is bound to ", VarType, " variable '", Attrs.Name, "[", BindPt - Attrs.BindPoint, "]' in shader '", GetShaderName(), "'"); \ - } while (false) - - m_ResourceCache.dbgVerifyCacheConsistency(); - - bool BindingsOK = true; - HandleConstResources( - [&](const ConstBuffBindInfo& cb) // - { - for (Uint32 BindPoint = cb.m_Attribs.BindPoint; BindPoint < Uint32{cb.m_Attribs.BindPoint} + cb.m_Attribs.BindCount; ++BindPoint) - { - if (!m_ResourceCache.IsCBBound(BindPoint)) - { - LOG_MISSING_BINDING("constant buffer", cb.m_Attribs, BindPoint); - BindingsOK = false; - } - } - }, - - [&](const TexSRVBindInfo& ts) // - { - for (Uint32 BindPoint = ts.m_Attribs.BindPoint; BindPoint < Uint32{ts.m_Attribs.BindPoint} + ts.m_Attribs.BindCount; ++BindPoint) - { - if (!m_ResourceCache.IsSRVBound(BindPoint, true)) - { - LOG_MISSING_BINDING("texture", ts.m_Attribs, BindPoint); - BindingsOK = false; - } - - if (ts.ValidSamplerAssigned()) - { - const auto& Sampler = GetConstResource(ts.SamplerIndex); - VERIFY_EXPR(Sampler.m_Attribs.BindCount == ts.m_Attribs.BindCount || Sampler.m_Attribs.BindCount == 1); - - // Verify that if single sampler is used for all texture array elements, all samplers set in the resource views are consistent - if (ts.m_Attribs.BindCount > 1 && Sampler.m_Attribs.BindCount == 1) - { - ShaderResourceCacheD3D11::CachedSampler* pCachedSamplers = nullptr; - ID3D11SamplerState** ppCachedD3D11Samplers = nullptr; - m_ResourceCache.GetSamplerArrays(pCachedSamplers, ppCachedD3D11Samplers); - VERIFY_EXPR(Sampler.m_Attribs.BindPoint < m_ResourceCache.GetSamplerCount()); - const auto& CachedSampler = pCachedSamplers[Sampler.m_Attribs.BindPoint]; - - ShaderResourceCacheD3D11::CachedResource* pCachedResources = nullptr; - ID3D11ShaderResourceView** ppCachedD3D11Resources = nullptr; - m_ResourceCache.GetSRVArrays(pCachedResources, ppCachedD3D11Resources); - VERIFY_EXPR(BindPoint < m_ResourceCache.GetSRVCount()); - auto& CachedResource = pCachedResources[BindPoint]; - if (CachedResource.pView) - { - auto* pTexView = CachedResource.pView.RawPtr(); - auto* pSampler = pTexView->GetSampler(); - if (pSampler != nullptr && pSampler != CachedSampler.pSampler.RawPtr()) - { - LOG_ERROR_MESSAGE("All elements of texture array '", ts.m_Attribs.Name, "' in shader '", GetShaderName(), "' share the same sampler. However, the sampler set in view for element ", BindPoint - ts.m_Attribs.BindPoint, " does not match bound sampler. This may cause incorrect behavior on GL platform."); - } - } - } - } - } - }, - - [&](const TexUAVBindInfo& uav) // - { - for (Uint32 BindPoint = uav.m_Attribs.BindPoint; BindPoint < Uint32{uav.m_Attribs.BindPoint} + uav.m_Attribs.BindCount; ++BindPoint) - { - if (!m_ResourceCache.IsUAVBound(BindPoint, true)) - { - LOG_MISSING_BINDING("texture UAV", uav.m_Attribs, BindPoint); - BindingsOK = false; - } - } - }, - - [&](const BuffSRVBindInfo& buf) // - { - for (Uint32 BindPoint = buf.m_Attribs.BindPoint; BindPoint < Uint32{buf.m_Attribs.BindPoint} + buf.m_Attribs.BindCount; ++BindPoint) - { - if (!m_ResourceCache.IsSRVBound(BindPoint, false)) - { - LOG_MISSING_BINDING("buffer", buf.m_Attribs, BindPoint); - BindingsOK = false; - } - } - }, - - [&](const BuffUAVBindInfo& uav) // - { - for (Uint32 BindPoint = uav.m_Attribs.BindPoint; BindPoint < Uint32{uav.m_Attribs.BindPoint} + uav.m_Attribs.BindCount; ++BindPoint) - { - if (!m_ResourceCache.IsUAVBound(BindPoint, false)) - { - LOG_MISSING_BINDING("buffer UAV", uav.m_Attribs, BindPoint); - BindingsOK = false; - } - } - }, - - [&](const SamplerBindInfo& sam) // - { - for (Uint32 BindPoint = sam.m_Attribs.BindPoint; BindPoint < Uint32{sam.m_Attribs.BindPoint} + sam.m_Attribs.BindCount; ++BindPoint) - { - if (!m_ResourceCache.IsSamplerBound(BindPoint)) - { - LOG_MISSING_BINDING("sampler", sam.m_Attribs, BindPoint); - BindingsOK = false; - } - } - } // clang-format off - ); // clang-format on -# undef LOG_MISSING_BINDING - - return BindingsOK; -} - -#endif -} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp index 1986eb6b..1b5f3b17 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourcesD3D11.cpp @@ -146,19 +146,23 @@ void ShaderResourcesD3D11::dvpVerifyCommittedResources(ID3D11Buffer* ID3D11Resource* CommittedD3D11UAVResources[], ShaderResourceCacheD3D11& ResourceCache) const { - ShaderResourceCacheD3D11::CachedCB* CachedCBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - ShaderResourceCacheD3D11::CachedResource* CachedSRVResources = nullptr; - ID3D11ShaderResourceView** d3d11SRVs = nullptr; - ShaderResourceCacheD3D11::CachedSampler* CachedSamplers = nullptr; - ID3D11SamplerState** d3d11Samplers = nullptr; - ShaderResourceCacheD3D11::CachedResource* CachedUAVResources = nullptr; - ID3D11UnorderedAccessView** d3d11UAVs = nullptr; + ShaderResourceCacheD3D11::CachedCB* CachedCBs = nullptr; + ID3D11Buffer** d3d11CBs = nullptr; + ShaderResourceCacheD3D11::CachedResource* CachedSRVResources = nullptr; + ID3D11ShaderResourceView** d3d11SRVs = nullptr; + ShaderResourceCacheD3D11::CachedSampler* CachedSamplers = nullptr; + ID3D11SamplerState** d3d11Samplers = nullptr; + ShaderResourceCacheD3D11::CachedResource* CachedUAVResources = nullptr; + ID3D11UnorderedAccessView** d3d11UAVs = nullptr; + ShaderResourceCacheD3D11::TBindPointsAndActiveBits* CBBindPoints = nullptr; + ShaderResourceCacheD3D11::TBindPointsAndActiveBits* SRVBindPoints = nullptr; + ShaderResourceCacheD3D11::TBindPointsAndActiveBits* SampBindPoints = nullptr; + ShaderResourceCacheD3D11::TBindPointsAndActiveBits* UAVBindPoints = nullptr; // clang-format off - ResourceCache.GetCBArrays (CachedCBs, d3d11CBs); - ResourceCache.GetSRVArrays (CachedSRVResources, d3d11SRVs); - ResourceCache.GetSamplerArrays(CachedSamplers, d3d11Samplers); - ResourceCache.GetUAVArrays (CachedUAVResources, d3d11UAVs); + ResourceCache.GetCBArrays (CachedCBs, d3d11CBs, CBBindPoints); + ResourceCache.GetSRVArrays (CachedSRVResources, d3d11SRVs, SRVBindPoints); + ResourceCache.GetSamplerArrays(CachedSamplers, d3d11Samplers, SampBindPoints); + ResourceCache.GetUAVArrays (CachedUAVResources, d3d11UAVs, UAVBindPoints); // clang-format on ProcessResources( diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderVariableManagerD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderVariableManagerD3D11.cpp new file mode 100644 index 00000000..79fdb94a --- /dev/null +++ b/Graphics/GraphicsEngineD3D11/src/ShaderVariableManagerD3D11.cpp @@ -0,0 +1,857 @@ +/* + * Copyright 2019-2021 Diligent Graphics LLC + * Copyright 2015-2019 Egor Yusov + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * In no event and under no legal theory, whether in tort (including negligence), + * contract, or otherwise, unless required by applicable law (such as deliberate + * and grossly negligent acts) or agreed to in writing, shall any Contributor be + * liable for any damages, including any direct, indirect, special, incidental, + * or consequential damages of any character arising as a result of this License or + * out of the use or inability to use the software (including but not limited to damages + * for loss of goodwill, work stoppage, computer failure or malfunction, or any and + * all other commercial damages or losses), even if such Contributor has been advised + * of the possibility of such damages. + */ + +#include "pch.h" + +#include + +#include "ShaderVariableManagerD3D11.hpp" +#include "ShaderResourceCacheD3D11.hpp" +#include "BufferD3D11Impl.hpp" +#include "BufferViewD3D11Impl.hpp" +#include "TextureBaseD3D11.hpp" +#include "TextureViewD3D11.h" +#include "SamplerD3D11Impl.hpp" +#include "ShaderD3D11Impl.hpp" +#include "ShaderResourceVariableBase.hpp" +#include "PipelineResourceSignatureD3D11Impl.hpp" + +namespace Diligent +{ + +ShaderVariableManagerD3D11::~ShaderVariableManagerD3D11() +{ + VERIFY(m_ResourceBuffer == nullptr, "DestroyVariables() has not been called"); +} + +void ShaderVariableManagerD3D11::Destroy(IMemoryAllocator& Allocator) +{ + if (m_ResourceBuffer == nullptr) + return; + + VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + + HandleResources( + [&](ConstBuffBindInfo& cb) { + cb.~ConstBuffBindInfo(); + }, + [&](TexSRVBindInfo& ts) { + ts.~TexSRVBindInfo(); + }, + [&](TexUAVBindInfo& uav) { + uav.~TexUAVBindInfo(); + }, + [&](BuffSRVBindInfo& srv) { + srv.~BuffSRVBindInfo(); + }, + [&](BuffUAVBindInfo& uav) { + uav.~BuffUAVBindInfo(); + }, + [&](SamplerBindInfo& sam) { + sam.~SamplerBindInfo(); + }); + + Allocator.Free(m_ResourceBuffer); + + m_ResourceBuffer = nullptr; +} + +const PipelineResourceDesc& ShaderVariableManagerD3D11::GetResourceDesc(Uint32 Index) const +{ + VERIFY_EXPR(m_pSignature); + return m_pSignature->GetResourceDesc(Index); +} + +const PipelineResourceAttribsD3D11& ShaderVariableManagerD3D11::GetAttribs(Uint32 Index) const +{ + VERIFY_EXPR(m_pSignature); + return m_pSignature->GetResourceAttribs(Index); +} + +void ShaderVariableManagerD3D11::CountResources(const PipelineResourceSignatureD3D11Impl& Signature, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + const SHADER_TYPE ShaderType, + D3DShaderResourceCounters& Counters) +{ + ProcessSignatureResources( + Signature, AllowedVarTypes, NumAllowedTypes, ShaderType, + [&](Uint32 Index) // + { + const auto& ResDesc = Signature.GetResourceDesc(Index); + static_assert(SHADER_RESOURCE_TYPE_LAST == 8, "Please update the switch below to handle the new shader resource range"); + switch (ResDesc.ResourceType) + { + // clang-format off + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: ++Counters.NumCBs; break; + case SHADER_RESOURCE_TYPE_TEXTURE_SRV: ++Counters.NumTexSRVs; break; + case SHADER_RESOURCE_TYPE_BUFFER_SRV: ++Counters.NumBufSRVs; break; + case SHADER_RESOURCE_TYPE_TEXTURE_UAV: ++Counters.NumTexUAVs; break; + case SHADER_RESOURCE_TYPE_BUFFER_UAV: ++Counters.NumBufUAVs; break; + case SHADER_RESOURCE_TYPE_SAMPLER: ++Counters.NumSamplers; break; + case SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT: ++Counters.NumTexSRVs; break; + // clang-format on + default: + UNEXPECTED("Unsupported resource type."); + } + }); +} + +template +void ShaderVariableManagerD3D11::ProcessSignatureResources(const PipelineResourceSignatureD3D11Impl& Signature, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + SHADER_TYPE ShaderType, + HandlerType Handler) +{ + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + const bool UsingSeparateSamplers = Signature.IsUsingSeparateSamplers(); + + for (Uint32 var_type = 0; var_type < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; ++var_type) + { + const auto VarType = static_cast(var_type); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + const auto ResIdxRange = Signature.GetResourceIndexRange(VarType); + for (Uint32 r = ResIdxRange.first; r < ResIdxRange.second; ++r) + { + const auto& Res = Signature.GetResourceDesc(r); + const auto& Attr = Signature.GetResourceAttribs(r); + VERIFY_EXPR(Res.VarType == VarType); + + if ((Res.ShaderStages & ShaderType) == 0) + continue; + + // When using HLSL-style combined image samplers, we need to skip separate samplers. + // Also always skip immutable separate samplers. + if (Res.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER && + (!UsingSeparateSamplers || Attr.IsImmutableSamplerAssigned())) + continue; + + Handler(r); + } + } + } +} + +size_t ShaderVariableManagerD3D11::GetRequiredMemorySize(const PipelineResourceSignatureD3D11Impl& Signature, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + SHADER_TYPE ShaderType) +{ + D3DShaderResourceCounters ResCounters; + CountResources(Signature, AllowedVarTypes, NumAllowedTypes, ShaderType, ResCounters); + + // clang-format off + auto MemSize = ResCounters.NumCBs * sizeof(ConstBuffBindInfo) + + ResCounters.NumTexSRVs * sizeof(TexSRVBindInfo) + + ResCounters.NumTexUAVs * sizeof(TexUAVBindInfo) + + ResCounters.NumBufSRVs * sizeof(BuffSRVBindInfo) + + ResCounters.NumBufUAVs * sizeof(BuffUAVBindInfo) + + ResCounters.NumSamplers * sizeof(SamplerBindInfo); + // clang-format on + return MemSize; +} + + +void ShaderVariableManagerD3D11::Initialize(const PipelineResourceSignatureD3D11Impl& Signature, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + SHADER_TYPE ShaderType) +{ +#ifdef DILIGENT_DEBUG + m_pDbgAllocator = &Allocator; +#endif + + D3DShaderResourceCounters ResCounters; + CountResources(Signature, AllowedVarTypes, NumAllowedTypes, ShaderType, ResCounters); + + m_pSignature = &Signature; + + // Initialize offsets + size_t CurrentOffset = 0; + + auto AdvanceOffset = [&CurrentOffset](size_t NumBytes) // + { + constexpr size_t MaxOffset = std::numeric_limits::max(); + VERIFY(CurrentOffset <= MaxOffset, "Current offser (", CurrentOffset, ") exceeds max allowed value (", MaxOffset, ")"); + auto Offset = static_cast(CurrentOffset); + CurrentOffset += NumBytes; + return Offset; + }; + + // clang-format off + auto CBOffset = AdvanceOffset(ResCounters.NumCBs * sizeof(ConstBuffBindInfo)); (void)CBOffset; // To suppress warning + m_TexSRVsOffset = AdvanceOffset(ResCounters.NumTexSRVs * sizeof(TexSRVBindInfo) ); + m_TexUAVsOffset = AdvanceOffset(ResCounters.NumTexUAVs * sizeof(TexUAVBindInfo) ); + m_BuffSRVsOffset = AdvanceOffset(ResCounters.NumBufSRVs * sizeof(BuffSRVBindInfo) ); + m_BuffUAVsOffset = AdvanceOffset(ResCounters.NumBufUAVs * sizeof(BuffUAVBindInfo) ); + m_SamplerOffset = AdvanceOffset(ResCounters.NumSamplers * sizeof(SamplerBindInfo) ); + m_MemorySize = AdvanceOffset(0); + // clang-format on + + VERIFY_EXPR(m_MemorySize == GetRequiredMemorySize(Signature, AllowedVarTypes, NumAllowedTypes, ShaderType)); + + if (m_MemorySize) + { + m_ResourceBuffer = ALLOCATE_RAW(Allocator, "Raw memory buffer for shader resource layout resources", m_MemorySize); + } + + // clang-format off + VERIFY_EXPR(ResCounters.NumCBs == GetNumCBs() ); + VERIFY_EXPR(ResCounters.NumTexSRVs == GetNumTexSRVs() ); + VERIFY_EXPR(ResCounters.NumTexUAVs == GetNumTexUAVs() ); + VERIFY_EXPR(ResCounters.NumBufSRVs == GetNumBufSRVs() ); + VERIFY_EXPR(ResCounters.NumBufUAVs == GetNumBufUAVs() ); + VERIFY_EXPR(ResCounters.NumSamplers== GetNumSamplers()); + // clang-format on + + // Current resource index for every resource type + Uint32 cb = 0; + Uint32 texSrv = 0; + Uint32 texUav = 0; + Uint32 bufSrv = 0; + Uint32 bufUav = 0; + Uint32 sam = 0; + + Uint32 NumCBSlots = 0; + Uint32 NumSRVSlots = 0; + Uint32 NumSamplerSlots = 0; + Uint32 NumUAVSlots = 0; + ProcessSignatureResources( + Signature, AllowedVarTypes, NumAllowedTypes, ShaderType, + [&](Uint32 Index) // + { + const auto& ResDesc = Signature.GetResourceDesc(Index); + const auto& ResAttr = Signature.GetResourceAttribs(Index); + static_assert(SHADER_RESOURCE_TYPE_LAST == 8, "Please update the switch below to handle the new shader resource range"); + switch (ResDesc.ResourceType) + { + case SHADER_RESOURCE_TYPE_CONSTANT_BUFFER: + // Initialize current CB in place, increment CB counter + new (&GetResource(cb++)) ConstBuffBindInfo(*this, Index); + NumCBSlots = std::max(NumCBSlots, ResAttr.CacheOffset + ResDesc.ArraySize); + break; + + case SHADER_RESOURCE_TYPE_TEXTURE_SRV: + case SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT: + // Initialize tex SRV in place, increment counter of tex SRVs + new (&GetResource(texSrv++)) TexSRVBindInfo{*this, Index}; + NumSRVSlots = std::max(NumSRVSlots, ResAttr.CacheOffset + ResDesc.ArraySize); + break; + + case SHADER_RESOURCE_TYPE_BUFFER_SRV: + // Initialize buff SRV in place, increment counter of buff SRVs + new (&GetResource(bufSrv++)) BuffSRVBindInfo(*this, Index); + NumSRVSlots = std::max(NumSRVSlots, ResAttr.CacheOffset + ResDesc.ArraySize); + break; + + case SHADER_RESOURCE_TYPE_TEXTURE_UAV: + // Initialize tex UAV in place, increment counter of tex UAVs + new (&GetResource(texUav++)) TexUAVBindInfo(*this, Index); + NumUAVSlots = std::max(NumUAVSlots, ResAttr.CacheOffset + ResDesc.ArraySize); + break; + + case SHADER_RESOURCE_TYPE_BUFFER_UAV: + // Initialize buff UAV in place, increment counter of buff UAVs + new (&GetResource(bufUav++)) BuffUAVBindInfo(*this, Index); + NumUAVSlots = std::max(NumUAVSlots, ResAttr.CacheOffset + ResDesc.ArraySize); + break; + + case SHADER_RESOURCE_TYPE_SAMPLER: + // Initialize current sampler in place, increment sampler counter + new (&GetResource(sam++)) SamplerBindInfo(*this, Index); + NumSamplerSlots = std::max(NumSamplerSlots, ResAttr.CacheOffset + ResDesc.ArraySize); + break; + + default: + UNEXPECTED("Unsupported resource type."); + } + }); + + // clang-format off + VERIFY(cb == GetNumCBs(), "Not all CBs are initialized which will cause a crash when dtor is called"); + VERIFY(texSrv == GetNumTexSRVs(), "Not all Tex SRVs are initialized which will cause a crash when dtor is called"); + VERIFY(texUav == GetNumTexUAVs(), "Not all Tex UAVs are initialized which will cause a crash when dtor is called"); + VERIFY(bufSrv == GetNumBufSRVs(), "Not all Buf SRVs are initialized which will cause a crash when dtor is called"); + VERIFY(bufUav == GetNumBufUAVs(), "Not all Buf UAVs are initialized which will cause a crash when dtor is called"); + VERIFY(sam == GetNumSamplers(), "Not all samplers are initialized which will cause a crash when dtor is called"); + // clang-format on +} + +void ShaderVariableManagerD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* pBuffer, Uint32 ArrayIndex) +{ + const auto& Desc = GetDesc(); + const auto& Attr = GetAttribs(); + DEV_CHECK_ERR(ArrayIndex < Desc.ArraySize, "Array index (", ArrayIndex, ") is out of range for variable '", Desc.Name, "'. Max allowed index: ", Desc.ArraySize - 1); + auto& ResourceCache = m_ParentManager.m_ResourceCache; + + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_CONSTANT_BUFFER); + + // We cannot use ValidatedCast<> here as the resource retrieved from the + // resource mapping can be of wrong type + RefCntAutoPtr pBuffD3D11Impl{pBuffer, IID_BufferD3D11}; +#ifdef DILIGENT_DEVELOPMENT + { + const auto& CachedCB = ResourceCache.GetCB(Attr.CacheOffset + ArrayIndex); + VerifyConstantBufferBinding(Desc.Name, Desc.ArraySize, Desc.VarType, Desc.Flags, ArrayIndex, pBuffer, pBuffD3D11Impl.RawPtr(), CachedCB.pBuff.RawPtr()); + } +#endif + ResourceCache.SetCB(Attr.CacheOffset, ArrayIndex, Attr.BindPoints, std::move(pBuffD3D11Impl)); +} + + +void ShaderVariableManagerD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pView, Uint32 ArrayIndex) +{ + const auto& Desc = GetDesc(); + const auto& Attr = GetAttribs(); + DEV_CHECK_ERR(ArrayIndex < Desc.ArraySize, "Array index (", ArrayIndex, ") is out of range for variable '", Desc.Name, "'. Max allowed index: ", Desc.ArraySize - 1); + auto& ResourceCache = m_ParentManager.m_ResourceCache; + + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV || + Desc.ResourceType == SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT); + + // We cannot use ValidatedCast<> here as the resource retrieved from the + // resource mapping can be of wrong type + RefCntAutoPtr pViewD3D11{pView, IID_TextureViewD3D11}; +#ifdef DILIGENT_DEVELOPMENT + { + auto& CachedSRV = ResourceCache.GetSRV(Attr.CacheOffset + ArrayIndex); + VerifyResourceViewBinding(Desc.Name, Desc.ArraySize, Desc.VarType, ArrayIndex, + pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, + RESOURCE_DIM_UNDEFINED, false, CachedSRV.pView.RawPtr()); + } +#endif + + if (Attr.IsSamplerAssigned() && !Attr.IsImmutableSamplerAssigned()) + { + const auto& SampAttr = m_ParentManager.GetAttribs(Attr.SamplerInd); + const auto& SampDesc = m_ParentManager.GetResourceDesc(Attr.SamplerInd); + VERIFY_EXPR(SampDesc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER); + VERIFY_EXPR((Desc.ShaderStages & SampDesc.ShaderStages) == Desc.ShaderStages); + VERIFY_EXPR(SampDesc.ArraySize == Desc.ArraySize || SampDesc.ArraySize == 1); + const auto SampArrayIndex = (SampDesc.ArraySize != 1 ? ArrayIndex : 0); + + SamplerD3D11Impl* pSamplerD3D11Impl = nullptr; + if (pViewD3D11) + { + pSamplerD3D11Impl = ValidatedCast(pViewD3D11->GetSampler()); +#ifdef DILIGENT_DEVELOPMENT + if (pSamplerD3D11Impl == nullptr) + { + if (SampDesc.ArraySize > 1) + LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", SampDesc.Name, "[", ArrayIndex, "]'. Sampler is not set in the texture view '", pViewD3D11->GetDesc().Name, "'"); + else + LOG_ERROR_MESSAGE("Failed to bind sampler to variable '", SampDesc.Name, "'. Sampler is not set in the texture view '", pViewD3D11->GetDesc().Name, "'"); + } +#endif + } +#ifdef DILIGENT_DEVELOPMENT + if (SampDesc.VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) + { + auto& CachedSampler = ResourceCache.GetSampler(SampAttr.CacheOffset + SampArrayIndex); + if (CachedSampler.pSampler != nullptr && CachedSampler.pSampler != pSamplerD3D11Impl) + { + auto VarTypeStr = GetShaderVariableTypeLiteralName(GetType()); + LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetShaderResourcePrintName(SampDesc, ArrayIndex), + "'. Attempting to bind another sampler or null is an error and may cause unpredicted behavior. Use another shader resource binding instance or label the variable as dynamic."); + } + } +#endif + ResourceCache.SetSampler(SampAttr.CacheOffset, SampArrayIndex, SampAttr.BindPoints, pSamplerD3D11Impl); + } + ResourceCache.SetTexSRV(Attr.CacheOffset, ArrayIndex, Attr.BindPoints, std::move(pViewD3D11)); +} + +void ShaderVariableManagerD3D11::SamplerBindInfo::BindResource(IDeviceObject* pSampler, Uint32 ArrayIndex) +{ + const auto& Desc = GetDesc(); + const auto& Attr = GetAttribs(); + DEV_CHECK_ERR(ArrayIndex < Desc.ArraySize, "Array index (", ArrayIndex, ") is out of range for variable '", Desc.Name, "'. Max allowed index: ", Desc.ArraySize - 1); + auto& ResourceCache = m_ParentManager.m_ResourceCache; + + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_SAMPLER); + + // We cannot use ValidatedCast<> here as the resource retrieved from the + // resource mapping can be of wrong type + RefCntAutoPtr pSamplerD3D11{pSampler, IID_SamplerD3D11}; + +#ifdef DILIGENT_DEVELOPMENT + if (pSampler && !pSamplerD3D11) + { + LOG_ERROR_MESSAGE("Failed to bind object '", Desc.Name, "' to variable '", GetShaderResourcePrintName(Desc, ArrayIndex), + "''. Incorect object type: sampler is expected."); + } + + if (Attr.IsSamplerAssigned()) + { + auto* TexSRVName = m_ParentManager.GetResourceDesc(Attr.SamplerInd).Name; // AZ TODO: check + LOG_WARNING_MESSAGE("Texture sampler sampler '", Desc.Name, "' is assigned to texture SRV '", + TexSRVName, "' and should not be accessed directly. The sampler is initialized when texture SRV is set to '", + TexSRVName, "' variable."); + } + + if (GetType() != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) + { + auto& CachedSampler = ResourceCache.GetSampler(Attr.CacheOffset + ArrayIndex); + if (CachedSampler.pSampler != nullptr && CachedSampler.pSampler != pSamplerD3D11) + { + auto VarTypeStr = GetShaderVariableTypeLiteralName(GetType()); + LOG_ERROR_MESSAGE("Non-null sampler is already bound to ", VarTypeStr, " shader variable '", GetShaderResourcePrintName(Desc, ArrayIndex), + "'. Attempting to bind another sampler or null is an error and may cause unpredicted behavior. " + "Use another shader resource binding instance or label the variable as dynamic."); + } + } +#endif + + ResourceCache.SetSampler(Attr.CacheOffset, ArrayIndex, Attr.BindPoints, std::move(pSamplerD3D11)); +} + +void ShaderVariableManagerD3D11::BuffSRVBindInfo::BindResource(IDeviceObject* pView, Uint32 ArrayIndex) +{ + const auto& Desc = GetDesc(); + const auto& Attr = GetAttribs(); + DEV_CHECK_ERR(ArrayIndex < Desc.ArraySize, "Array index (", ArrayIndex, ") is out of range for variable '", Desc.Name, "'. Max allowed index: ", Desc.ArraySize - 1); + auto& ResourceCache = m_ParentManager.m_ResourceCache; + + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV); + + // We cannot use ValidatedCast<> here as the resource retrieved from the + // resource mapping can be of wrong type + RefCntAutoPtr pViewD3D11{pView, IID_BufferViewD3D11}; +#ifdef DILIGENT_DEVELOPMENT + { + auto& CachedSRV = ResourceCache.GetSRV(Attr.CacheOffset + ArrayIndex); + VerifyResourceViewBinding(Desc.Name, Desc.ArraySize, Desc.VarType, ArrayIndex, + pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE}, + RESOURCE_DIM_BUFFER, false, CachedSRV.pView.RawPtr()); + } +#endif + ResourceCache.SetBufSRV(Attr.CacheOffset, ArrayIndex, Attr.BindPoints, std::move(pViewD3D11)); +} + + +void ShaderVariableManagerD3D11::TexUAVBindInfo::BindResource(IDeviceObject* pView, Uint32 ArrayIndex) +{ + const auto& Desc = GetDesc(); + const auto& Attr = GetAttribs(); + DEV_CHECK_ERR(ArrayIndex < Desc.ArraySize, "Array index (", ArrayIndex, ") is out of range for variable '", Desc.Name, "'. Max allowed index: ", Desc.ArraySize - 1); + auto& ResourceCache = m_ParentManager.m_ResourceCache; + + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_UAV); + + // We cannot use ValidatedCast<> here as the resource retrieved from the + // resource mapping can be of wrong type + RefCntAutoPtr pViewD3D11{pView, IID_TextureViewD3D11}; +#ifdef DILIGENT_DEVELOPMENT + { + auto& CachedUAV = ResourceCache.GetUAV(Attr.CacheOffset + ArrayIndex); + VerifyResourceViewBinding(Desc.Name, Desc.ArraySize, Desc.VarType, ArrayIndex, + pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_UNORDERED_ACCESS}, + RESOURCE_DIM_UNDEFINED, false, CachedUAV.pView.RawPtr()); + } +#endif + ResourceCache.SetTexUAV(Attr.CacheOffset, ArrayIndex, Attr.BindPoints, std::move(pViewD3D11)); +} + + +void ShaderVariableManagerD3D11::BuffUAVBindInfo::BindResource(IDeviceObject* pView, Uint32 ArrayIndex) +{ + const auto& Desc = GetDesc(); + const auto& Attr = GetAttribs(); + DEV_CHECK_ERR(ArrayIndex < Desc.ArraySize, "Array index (", ArrayIndex, ") is out of range for variable '", Desc.Name, "'. Max allowed index: ", Desc.ArraySize - 1); + auto& ResourceCache = m_ParentManager.m_ResourceCache; + + VERIFY_EXPR(Desc.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_UAV); + + // We cannot use ValidatedCast<> here as the resource retrieved from the + // resource mapping can be of wrong type + RefCntAutoPtr pViewD3D11{pView, IID_BufferViewD3D11}; +#ifdef DILIGENT_DEVELOPMENT + { + auto& CachedUAV = ResourceCache.GetUAV(Attr.CacheOffset + ArrayIndex); + VerifyResourceViewBinding(Desc.Name, Desc.ArraySize, Desc.VarType, ArrayIndex, + pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_UNORDERED_ACCESS}, + RESOURCE_DIM_BUFFER, false, CachedUAV.pView.RawPtr()); + } +#endif + ResourceCache.SetBufUAV(Attr.CacheOffset, ArrayIndex, Attr.BindPoints, std::move(pViewD3D11)); +} + +void ShaderVariableManagerD3D11::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) +{ + if (pResourceMapping == nullptr) + { + LOG_ERROR_MESSAGE("Failed to bind resources: resource mapping is null"); + return; + } + + if ((Flags & BIND_SHADER_RESOURCES_UPDATE_ALL) == 0) + Flags |= BIND_SHADER_RESOURCES_UPDATE_ALL; + + HandleResources( + [&](ConstBuffBindInfo& cb) { + cb.BindResources(pResourceMapping, Flags); + }, + [&](TexSRVBindInfo& ts) { + ts.BindResources(pResourceMapping, Flags); + }, + [&](TexUAVBindInfo& uav) { + uav.BindResources(pResourceMapping, Flags); + }, + [&](BuffSRVBindInfo& srv) { + srv.BindResources(pResourceMapping, Flags); + }, + [&](BuffUAVBindInfo& uav) { + uav.BindResources(pResourceMapping, Flags); + }, + [&](SamplerBindInfo& sam) { + sam.BindResources(pResourceMapping, Flags); + }); +} + +template +IShaderResourceVariable* ShaderVariableManagerD3D11::GetResourceByName(const Char* Name) const +{ + auto NumResources = GetNumResources(); + for (Uint32 res = 0; res < NumResources; ++res) + { + auto& Resource = GetResource(res); + if (strcmp(Resource.GetDesc().Name, Name) == 0) + return &Resource; + } + + return nullptr; +} + +IShaderResourceVariable* ShaderVariableManagerD3D11::GetVariable(const Char* Name) const +{ + if (auto* pCB = GetResourceByName(Name)) + return pCB; + + if (auto* pTexSRV = GetResourceByName(Name)) + return pTexSRV; + + if (auto* pTexUAV = GetResourceByName(Name)) + return pTexUAV; + + if (auto* pBuffSRV = GetResourceByName(Name)) + return pBuffSRV; + + if (auto* pBuffUAV = GetResourceByName(Name)) + return pBuffUAV; + + if (!m_pSignature->IsUsingCombinedSamplers()) + { + // Immutable samplers are never created in the resource layout + if (auto* pSampler = GetResourceByName(Name)) + return pSampler; + } + + return nullptr; +} + +class ShaderVariableIndexLocator +{ +public: + ShaderVariableIndexLocator(const ShaderVariableManagerD3D11& _Layout, const ShaderVariableManagerD3D11::ShaderVariableD3D11Base& Variable) : + // clang-format off + Layout {_Layout}, + VarOffset(reinterpret_cast(&Variable) - reinterpret_cast(_Layout.m_ResourceBuffer)) + // clang-format on + {} + + template + bool TryResource(ShaderVariableManagerD3D11::OffsetType NextResourceTypeOffset) + { +#ifdef DILIGENT_DEBUG + { + VERIFY(Layout.GetResourceOffset() >= dbgPreviousResourceOffset, "Resource types are processed out of order!"); + dbgPreviousResourceOffset = Layout.GetResourceOffset(); + VERIFY_EXPR(NextResourceTypeOffset >= Layout.GetResourceOffset()); + } +#endif + if (VarOffset < NextResourceTypeOffset) + { + auto RelativeOffset = VarOffset - Layout.GetResourceOffset(); + DEV_CHECK_ERR(RelativeOffset % sizeof(ResourceType) == 0, "Offset is not multiple of resource type (", sizeof(ResourceType), ")"); + Index += static_cast(RelativeOffset / sizeof(ResourceType)); + return true; + } + else + { + Index += Layout.GetNumResources(); + return false; + } + } + + Uint32 GetIndex() const { return Index; } + +private: + const ShaderVariableManagerD3D11& Layout; + const size_t VarOffset; + Uint32 Index = 0; +#ifdef DILIGENT_DEBUG + Uint32 dbgPreviousResourceOffset = 0; +#endif +}; + +Uint32 ShaderVariableManagerD3D11::GetVariableIndex(const ShaderVariableD3D11Base& Variable) const +{ + if (m_ResourceBuffer == nullptr) + { + LOG_ERROR("This shader resource layout does not have resources"); + return static_cast(-1); + } + + ShaderVariableIndexLocator IdxLocator(*this, Variable); + if (IdxLocator.TryResource(m_TexSRVsOffset)) + return IdxLocator.GetIndex(); + + if (IdxLocator.TryResource(m_TexUAVsOffset)) + return IdxLocator.GetIndex(); + + if (IdxLocator.TryResource(m_BuffSRVsOffset)) + return IdxLocator.GetIndex(); + + if (IdxLocator.TryResource(m_BuffUAVsOffset)) + return IdxLocator.GetIndex(); + + if (IdxLocator.TryResource(m_SamplerOffset)) + return IdxLocator.GetIndex(); + + if (!m_pSignature->IsUsingCombinedSamplers()) + { + if (IdxLocator.TryResource(m_MemorySize)) + return IdxLocator.GetIndex(); + } + + LOG_ERROR("Failed to get variable index. The variable ", &Variable, " does not belong to this shader resource layout"); + return static_cast(-1); +} + +class ShaderVariableLocator +{ +public: + ShaderVariableLocator(const ShaderVariableManagerD3D11& _Layout, Uint32 _Index) : + // clang-format off + Layout{_Layout}, + Index {_Index } + // clang-format on + { + } + + template + IShaderResourceVariable* TryResource() + { +#ifdef DILIGENT_DEBUG + { + VERIFY(Layout.GetResourceOffset() >= dbgPreviousResourceOffset, "Resource types are processed out of order!"); + dbgPreviousResourceOffset = Layout.GetResourceOffset(); + } +#endif + auto NumResources = Layout.GetNumResources(); + if (Index < NumResources) + return &Layout.GetResource(Index); + else + { + Index -= NumResources; + return nullptr; + } + } + +private: + ShaderVariableManagerD3D11 const& Layout; + Uint32 Index = 0; +#ifdef DILIGENT_DEBUG + Uint32 dbgPreviousResourceOffset = 0; +#endif +}; + +IShaderResourceVariable* ShaderVariableManagerD3D11::GetVariable(Uint32 Index) const +{ + ShaderVariableLocator VarLocator(*this, Index); + + if (auto* pCB = VarLocator.TryResource()) + return pCB; + + if (auto* pTexSRV = VarLocator.TryResource()) + return pTexSRV; + + if (auto* pTexUAV = VarLocator.TryResource()) + return pTexUAV; + + if (auto* pBuffSRV = VarLocator.TryResource()) + return pBuffSRV; + + if (auto* pBuffUAV = VarLocator.TryResource()) + return pBuffUAV; + + if (!m_pSignature->IsUsingCombinedSamplers()) + { + if (auto* pSampler = VarLocator.TryResource()) + return pSampler; + } + + LOG_ERROR(Index, " is not a valid variable index."); + return nullptr; +} + +Uint32 ShaderVariableManagerD3D11::GetVariableCount() const +{ + return GetNumCBs() + GetNumTexSRVs() + GetNumTexUAVs() + GetNumBufSRVs() + GetNumBufUAVs() + GetNumSamplers(); +} + +// AZ TODO +#if 0 //def DILIGENT_DEVELOPMENT +bool ShaderVariableManagerD3D11::dvpVerifyBindings() const +{ + +# define LOG_MISSING_BINDING(VarType, Attrs, BindPt) \ + do \ + { \ + if (Attrs.BindCount == 1) \ + LOG_ERROR_MESSAGE("No resource is bound to ", VarType, " variable '", Attrs.Name, "' in shader '", GetShaderName(), "'"); \ + else \ + LOG_ERROR_MESSAGE("No resource is bound to ", VarType, " variable '", Attrs.Name, "[", BindPt - Attrs.BindPoint, "]' in shader '", GetShaderName(), "'"); \ + } while (false) + + m_ResourceCache.DvpVerifyCacheConsistency(); + + bool BindingsOK = true; + HandleConstResources( + [&](const ConstBuffBindInfo& cb) // + { + for (Uint32 BindPoint = cb.m_Attribs.BindPoint; BindPoint < Uint32{cb.m_Attribs.BindPoint} + cb.m_Attribs.BindCount; ++BindPoint) + { + if (!m_ResourceCache.IsCBBound(BindPoint)) + { + LOG_MISSING_BINDING("constant buffer", cb.m_Attribs, BindPoint); + BindingsOK = false; + } + } + }, + + [&](const TexSRVBindInfo& ts) // + { + for (Uint32 BindPoint = ts.m_Attribs.BindPoint; BindPoint < Uint32{ts.m_Attribs.BindPoint} + ts.m_Attribs.BindCount; ++BindPoint) + { + if (!m_ResourceCache.IsSRVBound(BindPoint, true)) + { + LOG_MISSING_BINDING("texture", ts.m_Attribs, BindPoint); + BindingsOK = false; + } + + if (ts.ValidSamplerAssigned()) + { + const auto& Sampler = GetConstResource(ts.SamplerIndex); + VERIFY_EXPR(Sampler.m_Attribs.BindCount == ts.m_Attribs.BindCount || Sampler.m_Attribs.BindCount == 1); + + // Verify that if single sampler is used for all texture array elements, all samplers set in the resource views are consistent + if (ts.m_Attribs.BindCount > 1 && Sampler.m_Attribs.BindCount == 1) + { + ShaderResourceCacheD3D11::CachedSampler* pCachedSamplers = nullptr; + ID3D11SamplerState** ppCachedD3D11Samplers = nullptr; + m_ResourceCache.GetSamplerArrays(pCachedSamplers, ppCachedD3D11Samplers); + VERIFY_EXPR(Sampler.m_Attribs.BindPoint < m_ResourceCache.GetSamplerCount()); + const auto& CachedSampler = pCachedSamplers[Sampler.m_Attribs.BindPoint]; + + ShaderResourceCacheD3D11::CachedResource* pCachedResources = nullptr; + ID3D11ShaderResourceView** ppCachedD3D11Resources = nullptr; + m_ResourceCache.GetSRVArrays(pCachedResources, ppCachedD3D11Resources); + VERIFY_EXPR(BindPoint < m_ResourceCache.GetSRVCount()); + auto& CachedResource = pCachedResources[BindPoint]; + if (CachedResource.pView) + { + auto* pTexView = CachedResource.pView.RawPtr(); + auto* pSampler = pTexView->GetSampler(); + if (pSampler != nullptr && pSampler != CachedSampler.pSampler.RawPtr()) + { + LOG_ERROR_MESSAGE("All elements of texture array '", ts.m_Attribs.Name, "' in shader '", GetShaderName(), "' share the same sampler. However, the sampler set in view for element ", BindPoint - ts.m_Attribs.BindPoint, " does not match bound sampler. This may cause incorrect behavior on GL platform."); + } + } + } + } + } + }, + + [&](const TexUAVBindInfo& uav) // + { + for (Uint32 BindPoint = uav.m_Attribs.BindPoint; BindPoint < Uint32{uav.m_Attribs.BindPoint} + uav.m_Attribs.BindCount; ++BindPoint) + { + if (!m_ResourceCache.IsUAVBound(BindPoint, true)) + { + LOG_MISSING_BINDING("texture UAV", uav.m_Attribs, BindPoint); + BindingsOK = false; + } + } + }, + + [&](const BuffSRVBindInfo& buf) // + { + for (Uint32 BindPoint = buf.m_Attribs.BindPoint; BindPoint < Uint32{buf.m_Attribs.BindPoint} + buf.m_Attribs.BindCount; ++BindPoint) + { + if (!m_ResourceCache.IsSRVBound(BindPoint, false)) + { + LOG_MISSING_BINDING("buffer", buf.m_Attribs, BindPoint); + BindingsOK = false; + } + } + }, + + [&](const BuffUAVBindInfo& uav) // + { + for (Uint32 BindPoint = uav.m_Attribs.BindPoint; BindPoint < Uint32{uav.m_Attribs.BindPoint} + uav.m_Attribs.BindCount; ++BindPoint) + { + if (!m_ResourceCache.IsUAVBound(BindPoint, false)) + { + LOG_MISSING_BINDING("buffer UAV", uav.m_Attribs, BindPoint); + BindingsOK = false; + } + } + }, + + [&](const SamplerBindInfo& sam) // + { + for (Uint32 BindPoint = sam.m_Attribs.BindPoint; BindPoint < Uint32{sam.m_Attribs.BindPoint} + sam.m_Attribs.BindCount; ++BindPoint) + { + if (!m_ResourceCache.IsSamplerBound(BindPoint)) + { + LOG_MISSING_BINDING("sampler", sam.m_Attribs, BindPoint); + BindingsOK = false; + } + } + } // clang-format off + ); // clang-format on +# undef LOG_MISSING_BINDING + + return BindingsOK; +} + +#endif +} // namespace Diligent -- cgit v1.2.3