From cc11a1af8e1a0f8582914aa888b53e53883fdfaf Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 5 Oct 2020 10:03:34 -0700 Subject: Fixed typo --- Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 6a81faba..81d6753c 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -238,7 +238,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height }; - const auto& DeiceExtFeatures = PhysicalDevice->GetExtFeatures(); + const auto& DeviceExtFeatures = PhysicalDevice->GetExtFeatures(); #define ENABLE_FEATURE(IsFeatureSupported, Feature, FeatureName) \ do \ @@ -248,23 +248,23 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E } while (false) - auto MeshShaderFeats = DeiceExtFeatures.MeshShader; + auto MeshShaderFeats = DeviceExtFeatures.MeshShader; ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are"); - auto ShaderFloat16Int8 = DeiceExtFeatures.ShaderFloat16Int8; + auto ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8; // clang-format off ENABLE_FEATURE(ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are"); ENABLE_FEATURE(ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are"); // clang-format on - auto Storage16BitFeats = DeiceExtFeatures.Storage16Bit; + auto Storage16BitFeats = DeviceExtFeatures.Storage16Bit; // clang-format off ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is"); ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is"); ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are"); // clang-format on - auto Storage8BitFeats = DeiceExtFeatures.Storage8Bit; + auto Storage8BitFeats = DeviceExtFeatures.Storage8Bit; // clang-format off ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is"); ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is"); -- cgit v1.2.3 From c75307ce6d2d3d18b9ad7ba0bbcf2e2e59ba5a2c Mon Sep 17 00:00:00 2001 From: assiduous Date: Wed, 7 Oct 2020 14:12:45 -0700 Subject: Few minor updates --- Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp | 3 ++- Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp | 3 ++- Graphics/GraphicsEngine/interface/Shader.h | 4 +++- Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp | 3 +-- 4 files changed, 8 insertions(+), 5 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index 780562df..af77319a 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -1454,7 +1454,8 @@ Uint32 GetStagingTextureLocationOffset(const TextureDesc& TexDesc, // For non-compressed formats, BlockWidth is 1. Offset += (LocationX / FmtAttribs.BlockWidth) * FmtAttribs.GetElementSize(); - // Note: this addressing complies with how Vulkan addresses textures when copying data to/from buffer: + // Note: this addressing complies with how Vulkan (as well as OpenGL/GLES and Metal) address + // textures when copying data to/from buffers: // address of (x,y,z) = bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1) } diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp index 5648e39d..f82f18cf 100644 --- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp @@ -32,6 +32,7 @@ #include +#include "Atomics.hpp" #include "ShaderResourceVariable.h" #include "PipelineState.h" #include "StringTools.hpp" @@ -340,7 +341,7 @@ template (m_pPSO); for (Uint32 s = 0; s < m_NumShaders; ++s) { - auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + auto& VarDataAllocator = m_pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator); m_pShaderVarMgrs[s].~ShaderVariableManagerVk(); } -- cgit v1.2.3 From 2250c36e3570a949104a3a49b02546a3dd8f1917 Mon Sep 17 00:00:00 2001 From: assiduous Date: Wed, 7 Oct 2020 14:57:33 -0700 Subject: Updated PipelineState[D3D11,D3D12,Vk]Impl to allocate single chunk of memory for resource layout, resource cache and var managers objects --- .../src/PipelineStateD3D11Impl.cpp | 17 ++++++++--- .../src/PipelineStateD3D12Impl.cpp | 33 +++++++++++----------- .../src/PipelineStateVkImpl.cpp | 27 +++++++++++------- 3 files changed, 46 insertions(+), 31 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 39a6ca4a..fb93f90d 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -132,8 +132,16 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR UNEXPECTED(GetPipelineTypeString(m_Desc.PipelineType), " pipelines are not supported by Direct3D11 backend"); } - m_pStaticResourceLayouts = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11", ShaderResourceLayoutD3D11, m_NumShaders); - m_pStaticResourceCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheD3D11", ShaderResourceCacheD3D11, m_NumShaders); + // clang-format off + static_assert((sizeof(ShaderResourceLayoutD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutD3D11) is expected to be a multiple of sizeof(void*)"); + static_assert((sizeof(ShaderResourceCacheD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D11) is expected to be a multiple of sizeof(void*)"); + // clang-format on + const auto MemSize = (sizeof(ShaderResourceLayoutD3D11) + sizeof(ShaderResourceCacheD3D11)) * m_NumShaders; + auto* const pRawMem = + ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11 and ShaderResourceCacheD3D11 arrays", MemSize); + + m_pStaticResourceLayouts = reinterpret_cast(pRawMem); + m_pStaticResourceCaches = reinterpret_cast(m_pStaticResourceLayouts + m_NumShaders); const auto& ResourceLayout = m_Desc.ResourceLayout; @@ -236,13 +244,14 @@ PipelineStateD3D11Impl::~PipelineStateD3D11Impl() m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); } - GetRawAllocator().Free(m_pStaticResourceCaches); for (Uint32 l = 0; l < m_NumShaders; ++l) { m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); } - GetRawAllocator().Free(m_pStaticResourceLayouts); + // m_pStaticResourceLayouts and m_pStaticResourceCaches are allocated in contiguous chunks of memory. + auto* pRawMem = m_pStaticResourceLayouts; + GetRawAllocator().Free(pRawMem); } IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase) diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 138b6b3d..e9c313a5 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -110,20 +110,18 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR const auto& ResourceLayout = m_Desc.ResourceLayout; m_RootSig.AllocateStaticSamplers(ResourceLayout); - { - auto& ShaderResLayoutAllocator = GetRawAllocator(); - m_pShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutD3D12", ShaderResourceLayoutD3D12, m_NumShaders * 2); - } - - { - auto& ShaderResCacheAllocator = GetRawAllocator(); - m_pStaticResourceCaches = ALLOCATE(ShaderResCacheAllocator, "Raw memory for ShaderResourceCacheD3D12", ShaderResourceCacheD3D12, m_NumShaders); - } - - { - auto& ShaderVarMgrAllocator = GetRawAllocator(); - m_pStaticVarManagers = ALLOCATE(ShaderVarMgrAllocator, "Raw memory for ShaderVariableManagerD3D12", ShaderVariableManagerD3D12, m_NumShaders); - } + // clang-format off + static_assert((sizeof(ShaderResourceLayoutD3D12) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutD3D12) is expected to be a multiple of sizeof(void*)"); + static_assert((sizeof(ShaderResourceCacheD3D12) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D12) is expected to be a multiple of sizeof(void*)"); + static_assert((sizeof(ShaderVariableManagerD3D12) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerD3D12) is expected to be a multiple of sizeof(void*)"); + // clang-format on + const auto MemSize = (sizeof(ShaderResourceLayoutD3D12) * 2 + sizeof(ShaderResourceCacheD3D12) + sizeof(ShaderVariableManagerD3D12)) * m_NumShaders; + auto* const pRawMem = + ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12, ShaderResourceCacheD3D12, and ShaderVariableManagerD3D12 arrays", MemSize); + + m_pShaderResourceLayouts = reinterpret_cast(pRawMem); + m_pStaticResourceCaches = reinterpret_cast(m_pShaderResourceLayouts + m_NumShaders * 2); + m_pStaticVarManagers = reinterpret_cast(m_pStaticResourceCaches + m_NumShaders); #ifdef DILIGENT_DEVELOPMENT { @@ -444,9 +442,10 @@ PipelineStateD3D12Impl::~PipelineStateD3D12Impl() m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); m_pShaderResourceLayouts[m_NumShaders + s].~ShaderResourceLayoutD3D12(); } - ShaderResLayoutAllocator.Free(m_pStaticVarManagers); - ShaderResLayoutAllocator.Free(m_pStaticResourceCaches); - ShaderResLayoutAllocator.Free(m_pShaderResourceLayouts); + // m_pShaderResourceLayouts, m_pStaticResourceCaches, and m_pShaderResourceLayouts are allocated in + // contiguous chunks of memory. + auto* pRawMem = m_pShaderResourceLayouts; + ShaderResLayoutAllocator.Free(pRawMem); // D3D12 object can only be destroyed when it is no longer used by the GPU m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 5c165e32..75dd3263 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -159,15 +159,21 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); - // Initialize shader resource layouts - auto& ShaderResLayoutAllocator = GetRawAllocator(); - std::array, MAX_SHADERS_IN_PIPELINE> ShaderResources; std::array, MAX_SHADERS_IN_PIPELINE> ShaderSPIRVs; - m_ShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", ShaderResourceLayoutVk, m_NumShaders * 2); - m_StaticResCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", ShaderResourceCacheVk, m_NumShaders); - m_StaticVarsMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders); + // clang-format off + static_assert((sizeof(ShaderResourceLayoutVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutVk) is expected to be a multiple of sizeof(void*)"); + static_assert((sizeof(ShaderResourceCacheVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheVk) is expected to be a multiple of sizeof(void*)"); + static_assert((sizeof(ShaderVariableManagerVk) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerVk) is expected to be a multiple of sizeof(void*)"); + // clang-format on + const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * m_NumShaders; + auto* const pRawMem = + ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk, ShaderResourceCacheVk, and ShaderVariableManagerVk arrays", MemSize); + + m_ShaderResourceLayouts = reinterpret_cast(pRawMem); + m_StaticResCaches = reinterpret_cast(m_ShaderResourceLayouts + m_NumShaders * 2); + m_StaticVarsMgrs = reinterpret_cast(m_StaticResCaches + m_NumShaders); for (Uint32 s = 0; s < m_NumShaders; ++s) { @@ -182,7 +188,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun auto* pStaticResLayout = new (m_ShaderResourceLayouts + m_NumShaders + s) ShaderResourceLayoutVk{LogicalDevice}; auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources}; - pStaticResLayout->InitializeStaticResourceLayout(ShaderResources[s], ShaderResLayoutAllocator, m_Desc.ResourceLayout, m_StaticResCaches[s]); + pStaticResLayout->InitializeStaticResourceLayout(ShaderResources[s], GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache}; } @@ -507,9 +513,10 @@ PipelineStateVkImpl::~PipelineStateVkImpl() m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); m_StaticVarsMgrs[s].~ShaderVariableManagerVk(); } - RawAllocator.Free(m_ShaderResourceLayouts); - RawAllocator.Free(m_StaticResCaches); - RawAllocator.Free(m_StaticVarsMgrs); + // m_ShaderResourceLayouts, m_StaticResCaches and m_StaticVarsMgrs are allocted in + // contiguous chunks of memory. + void* pRawMem = m_ShaderResourceLayouts; + RawAllocator.Free(pRawMem); } IMPLEMENT_QUERY_INTERFACE(PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase) -- cgit v1.2.3 From 2b396d236ab33dfe9c0defbe401d354ed3fb34f9 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 8 Oct 2020 21:45:01 +0300 Subject: removed strong references to shaders in PSO --- .../src/GraphicsAccessories.cpp | 2 +- .../GraphicsEngine/include/PipelineStateBase.hpp | 603 +++++++++++---------- Graphics/GraphicsEngine/interface/PipelineState.h | 2 +- .../include/PipelineStateD3D11Impl.hpp | 15 +- .../src/DeviceContextD3D11Impl.cpp | 10 +- .../src/PipelineStateD3D11Impl.cpp | 64 ++- .../src/ShaderResourceBindingD3D11Impl.cpp | 9 +- .../include/PipelineStateD3D12Impl.hpp | 8 +- .../src/PipelineStateD3D12Impl.cpp | 69 ++- .../src/ShaderResourceBindingD3D12Impl.cpp | 16 +- .../src/PipelineStateGLImpl.cpp | 41 +- .../include/PipelineStateVkImpl.hpp | 15 +- .../include/ShaderResourceBindingVkImpl.hpp | 2 +- .../include/ShaderResourceLayoutVk.hpp | 118 ++-- .../include/VulkanTypeConversions.hpp | 3 + .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 22 - .../src/PipelineStateVkImpl.cpp | 602 ++++++++++---------- .../src/ShaderResourceBindingVkImpl.cpp | 8 +- .../src/ShaderResourceLayoutVk.cpp | 346 +++++++----- .../src/VulkanTypeConversions.cpp | 23 + .../ShaderTools/include/SPIRVShaderResources.hpp | 2 +- 21 files changed, 1055 insertions(+), 925 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index af77319a..29e5aff3 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -1316,7 +1316,7 @@ Int32 GetShaderTypePipelineIndex(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineT { VERIFY(IsConsistentShaderType(ShaderType, PipelineType), "Shader type ", GetShaderTypeLiteralName(ShaderType), " is inconsistent with pipeline type ", GetPipelineTypeString(PipelineType)); - VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "Only single shader stage should be provided"); + VERIFY((ShaderType & (ShaderType - 1)) == 0, "More than one shader type specified"); static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type"); switch (ShaderType) diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index b54a2f76..76760db5 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -60,44 +60,42 @@ public: /// \param pRefCounters - reference counters object that controls the lifetime of this PSO /// \param pDevice - pointer to the device. /// \param PSODesc - pipeline state description. - /// \param bIsDeviceInternal - flag indicating if the blend state is an internal device object and + /// \param bIsDeviceInternal - flag indicating if the pipeline state is an internal device object and /// must not keep a strong reference to the device. PipelineStateBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, const PipelineStateDesc& PSODesc, bool bIsDeviceInternal = false) : - TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal}, - m_NumShaders{0} + TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal} { - ValidateDesc(); - const auto& SrcLayout = PSODesc.ResourceLayout; size_t StringPoolSize = 0; if (SrcLayout.Variables != nullptr) { for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) + { + VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); StringPoolSize += strlen(SrcLayout.Variables[i].Name) + 1; + } } if (SrcLayout.StaticSamplers != nullptr) { for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + { + VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); StringPoolSize += strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1; + } } - if (PSODesc.IsAnyGraphicsPipeline()) + switch (PSODesc.PipelineType) { - CheckAndCorrectBlendStateDesc(); - CheckRasterizerStateDesc(); - CheckAndCorrectDepthStencilDesc(); - - const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1; - } - else - { - DEV_CHECK_ERR(PSODesc.GraphicsPipeline.InputLayout.NumElements == 0, "Compute pipelines must not have input layout elements"); + // clang-format off + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: ValidateGraphicsPipeline( StringPoolSize); break; + case PIPELINE_TYPE_COMPUTE: ValidateComputePipeline( StringPoolSize); break; + default: UNEXPECTED("unknown pipeline type"); + // clang-format on } m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); @@ -110,7 +108,6 @@ public: DstLayout.Variables = Variables; for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) { - VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); Variables[i] = SrcLayout.Variables[i]; Variables[i].Name = m_StringPool.CopyString(SrcLayout.Variables[i].Name); } @@ -123,7 +120,6 @@ public: DstLayout.StaticSamplers = StaticSamplers; for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) { - VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); #ifdef DILIGENT_DEVELOPMENT { const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor; @@ -143,208 +139,14 @@ public: } } - - if (this->m_Desc.IsComputePipeline()) + switch (PSODesc.PipelineType) { - const auto& ComputePipeline = PSODesc.ComputePipeline; - if (ComputePipeline.pCS == nullptr) - { - LOG_ERROR_AND_THROW("Compute shader is not provided"); - } - -#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \ - if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \ - { \ - LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ - } - - VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute") - - m_pCS = ComputePipeline.pCS; - m_ppShaders[0] = ComputePipeline.pCS; - m_NumShaders = 1; - } - else - { - const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; - - VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pAS, SHADER_TYPE_AMPLIFICATION, "amplification") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pMS, SHADER_TYPE_MESH, "mesh") -#undef VALIDATE_SHADER_TYPE - - if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) - { - DEV_CHECK_ERR(GraphicsPipeline.pVS, "Vertex shader must be defined"); - DEV_CHECK_ERR(!GraphicsPipeline.pAS && !GraphicsPipeline.pMS, "Mesh shaders are not supported in graphics pipeline"); - m_pVS = GraphicsPipeline.pVS; - m_pPS = GraphicsPipeline.pPS; - m_pGS = GraphicsPipeline.pGS; - m_pDS = GraphicsPipeline.pDS; - m_pHS = GraphicsPipeline.pHS; - } - else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH) - { - DEV_CHECK_ERR(GraphicsPipeline.pMS, "Mesh shader must be defined"); - DEV_CHECK_ERR(!GraphicsPipeline.pVS && !GraphicsPipeline.pGS && !GraphicsPipeline.pDS && !GraphicsPipeline.pHS, - "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline"); - DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout ignored in mesh shader"); - DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || - GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED, - "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)"); - m_pAS = GraphicsPipeline.pAS; - m_pMS = GraphicsPipeline.pMS; - m_pPS = GraphicsPipeline.pPS; - } - - if (GraphicsPipeline.pVS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pVS; - if (GraphicsPipeline.pPS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pPS; - if (GraphicsPipeline.pGS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pGS; - if (GraphicsPipeline.pHS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pHS; - if (GraphicsPipeline.pDS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pDS; - if (GraphicsPipeline.pAS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pAS; - if (GraphicsPipeline.pMS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pMS; - - DEV_CHECK_ERR(m_NumShaders > 0, "There must be at least one shader in the Pipeline State"); - - m_pRenderPass = PSODesc.GraphicsPipeline.pRenderPass; - - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) - { - auto RTVFmt = GraphicsPipeline.RTVFormats[rt]; - if (RTVFmt != TEX_FORMAT_UNKNOWN) - { - LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt, - " must be set to TEX_FORMAT_UNKNOWN"); - } - } - - if (m_pRenderPass) - { - const auto& RPDesc = m_pRenderPass->GetDesc(); - VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount); - const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex]; - - this->m_Desc.GraphicsPipeline.NumRenderTargets = static_cast(Subpass.RenderTargetAttachmentCount); - for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt) - { - const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt]; - if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) - { - VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); - this->m_Desc.GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format; - } - } - - if (Subpass.pDepthStencilAttachment != nullptr) - { - const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment; - if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) - { - VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); - this->m_Desc.GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format; - } - } - } - - const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; - LayoutElement* pLayoutElements = nullptr; - if (InputLayout.NumElements > 0) - { - pLayoutElements = ALLOCATE(GetRawAllocator(), "Raw memory for input layout elements", LayoutElement, InputLayout.NumElements); - } - this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements; - for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem) - { - pLayoutElements[Elem] = InputLayout.LayoutElements[Elem]; - pLayoutElements[Elem].HLSLSemantic = m_StringPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic); - } - - - // Correct description and compute offsets and tight strides - std::array Strides, TightStrides = {}; - // Set all strides to an invalid value because an application may want to use 0 stride - for (auto& Stride : Strides) - Stride = LAYOUT_ELEMENT_AUTO_STRIDE; - - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - { - auto& LayoutElem = pLayoutElements[i]; - - if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16) - LayoutElem.IsNormalized = false; // Floating point values cannot be normalized - - auto BuffSlot = LayoutElem.BufferSlot; - if (BuffSlot >= Strides.size()) - { - UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")"); - continue; - } - m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1); - - auto& CurrAutoStride = TightStrides[BuffSlot]; - // If offset is not explicitly specified, use current auto stride value - if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET) - { - LayoutElem.RelativeOffset = CurrAutoStride; - } - - // If stride is explicitly specified, use it for the current buffer slot - if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE) - { - // Verify that the value is consistent with the previously specified stride, if any - if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride) - { - LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot, - ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ", - LayoutElem.Stride, ", while current value is ", Strides[BuffSlot], - ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow " - "the engine compute strides automatically."); - } - Strides[BuffSlot] = LayoutElem.Stride; - } - - CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType)); - } - - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - { - auto& LayoutElem = pLayoutElements[i]; - - auto BuffSlot = LayoutElem.BufferSlot; - // If no input elements explicitly specified stride for this buffer slot, use automatic stride - if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE) - { - Strides[BuffSlot] = TightStrides[BuffSlot]; - } - else - { - if (Strides[BuffSlot] < TightStrides[BuffSlot]) - { - LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot, - " is smaller than the minimum stride ", TightStrides[BuffSlot], - " required to accomodate all input elements."); - } - } - if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE) - LayoutElem.Stride = Strides[BuffSlot]; - } - - if (m_BufferSlotsUsed > 0) - { - m_pStrides = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", Uint32, m_BufferSlotsUsed); - - // Set strides for all unused slots to 0 - for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i) - { - auto Stride = Strides[i]; - m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0; - } - } + // clang-format off + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: InitGraphicsPipeline(); break; + case PIPELINE_TYPE_COMPUTE: InitComputePipeline(); break; + default: UNEXPECTED("unknown pipeline type"); + // clang-format on } VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); @@ -399,28 +201,8 @@ public: return m_BufferSlotsUsed; } - IShader* GetVS() { return m_pVS; } - IShader* GetPS() { return m_pPS; } - IShader* GetGS() { return m_pGS; } - IShader* GetDS() { return m_pDS; } - IShader* GetHS() { return m_pHS; } - IShader* GetCS() { return m_pCS; } - - IShader* const* GetShaders() const { return m_ppShaders.data(); } - Uint32 GetNumShaders() const { return m_NumShaders; } - - template - ShaderType* GetShader(Uint32 ShaderInd) - { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return ValidatedCast(m_ppShaders[ShaderInd]); - } - template - ShaderType* GetShader(Uint32 ShaderInd) const - { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return ValidatedCast(m_ppShaders[ShaderInd]); - } + SHADER_TYPE const* GetShaderTypes() const { return m_pShaderTypes.data(); } + Uint32 GetNumShaderTypes() const { return m_NumShaderTypes; } // This function only compares shader resource layout hashes, so // it can potentially give false negatives @@ -431,27 +213,20 @@ public: protected: Uint32 m_BufferSlotsUsed = 0; - Uint32 m_NumShaders = 0; ///< Number of shaders that this PSO uses Uint32* m_pStrides = nullptr; StringPool m_StringPool; - RefCntAutoPtr m_pVS; ///< Strong reference to the vertex shader - RefCntAutoPtr m_pPS; ///< Strong reference to the pixel shader - RefCntAutoPtr m_pGS; ///< Strong reference to the geometry shader - RefCntAutoPtr m_pDS; ///< Strong reference to the domain shader - RefCntAutoPtr m_pHS; ///< Strong reference to the hull shader - RefCntAutoPtr m_pCS; ///< Strong reference to the compute shader - RefCntAutoPtr m_pAS; ///< Strong reference to the amplification shader - RefCntAutoPtr m_pMS; ///< Strong reference to the mesh shader - RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object - std::array m_ppShaders = {}; ///< Array of pointers to the shaders used by this PSO - size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout + Uint8 m_NumShaderTypes = 0; ///< Number of shader types that this PSO uses + std::array m_pShaderTypes = {}; ///< Array of shader types used by this PSO + size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout protected: +#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(this->m_Desc.PipelineType), " PSO '", this->m_Desc.Name, "' is invalid: ", ##__VA_ARGS__) + Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array& ResourceLayoutIndex) const { if (!IsConsistentShaderType(ShaderType, this->m_Desc.PipelineType)) @@ -512,46 +287,70 @@ protected: return LayoutInd; } -private: -#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(this->m_Desc.PipelineType), " PSO '", this->m_Desc.Name, "' is invalid: ", ##__VA_ARGS__) +public: + using ShaderStages_t = std::vector>; - void ValidateDesc() const +protected: + void ExtractShaders(ShaderStages_t& ShaderStages) { - if (this->m_Desc.IsComputePipeline()) + auto& Desc = this->m_Desc; + switch (Desc.PipelineType) { - if (this->m_Desc.GraphicsPipeline.pRenderPass != nullptr) + case PIPELINE_TYPE_COMPUTE: { - LOG_PSO_ERROR_AND_THROW("GraphicsPipeline.pRenderPass must be null for compute pipelines"); - } - } - else - { - const auto& GraphicsPipeline = this->m_Desc.GraphicsPipeline; - if (GraphicsPipeline.pRenderPass != nullptr) - { - if (GraphicsPipeline.NumRenderTargets != 0) - LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used"); - if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN) - LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); + if (Desc.ComputePipeline.pCS) ShaderStages.push_back({SHADER_TYPE_COMPUTE, Desc.ComputePipeline.pCS}); - for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) - { - if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN) - LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); - } + // reset shader pointers because we don't keep strong references to shaders + Desc.ComputePipeline.pCS = nullptr; + break; + } - const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc(); - if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount) - LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'"); + case PIPELINE_TYPE_GRAPHICS: + { + if (Desc.GraphicsPipeline.pVS) ShaderStages.push_back({SHADER_TYPE_VERTEX, Desc.GraphicsPipeline.pVS}); + if (Desc.GraphicsPipeline.pHS) ShaderStages.push_back({SHADER_TYPE_HULL, Desc.GraphicsPipeline.pHS}); + if (Desc.GraphicsPipeline.pDS) ShaderStages.push_back({SHADER_TYPE_DOMAIN, Desc.GraphicsPipeline.pDS}); + if (Desc.GraphicsPipeline.pGS) ShaderStages.push_back({SHADER_TYPE_GEOMETRY, Desc.GraphicsPipeline.pGS}); + if (Desc.GraphicsPipeline.pPS) ShaderStages.push_back({SHADER_TYPE_PIXEL, Desc.GraphicsPipeline.pPS}); + + // reset shader pointers because we don't keep strong references to shaders + Desc.GraphicsPipeline.pVS = nullptr; + Desc.GraphicsPipeline.pHS = nullptr; + Desc.GraphicsPipeline.pDS = nullptr; + Desc.GraphicsPipeline.pGS = nullptr; + Desc.GraphicsPipeline.pPS = nullptr; + break; } - else + + case PIPELINE_TYPE_MESH: { - if (GraphicsPipeline.SubpassIndex != 0) - LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used"); + if (Desc.GraphicsPipeline.pAS) ShaderStages.push_back({SHADER_TYPE_AMPLIFICATION, Desc.GraphicsPipeline.pAS}); + if (Desc.GraphicsPipeline.pMS) ShaderStages.push_back({SHADER_TYPE_MESH, Desc.GraphicsPipeline.pMS}); + if (Desc.GraphicsPipeline.pPS) ShaderStages.push_back({SHADER_TYPE_PIXEL, Desc.GraphicsPipeline.pPS}); + + // reset shader pointers because we don't keep strong references to shaders + Desc.GraphicsPipeline.pAS = nullptr; + Desc.GraphicsPipeline.pMS = nullptr; + Desc.GraphicsPipeline.pPS = nullptr; + break; } + + default: + UNEXPECTED("unknown pipeline type"); } + +#ifdef DILIGENT_DEVELOPMENT + VERIFY_EXPR(ShaderStages.size() == m_NumShaderTypes); + + for (Uint32 s = 0; s < m_NumShaderTypes; ++s) + { + VERIFY_EXPR(ShaderStages[s].first == m_pShaderTypes[s]); + } +#endif } + +private: void CheckRasterizerStateDesc() const { const auto& RSDesc = this->m_Desc.GraphicsPipeline.RasterizerDesc; @@ -648,6 +447,246 @@ private: RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp; } } + + void ValidateGraphicsPipeline(size_t& StringPoolSize) + { + const auto& GraphicsPipeline = this->m_Desc.GraphicsPipeline; + if (GraphicsPipeline.pRenderPass != nullptr) + { + if (GraphicsPipeline.NumRenderTargets != 0) + LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used"); + if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); + + for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) + { + if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); + } + + const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc(); + if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount) + LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'"); + } + else + { + if (GraphicsPipeline.SubpassIndex != 0) + LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used"); + } + + CheckAndCorrectBlendStateDesc(); + CheckRasterizerStateDesc(); + CheckAndCorrectDepthStencilDesc(); + + const auto& InputLayout = this->m_Desc.GraphicsPipeline.InputLayout; + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1; + } + + void ValidateComputePipeline(size_t& StringPoolSize) + { + if (this->m_Desc.GraphicsPipeline.pRenderPass != nullptr) + { + LOG_PSO_ERROR_AND_THROW("GraphicsPipeline.pRenderPass must be null for compute pipelines"); + } + DEV_CHECK_ERR(this->m_Desc.GraphicsPipeline.InputLayout.NumElements == 0, "Compute pipelines must not have input layout elements"); + } + +#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \ + if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \ + { \ + LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ + } + + void InitGraphicsPipeline() + { + const auto& PSODesc = this->m_Desc; + const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; + + VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pAS, SHADER_TYPE_AMPLIFICATION, "amplification") + VALIDATE_SHADER_TYPE(GraphicsPipeline.pMS, SHADER_TYPE_MESH, "mesh") + + if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) + { + DEV_CHECK_ERR(GraphicsPipeline.pVS, "Vertex shader must be defined"); + DEV_CHECK_ERR(!GraphicsPipeline.pAS && !GraphicsPipeline.pMS, "Mesh shaders are not supported in graphics pipeline"); + } + else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH) + { + DEV_CHECK_ERR(GraphicsPipeline.pMS, "Mesh shader must be defined"); + DEV_CHECK_ERR(!GraphicsPipeline.pVS && !GraphicsPipeline.pGS && !GraphicsPipeline.pDS && !GraphicsPipeline.pHS, + "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline"); + DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout ignored in mesh shader"); + DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || + GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED, + "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)"); + } + + if (GraphicsPipeline.pVS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_VERTEX; + if (GraphicsPipeline.pHS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_HULL; + if (GraphicsPipeline.pDS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_DOMAIN; + if (GraphicsPipeline.pGS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_GEOMETRY; + if (GraphicsPipeline.pAS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_AMPLIFICATION; + if (GraphicsPipeline.pMS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_MESH; + if (GraphicsPipeline.pPS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_PIXEL; + + DEV_CHECK_ERR(m_NumShaderTypes > 0, "There must be at least one shader in the Pipeline State"); + + m_pRenderPass = PSODesc.GraphicsPipeline.pRenderPass; + + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) + { + auto RTVFmt = GraphicsPipeline.RTVFormats[rt]; + if (RTVFmt != TEX_FORMAT_UNKNOWN) + { + LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt, + " must be set to TEX_FORMAT_UNKNOWN"); + } + } + + if (m_pRenderPass) + { + const auto& RPDesc = m_pRenderPass->GetDesc(); + VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount); + const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex]; + + this->m_Desc.GraphicsPipeline.NumRenderTargets = static_cast(Subpass.RenderTargetAttachmentCount); + for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt) + { + const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt]; + if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); + this->m_Desc.GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format; + } + } + + if (Subpass.pDepthStencilAttachment != nullptr) + { + const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment; + if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) + { + VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); + this->m_Desc.GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format; + } + } + } + + const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; + LayoutElement* pLayoutElements = nullptr; + if (InputLayout.NumElements > 0) + { + pLayoutElements = ALLOCATE(GetRawAllocator(), "Raw memory for input layout elements", LayoutElement, InputLayout.NumElements); + } + for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem) + { + pLayoutElements[Elem] = InputLayout.LayoutElements[Elem]; + pLayoutElements[Elem].HLSLSemantic = m_StringPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic); + } + this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements; + + + // Correct description and compute offsets and tight strides + std::array Strides, TightStrides = {}; + // Set all strides to an invalid value because an application may want to use 0 stride + for (auto& Stride : Strides) + Stride = LAYOUT_ELEMENT_AUTO_STRIDE; + + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + { + auto& LayoutElem = pLayoutElements[i]; + + if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16) + LayoutElem.IsNormalized = false; // Floating point values cannot be normalized + + auto BuffSlot = LayoutElem.BufferSlot; + if (BuffSlot >= Strides.size()) + { + UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")"); + continue; + } + m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1); + + auto& CurrAutoStride = TightStrides[BuffSlot]; + // If offset is not explicitly specified, use current auto stride value + if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET) + { + LayoutElem.RelativeOffset = CurrAutoStride; + } + + // If stride is explicitly specified, use it for the current buffer slot + if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE) + { + // Verify that the value is consistent with the previously specified stride, if any + if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride) + { + LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot, + ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ", + LayoutElem.Stride, ", while current value is ", Strides[BuffSlot], + ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow " + "the engine compute strides automatically."); + } + Strides[BuffSlot] = LayoutElem.Stride; + } + + CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType)); + } + + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + { + auto& LayoutElem = pLayoutElements[i]; + + auto BuffSlot = LayoutElem.BufferSlot; + // If no input elements explicitly specified stride for this buffer slot, use automatic stride + if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE) + { + Strides[BuffSlot] = TightStrides[BuffSlot]; + } + else + { + if (Strides[BuffSlot] < TightStrides[BuffSlot]) + { + LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot, + " is smaller than the minimum stride ", TightStrides[BuffSlot], + " required to accomodate all input elements."); + } + } + if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE) + LayoutElem.Stride = Strides[BuffSlot]; + } + + if (m_BufferSlotsUsed > 0) + { + m_pStrides = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", Uint32, m_BufferSlotsUsed); + + // Set strides for all unused slots to 0 + for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i) + { + auto Stride = Strides[i]; + m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0; + } + } + } + + void InitComputePipeline() + { + const auto& ComputePipeline = this->m_Desc.ComputePipeline; + if (ComputePipeline.pCS == nullptr) + { + LOG_ERROR_AND_THROW("Compute shader is not provided"); + } + + VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute"); + + m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_COMPUTE; + } + +#undef VALIDATE_SHADER_TYPE #undef LOG_PSO_ERROR_AND_THROW }; diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 9491168d..2d22c826 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -286,7 +286,7 @@ struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs) #if DILIGENT_CPP_INTERFACE bool IsAnyGraphicsPipeline() const { return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH; } - bool IsComputePipeline () const { return PipelineType == PIPELINE_TYPE_COMPUTE; } + bool IsComputePipeline() const { return PipelineType == PIPELINE_TYPE_COMPUTE; } #endif }; typedef struct PipelineStateDesc PipelineStateDesc; diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 02f922a6..7acb15f0 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -36,6 +36,7 @@ #include "ShaderResourceLayoutD3D11.hpp" #include "SRBMemoryAllocator.hpp" #include "RenderDeviceD3D11Impl.hpp" +#include "ShaderD3D11Impl.hpp" namespace Diligent { @@ -117,16 +118,19 @@ public: const ShaderResourceLayoutD3D11& GetStaticResourceLayout(Uint32 s) const { - VERIFY_EXPR(s < m_NumShaders); + VERIFY_EXPR(s < GetNumShaderTypes()); return m_pStaticResourceLayouts[s]; } ShaderResourceCacheD3D11& GetStaticResourceCache(Uint32 s) { - VERIFY_EXPR(s < m_NumShaders); + VERIFY_EXPR(s < GetNumShaderTypes()); return m_pStaticResourceCaches[s]; } + const ShaderD3D11Impl* GetShaderByType(SHADER_TYPE ShaderType) const; + const ShaderD3D11Impl* GetShader(Uint32 Index) const; + void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; private: @@ -135,6 +139,13 @@ private: 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; ShaderResourceLayoutD3D11* m_pStaticResourceLayouts = nullptr; diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index 6af8b502..cd942aed 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -179,9 +179,9 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* { #ifdef DILIGENT_DEVELOPMENT bool ResourcesPresent = false; - for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaders(); ++s) + for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaderTypes(); ++s) { - auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); + auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); if (pShaderD3D11->GetD3D11Resources()->GetTotalResources() > 0) ResourcesPresent = true; } @@ -206,7 +206,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* #endif auto NumShaders = pShaderResBindingD3D11->GetNumActiveShaders(); - VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaders(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state"); + VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaderTypes(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state"); #ifdef DILIGENT_DEVELOPMENT { @@ -233,7 +233,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType); #ifdef DILIGENT_DEVELOPMENT - auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); + auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType); #endif @@ -380,7 +380,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType); #ifdef DILIGENT_DEVELOPMENT - auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); + auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType); #endif diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index fb93f90d..0e312740 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -31,7 +31,6 @@ #include "RenderDeviceD3D11Impl.hpp" #include "ShaderResourceBindingD3D11Impl.hpp" #include "EngineMemory.h" -#include "ShaderD3D11Impl.hpp" namespace Diligent { @@ -136,24 +135,24 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR static_assert((sizeof(ShaderResourceLayoutD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutD3D11) is expected to be a multiple of sizeof(void*)"); static_assert((sizeof(ShaderResourceCacheD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D11) is expected to be a multiple of sizeof(void*)"); // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutD3D11) + sizeof(ShaderResourceCacheD3D11)) * m_NumShaders; + const auto MemSize = (sizeof(ShaderResourceLayoutD3D11) + sizeof(ShaderResourceCacheD3D11)) * GetNumShaderTypes(); auto* const pRawMem = ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11 and ShaderResourceCacheD3D11 arrays", MemSize); m_pStaticResourceLayouts = reinterpret_cast(pRawMem); - m_pStaticResourceCaches = reinterpret_cast(m_pStaticResourceLayouts + m_NumShaders); + m_pStaticResourceCaches = reinterpret_cast(m_pStaticResourceLayouts + GetNumShaderTypes()); const auto& ResourceLayout = m_Desc.ResourceLayout; #ifdef DILIGENT_DEVELOPMENT { const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { - auto* pShader = GetShader(s); + auto* pShader = GetShader(s); pResources[s] = &(*pShader->GetD3D11Resources()); } - ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, m_NumShaders, + ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderTypes(), (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); } @@ -162,9 +161,9 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR decltype(m_StaticSamplers) StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")); std::array ShaderResLayoutDataSizes = {}; std::array ShaderResCacheDataSizes = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { - const auto* pShader = GetShader(s); + const auto* pShader = GetShader(s); const auto& ShaderDesc = pShader->GetDesc(); const auto& ShaderResources = *pShader->GetD3D11Resources(); VERIFY_EXPR(ShaderDesc.ShaderType == ShaderResources.GetShaderType()); @@ -222,14 +221,14 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR if (m_Desc.SRBAllocationGranularity > 1) { - m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderResLayoutDataSizes.data(), m_NumShaders, ShaderResCacheDataSizes.data()); + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderTypes(), ShaderResLayoutDataSizes.data(), GetNumShaderTypes(), ShaderResCacheDataSizes.data()); } m_StaticSamplers.reserve(StaticSamplers.size()); for (auto& Sam : StaticSamplers) m_StaticSamplers.emplace_back(std::move(Sam)); - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { // Initialize static samplers in the static resource cache to avoid warning messages SetStaticSamplers(m_pStaticResourceCaches[s], s); @@ -239,13 +238,13 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR PipelineStateD3D11Impl::~PipelineStateD3D11Impl() { - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); } - for (Uint32 l = 0; l < m_NumShaders; ++l) + for (Uint32 l = 0; l < GetNumShaderTypes(); ++l) { m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); } @@ -298,13 +297,13 @@ bool PipelineStateD3D11Impl::IsCompatibleWith(const IPipelineState* pPSO) const if (m_ShaderResourceLayoutHash != pPSOD3D11->m_ShaderResourceLayoutHash) return false; - if (m_NumShaders != pPSOD3D11->m_NumShaders) + if (GetNumShaderTypes() != pPSOD3D11->GetNumShaderTypes()) return false; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { - auto* pShader0 = GetShader(s); - auto* pShader1 = pPSOD3D11->GetShader(s); + auto* pShader0 = GetShader(s); + auto* pShader1 = pPSOD3D11->GetShader(s); if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType) return false; const auto& Res0 = *pShader0->GetD3D11Resources(); @@ -361,7 +360,7 @@ ID3D11ComputeShader* PipelineStateD3D11Impl::GetD3D11ComputeShader() void PipelineStateD3D11Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) { - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { auto& StaticResLayout = m_pStaticResourceLayouts[s]; if ((ShaderFlags & StaticResLayout.GetShaderType()) != 0) @@ -375,7 +374,7 @@ Uint32 PipelineStateD3D11Impl::GetStaticVariableCount(SHADER_TYPE ShaderType) co if (LayoutInd < 0) return 0; - VERIFY_EXPR(static_cast(LayoutInd) <= m_NumShaders); + VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderTypes()); return m_pStaticResourceLayouts[LayoutInd].GetTotalResourceCount(); } @@ -385,7 +384,7 @@ IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByName(SHADER_ if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) <= m_NumShaders); + VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderTypes()); return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Name); } @@ -395,7 +394,7 @@ IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByIndex(SHADER if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) <= m_NumShaders); + VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderTypes()); return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Index); } @@ -414,4 +413,29 @@ void PipelineStateD3D11Impl::SetStaticSamplers(ShaderResourceCacheD3D11& Resourc } } +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 + } +} + +const ShaderD3D11Impl* PipelineStateD3D11Impl::GetShader(Uint32 Index) const +{ + if (Index < GetNumShaderTypes()) + return GetShaderByType(GetShaderTypes()[Index]); + + UNEXPECTED("Shader index is out of range"); + return nullptr; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 62fd2df7..17083bbc 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -50,7 +50,7 @@ ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounter // clang-format on { m_ResourceLayoutIndex.fill(-1); - m_NumActiveShaders = static_cast(pPSO->GetNumShaders()); + m_NumActiveShaders = static_cast(pPSO->GetNumShaderTypes()); // clang-format off m_pResourceLayouts = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11", ShaderResourceLayoutD3D11, m_NumActiveShaders); @@ -62,7 +62,7 @@ ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounter // Reserve memory for resource layouts for (Uint8 s = 0; s < m_NumActiveShaders; ++s) { - auto* pShaderD3D11 = pPSO->GetShader(s); + auto* pShaderD3D11 = pPSO->GetShader(s); auto& SRBMemAllocator = pPSO->GetSRBMemoryAllocator(); auto& ResCacheDataAllocator = SRBMemAllocator.GetResourceCacheDataAllocator(s); @@ -151,14 +151,13 @@ void ShaderResourceBindingD3D11Impl::InitializeStaticResources(const IPipelineSt } const auto* pPSOD3D11 = ValidatedCast(pPipelineState); - auto ppShaders = pPSOD3D11->GetShaders(); - auto NumShaders = pPSOD3D11->GetNumShaders(); + auto NumShaders = pPSOD3D11->GetNumShaderTypes(); VERIFY_EXPR(NumShaders == m_NumActiveShaders); for (Uint32 shader = 0; shader < NumShaders; ++shader) { const auto& StaticResLayout = pPSOD3D11->GetStaticResourceLayout(shader); - auto* pShaderD3D11 = ValidatedCast(ppShaders[shader]); + auto* pShaderD3D11 = pPSOD3D11->GetShader(shader); #ifdef DILIGENT_DEVELOPMENT if (!StaticResLayout.dvpVerifyBindings()) { diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index a53a625d..1ce53c24 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -95,19 +95,19 @@ public: const ShaderResourceLayoutD3D12& GetShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaders); + VERIFY_EXPR(ShaderInd < GetNumShaderTypes()); return m_pShaderResourceLayouts[ShaderInd]; } const ShaderResourceLayoutD3D12& GetStaticShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return m_pShaderResourceLayouts[m_NumShaders + ShaderInd]; + VERIFY_EXPR(ShaderInd < GetNumShaderTypes()); + return m_pShaderResourceLayouts[GetNumShaderTypes() + ShaderInd]; } ShaderResourceCacheD3D12& GetStaticShaderResCache(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaders); + VERIFY_EXPR(ShaderInd < GetNumShaderTypes()); return m_pStaticResourceCaches[ShaderInd]; } diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index e9c313a5..d5958ea8 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -106,6 +106,9 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR { m_ResourceLayoutIndex.fill(-1); + ShaderStages_t ShaderStages; + ExtractShaders(ShaderStages); + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); const auto& ResourceLayout = m_Desc.ResourceLayout; m_RootSig.AllocateStaticSamplers(ResourceLayout); @@ -115,31 +118,31 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR static_assert((sizeof(ShaderResourceCacheD3D12) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D12) is expected to be a multiple of sizeof(void*)"); static_assert((sizeof(ShaderVariableManagerD3D12) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerD3D12) is expected to be a multiple of sizeof(void*)"); // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutD3D12) * 2 + sizeof(ShaderResourceCacheD3D12) + sizeof(ShaderVariableManagerD3D12)) * m_NumShaders; + const auto MemSize = (sizeof(ShaderResourceLayoutD3D12) * 2 + sizeof(ShaderResourceCacheD3D12) + sizeof(ShaderVariableManagerD3D12)) * GetNumShaderTypes(); auto* const pRawMem = ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12, ShaderResourceCacheD3D12, and ShaderVariableManagerD3D12 arrays", MemSize); m_pShaderResourceLayouts = reinterpret_cast(pRawMem); - m_pStaticResourceCaches = reinterpret_cast(m_pShaderResourceLayouts + m_NumShaders * 2); - m_pStaticVarManagers = reinterpret_cast(m_pStaticResourceCaches + m_NumShaders); + m_pStaticResourceCaches = reinterpret_cast(m_pShaderResourceLayouts + GetNumShaderTypes() * 2); + m_pStaticVarManagers = reinterpret_cast(m_pStaticResourceCaches + GetNumShaderTypes()); #ifdef DILIGENT_DEVELOPMENT { const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - const auto* pShader = GetShader(s); + const auto* pShader = ValidatedCast(ShaderStages[s].second); pResources[s] = &(*pShader->GetShaderResources()); } - ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, m_NumShaders, + ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderTypes(), (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); } #endif - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto* pShaderD3D12 = GetShader(s); + auto* pShaderD3D12 = ValidatedCast(ShaderStages[s].second); auto ShaderType = pShaderD3D12->GetDesc().ShaderType; auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); @@ -163,7 +166,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D12{ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources}; const SHADER_RESOURCE_VARIABLE_TYPE StaticVarType[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; - new (m_pShaderResourceLayouts + m_NumShaders + s) + new (m_pShaderResourceLayouts + GetNumShaderTypes() + s) ShaderResourceLayoutD3D12 // { *this, @@ -182,11 +185,11 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR ShaderVariableManagerD3D12 // { *this, - GetStaticShaderResLayout(s), + GetStaticShaderResLayout(static_cast(s)), GetRawAllocator(), nullptr, 0, - GetStaticShaderResCache(s) // + GetStaticShaderResCache(static_cast(s)) // }; } m_RootSig.Finalize(pd3d12Device); @@ -195,14 +198,9 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR { case PIPELINE_TYPE_COMPUTE: { - auto& ComputePipeline = m_Desc.ComputePipeline; - - if (ComputePipeline.pCS == nullptr) - LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc"); - D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; - auto* pByteCode = ValidatedCast(ComputePipeline.pCS)->GetShaderByteCode(); + auto* pByteCode = ValidatedCast(ShaderStages[0].second)->GetShaderByteCode(); d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); @@ -231,9 +229,9 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto* pShaderD3D12 = GetShader(s); + auto* pShaderD3D12 = ValidatedCast(ShaderStages[s].second); auto ShaderType = pShaderD3D12->GetDesc().ShaderType; D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; @@ -335,9 +333,9 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR }; MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto* pShaderD3D12 = GetShader(s); + auto* pShaderD3D12 = ValidatedCast(ShaderStages[s].second); auto ShaderType = pShaderD3D12->GetDesc().ShaderType; D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; @@ -412,7 +410,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR if (m_Desc.SRBAllocationGranularity > 1) { std::array ShaderVarMgrDataSizes = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { std::array AllowedVarTypes = { @@ -425,7 +423,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR } auto CacheMemorySize = m_RootSig.GetResourceCacheRequiredMemSize(); - m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderVarMgrDataSizes.data(), 1, &CacheMemorySize); + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderTypes(), ShaderVarMgrDataSizes.data(), 1, &CacheMemorySize); } m_ShaderResourceLayoutHash = m_RootSig.GetHash(); @@ -434,13 +432,13 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR PipelineStateD3D12Impl::~PipelineStateD3D12Impl() { auto& ShaderResLayoutAllocator = GetRawAllocator(); - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { m_pStaticVarManagers[s].Destroy(GetRawAllocator()); m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); - m_pShaderResourceLayouts[m_NumShaders + s].~ShaderResourceLayoutD3D12(); + m_pShaderResourceLayouts[GetNumShaderTypes() + s].~ShaderResourceLayoutD3D12(); } // m_pShaderResourceLayouts, m_pStaticResourceCaches, and m_pShaderResourceLayouts are allocated in // contiguous chunks of memory. @@ -479,27 +477,26 @@ bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState* pPSO) const #ifdef DILIGENT_DEBUG { bool IsCompatibleShaders = true; - if (m_NumShaders != pPSOD3D12->m_NumShaders) + if (GetNumShaderTypes() != pPSOD3D12->GetNumShaderTypes()) IsCompatibleShaders = false; if (IsCompatibleShaders) { - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { - auto* pShader0 = GetShader(s); - auto* pShader1 = pPSOD3D12->GetShader(s); - if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType) + if (GetShaderTypes()[s] != pPSOD3D12->GetShaderTypes()[s]) { IsCompatibleShaders = false; break; } - const ShaderResourcesD3D12* pRes0 = pShader0->GetShaderResources().get(); + // AZ TODO + /*const ShaderResourcesD3D12* pRes0 = pShader0->GetShaderResources().get(); const ShaderResourcesD3D12* pRes1 = pShader1->GetShaderResources().get(); if (!pRes0->IsCompatibleWith(*pRes1)) { IsCompatibleShaders = false; break; - } + }*/ } } @@ -606,7 +603,7 @@ bool PipelineStateD3D12Impl::ContainsShaderResources() const void PipelineStateD3D12Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) { - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { auto ShaderType = GetStaticShaderResLayout(s).GetShaderType(); if ((ShaderFlags & ShaderType) != 0) @@ -620,7 +617,7 @@ Uint32 PipelineStateD3D12Impl::GetStaticVariableCount(SHADER_TYPE ShaderType) co if (LayoutInd < 0) return 0; - VERIFY_EXPR(static_cast(LayoutInd) < m_NumShaders); + VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderTypes()); return m_pStaticVarManagers[LayoutInd].GetVariableCount(); } @@ -630,7 +627,7 @@ IShaderResourceVariable* PipelineStateD3D12Impl::GetStaticVariableByName(SHADER_ if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) < m_NumShaders); + VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderTypes()); return m_pStaticVarManagers[LayoutInd].GetVariable(Name); } @@ -640,7 +637,7 @@ IShaderResourceVariable* PipelineStateD3D12Impl::GetStaticVariableByIndex(SHADER if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) < m_NumShaders); + VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderTypes()); return m_pStaticVarManagers[LayoutInd].GetVariable(Index); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 257a4688..17387138 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -45,11 +45,10 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter IsPSOInternal }, m_ShaderResourceCache{ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources}, - m_NumShaders {static_cast(pPSO->GetNumShaders())} + m_NumShaders {static_cast(pPSO->GetNumShaderTypes())} // clang-format on { m_ResourceLayoutIndex.fill(-1); - auto* ppShaders = pPSO->GetShaders(); auto* pRenderDeviceD3D12Impl = ValidatedCast(pPSO->GetDevice()); auto& ResCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); @@ -59,9 +58,8 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter for (Uint32 s = 0; s < m_NumShaders; ++s) { - auto* pShader = ppShaders[s]; - auto ShaderType = pShader->GetDesc().ShaderType; - auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType); + auto ShaderType = pPSO->GetShaderTypes()[s]; + auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType); auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); @@ -189,20 +187,20 @@ void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const IPipelineSt } auto* pPSO12 = ValidatedCast(pPSO); - auto NumShaders = pPSO12->GetNumShaders(); + auto NumShaders = pPSO12->GetNumShaderTypes(); // Copy static resources for (Uint32 s = 0; s < NumShaders; ++s) { const auto& ShaderResLayout = pPSO12->GetShaderResLayout(s); auto& StaticResLayout = pPSO12->GetStaticShaderResLayout(s); auto& StaticResCache = pPSO12->GetStaticShaderResCache(s); + #ifdef DILIGENT_DEVELOPMENT if (!StaticResLayout.dvpVerifyBindings(StaticResCache)) { - auto* pShader = pPSO12->GetShader(s); LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", pPSO12->GetDesc().Name, - "' will not be successfully initialized because not all static resource bindings in shader '", - pShader->GetDesc().Name, + "' will not be successfully initialized because not all static resource bindings in shader type '", + GetShaderTypeLiteralName(pPSO12->GetShaderTypes()[s]), "' 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."); } diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 399983c9..c61ead8c 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -52,7 +52,9 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun m_StaticResourceLayout{*this} // clang-format on { - if (m_Desc.IsAnyGraphicsPipeline() && m_pPS == nullptr) + RefCntAutoPtr pTempPS; + + if (m_Desc.IsAnyGraphicsPipeline() && m_Desc.GraphicsPipeline.pPS == nullptr) { // Some OpenGL implementations fail if fragment shader is not present, so // create a dummy one. @@ -61,9 +63,16 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun ShaderCI.Source = "void main(){}"; ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; ShaderCI.Desc.Name = "Dummy fragment shader"; - pDeviceGL->CreateShader(ShaderCI, &m_pPS); - m_Desc.GraphicsPipeline.pPS = m_pPS; - m_ppShaders[m_NumShaders++] = m_pPS; + pDeviceGL->CreateShader(ShaderCI, &pTempPS); + } + + ShaderStages_t ShaderStages; + ExtractShaders(ShaderStages); + + if (pTempPS) + { + m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_PIXEL; + ShaderStages.push_back({SHADER_TYPE_PIXEL, pTempPS}); } auto& DeviceCaps = pDeviceGL->GetDeviceCaps(); @@ -83,13 +92,14 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun // Program pipelines are not shared between GL contexts, so we cannot create // it now m_ShaderResourceLayoutHash = 0; - m_ProgramResources.resize(m_NumShaders); - m_GLPrograms.reserve(m_NumShaders); - for (Uint32 i = 0; i < m_NumShaders; ++i) + m_ProgramResources.resize(ShaderStages.size()); + m_GLPrograms.reserve(ShaderStages.size()); + for (size_t i = 0; i < ShaderStages.size(); ++i) { - auto* pShaderGL = GetShader(i); + auto* pShader = ShaderStages[i].second; + auto* pShaderGL = ValidatedCast(pShader); const auto& ShaderDesc = pShaderGL->GetDesc(); - m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(&m_ppShaders[i], 1, true)); + m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(&pShader, 1, true)); // Load uniforms and assign bindings m_ProgramResources[i].LoadUniforms(ShaderDesc.ShaderType, m_GLPrograms[i], GLState, m_TotalUniformBufferBindings, @@ -102,10 +112,12 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun } else { - m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(m_ppShaders.data(), m_NumShaders, false)); + UNEXPECTED("TODO"); + // AZ TODO + /*m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(m_ppShaders.data(), ShaderStages.size(), false)); m_ProgramResources.resize(1); SHADER_TYPE ShaderStages = SHADER_TYPE_UNKNOWN; - for (Uint32 i = 0; i < m_NumShaders; ++i) + for (size_t i = 0; i < ShaderStages.size(); ++i) { const auto& ShaderDesc = m_ppShaders[i]->GetDesc(); ShaderStages |= ShaderDesc.ShaderType; @@ -116,7 +128,7 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun m_TotalImageBindings, m_TotalStorageBufferBindings); - m_ShaderResourceLayoutHash = m_ProgramResources[0].GetHash(); + m_ShaderResourceLayoutHash = m_ProgramResources[0].GetHash();*/ } // Initialize master resource layout that keeps all variable types and does not reference a resource cache @@ -214,10 +226,9 @@ GLObjectWrappers::GLPipelineObj& PipelineStateGLImpl::GetGLProgramPipeline(GLCon m_GLProgPipelines.emplace_back(Context, true); auto& ctx_pipeline = m_GLProgPipelines.back(); GLuint Pipeline = ctx_pipeline.second; - for (Uint32 i = 0; i < m_NumShaders; ++i) + for (Uint32 i = 0; i < GetNumShaderTypes(); ++i) { - auto* pCurrShader = GetShader(i); - auto GLShaderBit = ShaderTypeToGLShaderBit(pCurrShader->GetDesc().ShaderType); + auto GLShaderBit = ShaderTypeToGLShaderBit(GetShaderTypes()[i]); // If the program has an active code for each stage mentioned in set flags, // then that code will be used by the pipeline. If program is 0, then the given // stages are cleared from the pipeline. diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index d1732211..303496bb 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -56,6 +56,7 @@ class PipelineStateVkImpl final : public PipelineStateBase; + using ShaderSPIRVs_t = std::vector>; PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const PipelineStateCreateInfo& CreateInfo); ~PipelineStateVkImpl(); @@ -104,7 +105,7 @@ public: const ShaderResourceLayoutVk& GetShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaders); + VERIFY_EXPR(ShaderInd < m_NumShaderTypes); return m_ShaderResourceLayouts[ShaderInd]; } @@ -127,19 +128,19 @@ public: private: const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaders); - return m_ShaderResourceLayouts[m_NumShaders + ShaderInd]; + VERIFY_EXPR(ShaderInd < m_NumShaderTypes); + return m_ShaderResourceLayouts[m_NumShaderTypes + ShaderInd]; } const ShaderResourceCacheVk& GetStaticResCache(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaders); + VERIFY_EXPR(ShaderInd < m_NumShaderTypes); return m_StaticResCaches[ShaderInd]; } ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaders); + VERIFY_EXPR(ShaderInd < m_NumShaderTypes); return m_StaticVarsMgrs[ShaderInd]; } @@ -150,14 +151,12 @@ private: // SRB memory allocator must be declared before m_pDefaultShaderResBinding SRBMemoryAllocator m_SRBMemAllocator; - std::array m_ShaderModules = {}; - VulkanUtilities::PipelineWrapper m_Pipeline; PipelineLayout m_PipelineLayout; // Resource layout index in m_ShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex; bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp index 026bb9da..85230b02 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp @@ -81,7 +81,7 @@ private: // Resource layout index in m_ShaderResourceCache array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; + std::array m_ResourceLayoutIndex; bool m_bStaticResourcesInitialized = false; Uint8 m_NumShaders = 0; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index a6d20641..28defd0f 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -115,6 +115,9 @@ namespace Diligent class ShaderResourceLayoutVk { public: + using ShaderStages_t = std::vector>; + using ShaderSPIRVs_t = std::vector>; + ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) : m_LogicalDevice{LogicalDevice} { @@ -131,23 +134,22 @@ public: // This method is called by PipelineStateVkImpl class instance to initialize static // shader resource layout and the cache - void InitializeStaticResourceLayout(std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderResourceCacheVk& StaticResourceCache); + void InitializeStaticResourceLayout(IShader* pShader, + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderResourceCacheVk& StaticResourceCache); // This method is called by PipelineStateVkImpl class instance to initialize resource // layouts for all shader stages in the pipeline. - static void Initialize(IRenderDevice* pRenderDevice, - Uint32 NumShaders, - ShaderResourceLayoutVk Layouts[], - std::shared_ptr pShaderResources[], - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - std::vector SPIRVs[], - class PipelineLayout& PipelineLayout, - bool VerifyVariables, - bool VerifyStaticSamplers); + static void Initialize(IRenderDevice* pRenderDevice, + const ShaderStages_t& ShaderStages, + ShaderResourceLayoutVk Layouts[], + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderSPIRVs_t& SPIRVs, + class PipelineLayout& PipelineLayout, + bool VerifyVariables, + bool VerifyStaticSamplers); // sizeof(VkResource) == 24 (x64) struct VkResource @@ -175,33 +177,21 @@ public: /* 7.5 */ const Uint32 VariableType : VariableTypeBits; /* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits; -/* 8 */ const SPIRVShaderResourceAttribs& SpirvAttribs; -/* 16 */ const ShaderResourceLayoutVk& ParentResLayout; - - VkResource(const ShaderResourceLayoutVk& _ParentLayout, - const SPIRVShaderResourceAttribs& _SpirvAttribs, - SHADER_RESOURCE_VARIABLE_TYPE _VariableType, - uint32_t _Binding, - uint32_t _DescriptorSet, - Uint32 _CacheOffset, - Uint32 _SamplerInd, - bool _ImmutableSamplerAssigned = false)noexcept : - Binding {static_cast(_Binding) }, - DescriptorSet {static_cast(_DescriptorSet)}, - CacheOffset {_CacheOffset }, - SamplerInd {_SamplerInd }, - VariableType {_VariableType }, - ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, - SpirvAttribs {_SpirvAttribs }, - ParentResLayout {_ParentLayout } - { - VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) ); - VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) ); - VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max() ); - VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); - } +/* 8 */ const SPIRVShaderResourceAttribs SpirvAttribs; +/* 16 */ const ShaderResourceLayoutVk& ParentResLayout; // clang-format on + VkResource(const ShaderResourceLayoutVk& _ParentLayout, + const SPIRVShaderResourceAttribs& _SpirvAttribs, + SHADER_RESOURCE_VARIABLE_TYPE _VariableType, + uint32_t _Binding, + uint32_t _DescriptorSet, + Uint32 _CacheOffset, + Uint32 _SamplerInd, + bool _ImmutableSamplerAssigned = false) noexcept; + + ~VkResource(); + // Checks if a resource is bound in ResourceCache at the given ArrayIndex bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const; @@ -279,11 +269,10 @@ public: #ifdef DILIGENT_DEVELOPMENT bool dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache) const; - static void dvpVerifyResourceLayoutDesc(Uint32 NumShaders, - const std::shared_ptr pShaderResources[], - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - bool VerifyVariables, - bool VerifyStaticSamplers); + static void dvpVerifyResourceLayoutDesc(const ShaderStages_t& ShaderStages, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + bool VerifyVariables, + bool VerifyStaticSamplers); #endif Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const @@ -300,13 +289,10 @@ public: const Char* GetShaderName() const { - return m_pResources->GetShaderName(); + return ""; // AZ TODO } - SHADER_TYPE GetShaderType() const - { - return m_pResources->GetShaderType(); - } + SHADER_TYPE GetShaderType() const { return m_ShaderType; } const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const { @@ -315,7 +301,7 @@ public: return Resources[GetResourceOffset(VarType, r)]; } - bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedSamplers(); } + bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; } private: Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const @@ -346,16 +332,12 @@ private: return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } - void AllocateMemory(std::shared_ptr pSrcResources, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - bool AllocateImmutableSamplers); - - Uint32 FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, - Uint32 CurrResourceCount, - SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const; + void AllocateMemory(IShader* pShader, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + bool AllocateImmutableSamplers); using ImmutableSamplerPtrType = RefCntAutoPtr; ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept @@ -366,16 +348,16 @@ private: } // clang-format off -/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; -/* 8 */ std::unique_ptr > m_ResourceBuffer; +/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; +/* 8 */ std::unique_ptr > m_ResourceBuffer; + +/*24 */ std::array m_NumResources = {}; - // We must use shared_ptr to reference ShaderResources instance, because - // there may be multiple objects referencing the same set of resources -/*24 */ std::shared_ptr m_pResources; +/*32 */ Uint32 m_NumImmutableSamplers = 0; +/*36 */ bool m_IsUsingSeparateSamplers = false; +/*37 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; -/*40 */ std::array m_NumResources = {}; -/*48 */ Uint32 m_NumImmutableSamplers = 0; -/*56*/ // End of class +/*40 */ // End of class // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp index dbba5b7e..1e6749f1 100644 --- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp +++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp @@ -82,4 +82,7 @@ ATTACHMENT_STORE_OP VkAttachmentStoreOpToAttachmentStoreOp(VkAttachmentStoreOp V VkPipelineStageFlags PipelineStageFlagsToVkPipelineStageFlags(PIPELINE_STAGE_FLAGS PipelineStageFlags); VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags); + +VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType); + } // namespace Diligent diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index 2fd063c9..6ed84171 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -40,28 +40,6 @@ namespace Diligent { - -static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType) -{ - static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type"); - switch (ShaderType) - { - // clang-format off - case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; - case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; - case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; - case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; - case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT; - case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; - case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV; - case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV; - // clang-format on - default: - UNEXPECTED("Unknown shader type"); - return VK_SHADER_STAGE_VERTEX_BIT; - } -} - class ResourceTypeToVkDescriptorType { public: diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 75dd3263..29d16239 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -129,352 +129,376 @@ RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc( return RPDesc; } -static std::vector StripReflection(const std::vector& OriginalSPIRV) +static bool StripReflection(std::vector& SPIRV) { #if DILIGENT_NO_HLSL - return OriginalSPIRV; + return false; #else std::vector StrippedSPIRV; spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0); // Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions // removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation. SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass()); - auto res = SpirvOptimizer.Run(OriginalSPIRV.data(), OriginalSPIRV.size(), &StrippedSPIRV); - if (!res) + if (SpirvOptimizer.Run(SPIRV.data(), SPIRV.size(), &StrippedSPIRV)) { - // Optimized SPIRV may be invalid - StrippedSPIRV.clear(); + SPIRV = std::move(StrippedSPIRV); + return true; } - return StrippedSPIRV; + else + return false; #endif } -PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, - RenderDeviceVkImpl* pDeviceVk, - const PipelineStateCreateInfo& CreateInfo) : - TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, - m_SRBMemAllocator{GetRawAllocator()} +static void InitializeShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, + const PipelineStateVkImpl::ShaderStages_t& ShaderStages, + PipelineStateVkImpl::ShaderSPIRVs_t& ShaderSPIRVs, + std::vector& ShaderModules, + std::vector& Stages) { - m_ResourceLayoutIndex.fill(-1); - - const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); + VERIFY_EXPR(ShaderStages.size() == ShaderSPIRVs.size()); - std::array, MAX_SHADERS_IN_PIPELINE> ShaderResources; - std::array, MAX_SHADERS_IN_PIPELINE> ShaderSPIRVs; - - // clang-format off - static_assert((sizeof(ShaderResourceLayoutVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutVk) is expected to be a multiple of sizeof(void*)"); - static_assert((sizeof(ShaderResourceCacheVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheVk) is expected to be a multiple of sizeof(void*)"); - static_assert((sizeof(ShaderVariableManagerVk) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerVk) is expected to be a multiple of sizeof(void*)"); - // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * m_NumShaders; - auto* const pRawMem = - ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk, ShaderResourceCacheVk, and ShaderVariableManagerVk arrays", MemSize); - - m_ShaderResourceLayouts = reinterpret_cast(pRawMem); - m_StaticResCaches = reinterpret_cast(m_ShaderResourceLayouts + m_NumShaders * 2); - m_StaticVarsMgrs = reinterpret_cast(m_StaticResCaches + m_NumShaders); - - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice}; - auto* pShaderVk = GetShader(s); - ShaderResources[s] = pShaderVk->GetShaderResources(); - ShaderSPIRVs[s] = pShaderVk->GetSPIRV(); - - const auto ShaderType = pShaderVk->GetDesc().ShaderType; - const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); - m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); - - auto* pStaticResLayout = new (m_ShaderResourceLayouts + m_NumShaders + s) ShaderResourceLayoutVk{LogicalDevice}; - auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources}; - pStaticResLayout->InitializeStaticResourceLayout(ShaderResources[s], GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); - - new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache}; - } - ShaderResourceLayoutVk::Initialize(pDeviceVk, m_NumShaders, m_ShaderResourceLayouts, ShaderResources.data(), GetRawAllocator(), - m_Desc.ResourceLayout, ShaderSPIRVs.data(), m_PipelineLayout, - (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, - (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); - m_PipelineLayout.Finalize(LogicalDevice); + auto* pShaderVk = ValidatedCast(ShaderStages[s].second); + auto& SPIRV = ShaderSPIRVs[s]; + const auto ShaderType = ShaderStages[s].first; - if (m_Desc.SRBAllocationGranularity > 1) - { - std::array ShaderVariableDataSizes = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) - { - const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; + VkPipelineShaderStageCreateInfo StageCI = {}; - Uint32 UnusedNumVars = 0; - ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars); - } - - Uint32 NumSets = 0; - auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets); - auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data()); - - m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderVariableDataSizes.data(), 1, &CacheMemorySize); - } - - // Create shader modules and initialize shader stages - std::array ShaderStages = {}; - for (Uint32 s = 0; s < m_NumShaders; ++s) - { - auto* pShaderVk = GetShader(s); - auto ShaderType = pShaderVk->GetDesc().ShaderType; - - auto& StageCI = ShaderStages[s]; StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; StageCI.pNext = nullptr; StageCI.flags = 0; // reserved for future use - switch (ShaderType) - { - // clang-format off - case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break; - case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break; - case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break; - case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break; - case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break; - case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break; - case SHADER_TYPE_AMPLIFICATION: StageCI.stage = VK_SHADER_STAGE_TASK_BIT_NV; break; - case SHADER_TYPE_MESH: StageCI.stage = VK_SHADER_STAGE_MESH_BIT_NV; break; - default: UNEXPECTED("Unknown shader type"); - // clang-format on - } + StageCI.stage = ShaderTypeToVkShaderStageFlagBit(ShaderType); VkShaderModuleCreateInfo ShaderModuleCI = {}; ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; ShaderModuleCI.pNext = nullptr; ShaderModuleCI.flags = 0; - const auto& SPIRV = ShaderSPIRVs[s]; // We have to strip reflection instructions to fix the follownig validation error: // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string // Optimizer also performs validation and may catch problems with the byte code. - auto StrippedSPIRV = StripReflection(SPIRV); - if (!StrippedSPIRV.empty()) - { - ShaderModuleCI.codeSize = StrippedSPIRV.size() * sizeof(uint32_t); - ShaderModuleCI.pCode = StrippedSPIRV.data(); - } - else - { + if (!StripReflection(SPIRV)) LOG_ERROR("Failed to strip reflection information from shader '", pShaderVk->GetDesc().Name, "'. This may indicate a problem with the byte code."); - ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t); - ShaderModuleCI.pCode = SPIRV.data(); - } - m_ShaderModules[s] = LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name); + ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t); + ShaderModuleCI.pCode = SPIRV.data(); + + ShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name)); - StageCI.module = m_ShaderModules[s]; + StageCI.module = ShaderModules.back(); StageCI.pName = pShaderVk->GetEntryPoint(); StageCI.pSpecializationInfo = nullptr; + + Stages.push_back(StageCI); } - // Create pipeline - if (m_Desc.IsComputePipeline()) - { - auto& ComputePipeline = m_Desc.ComputePipeline; + VERIFY_EXPR(ShaderModules.size() == Stages.size()); +} + + +static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& Desc, + VulkanUtilities::PipelineWrapper& Pipeline) +{ + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); + + VkComputePipelineCreateInfo PipelineCI = {}; + + PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; + PipelineCI.pNext = nullptr; +#ifdef DILIGENT_DEBUG + PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; +#endif + PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from + PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from - if (ComputePipeline.pCS == nullptr) - LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc"); + PipelineCI.stage = Stages[0]; + PipelineCI.layout = Layout.GetVkPipelineLayout(); - VkComputePipelineCreateInfo PipelineCI = {}; + Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, Desc.Name); +} + + +static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, + std::vector& Stages, + const PipelineLayout& Layout, + const PipelineStateDesc& Desc, + VulkanUtilities::PipelineWrapper& Pipeline, + RefCntAutoPtr& pRenderPass) +{ + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); + auto& GraphicsPipeline = Desc.GraphicsPipeline; + auto& RPCache = pDeviceVk->GetImplicitRenderPassCache(); + + if (pRenderPass == nullptr) + { + RenderPassCache::RenderPassCacheKey Key{ + GraphicsPipeline.NumRenderTargets, + GraphicsPipeline.SmplDesc.Count, + GraphicsPipeline.RTVFormats, + GraphicsPipeline.DSVFormat}; + pRenderPass = RPCache.GetRenderPass(Key); + } + + VkGraphicsPipelineCreateInfo PipelineCI = {}; - PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - PipelineCI.pNext = nullptr; + PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + PipelineCI.pNext = nullptr; #ifdef DILIGENT_DEBUG - PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; + PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; #endif - PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from - PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from - PipelineCI.stage = ShaderStages[0]; - PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout(); + PipelineCI.stageCount = static_cast(Stages.size()); + PipelineCI.pStages = Stages.data(); + PipelineCI.layout = Layout.GetVkPipelineLayout(); + + VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {}; + + std::array BindingDescriptions; + std::array AttributeDescription; + InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription); + PipelineCI.pVertexInputState = &VertexInputStateCI; - m_Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name); + + VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {}; + + InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; + InputAssemblyCI.pNext = nullptr; + InputAssemblyCI.flags = 0; // reserved for future use + InputAssemblyCI.primitiveRestartEnable = VK_FALSE; + PipelineCI.pInputAssemblyState = &InputAssemblyCI; + + + VkPipelineTessellationStateCreateInfo TessStateCI = {}; + + TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; + TessStateCI.pNext = nullptr; + TessStateCI.flags = 0; // reserved for future use + PipelineCI.pTessellationState = &TessStateCI; + + if (Desc.PipelineType == PIPELINE_TYPE_MESH) + { + // Input assembly is not used in the mesh pipeline, so topology may contain any value. + // Validation layers may generate a warning if point_list topology is used, so use MAX_ENUM value. + InputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM; + + // Vertex input state and tessellation state are ignored in a mesh pipeline and should be null. + PipelineCI.pVertexInputState = nullptr; + PipelineCI.pTessellationState = nullptr; } else { - const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); - auto& GraphicsPipeline = m_Desc.GraphicsPipeline; - auto& RPCache = pDeviceVk->GetImplicitRenderPassCache(); + PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints); + } - if (m_pRenderPass == nullptr) + VkPipelineViewportStateCreateInfo ViewPortStateCI = {}; + + ViewPortStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; + ViewPortStateCI.pNext = nullptr; + ViewPortStateCI.flags = 0; // reserved for future use + ViewPortStateCI.viewportCount = + GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used + // by the pipeline is still specified by the viewportCount member (23.5) + ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states + ViewPortStateCI.scissorCount = ViewPortStateCI.viewportCount; // the number of scissors must match the number of viewports (23.5) + // (why the hell it is in the struct then?) + VkRect2D ScissorRect = {}; + if (GraphicsPipeline.RasterizerDesc.ScissorEnable) + { + ViewPortStateCI.pScissors = nullptr; // Ignored if the scissor state is dynamic + } + else + { + const auto& Props = PhysicalDevice.GetProperties(); + // There are limitiations on the viewport width and height (23.5), but + // it is not clear if there are limitations on the scissor rect width and + // height + ScissorRect.extent.width = Props.limits.maxViewportDimensions[0]; + ScissorRect.extent.height = Props.limits.maxViewportDimensions[1]; + ViewPortStateCI.pScissors = &ScissorRect; + } + PipelineCI.pViewportState = &ViewPortStateCI; + + VkPipelineRasterizationStateCreateInfo RasterizerStateCI = + RasterizerStateDesc_To_VkRasterizationStateCI(GraphicsPipeline.RasterizerDesc); + PipelineCI.pRasterizationState = &RasterizerStateCI; + + // Multisample state (24) + VkPipelineMultisampleStateCreateInfo MSStateCI = {}; + + MSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; + MSStateCI.pNext = nullptr; + MSStateCI.flags = 0; // reserved for future use + // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of + // pMultisampleState must be the same as the sample count for those subpass attachments + MSStateCI.rasterizationSamples = static_cast(GraphicsPipeline.SmplDesc.Count); + MSStateCI.sampleShadingEnable = VK_FALSE; + MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE. + uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples + MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with + // the coverage information generated during rasterization (25.3) + MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on + // the alpha component of the fragment's first color output + MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one + PipelineCI.pMultisampleState = &MSStateCI; + + VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI = + DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc); + PipelineCI.pDepthStencilState = &DepthStencilStateCI; + + const auto& RPDesc = pRenderPass->GetDesc(); + const auto NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount; + VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments); + std::vector ColorBlendAttachmentStates(NumRTAttachments); + + VkPipelineColorBlendStateCreateInfo BlendStateCI = {}; + + BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr; + BlendStateCI.attachmentCount = NumRTAttachments; // must equal the colorAttachmentCount for the subpass + // in which this pipeline is used. + BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates); + PipelineCI.pColorBlendState = &BlendStateCI; + + + VkPipelineDynamicStateCreateInfo DynamicStateCI = {}; + + DynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; + DynamicStateCI.pNext = nullptr; + DynamicStateCI.flags = 0; // reserved for future use + std::vector DynamicStates = { - RenderPassCache::RenderPassCacheKey Key{ - GraphicsPipeline.NumRenderTargets, - GraphicsPipeline.SmplDesc.Count, - GraphicsPipeline.RTVFormats, - GraphicsPipeline.DSVFormat}; - m_pRenderPass = RPCache.GetRenderPass(Key); - } + VK_DYNAMIC_STATE_VIEWPORT, // pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be + // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports + // used by a pipeline is still specified by the viewportCount member of + // VkPipelineViewportStateCreateInfo. - VkGraphicsPipelineCreateInfo PipelineCI = {}; + VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored + // and must be set dynamically with vkCmdSetBlendConstants - PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - PipelineCI.pNext = nullptr; -#ifdef DILIGENT_DEBUG - PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT; -#endif + VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo + // for both front and back will be ignored and must be set dynamically + // with vkCmdSetStencilReference + }; - PipelineCI.stageCount = m_NumShaders; - PipelineCI.pStages = ShaderStages.data(); - PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout(); + if (GraphicsPipeline.RasterizerDesc.ScissorEnable) + { + // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set + // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles + // used by a pipeline is still specified by the scissorCount member of + // VkPipelineViewportStateCreateInfo. + DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR); + } + DynamicStateCI.dynamicStateCount = static_cast(DynamicStates.size()); + DynamicStateCI.pDynamicStates = DynamicStates.data(); + PipelineCI.pDynamicState = &DynamicStateCI; - VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {}; - std::array BindingDescriptions; - std::array AttributeDescription; - InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription); - PipelineCI.pVertexInputState = &VertexInputStateCI; + PipelineCI.renderPass = pRenderPass.RawPtr()->GetVkRenderPass(); + PipelineCI.subpass = Desc.GraphicsPipeline.SubpassIndex; + PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from + PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from + Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, Desc.Name); +} - VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {}; - InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - InputAssemblyCI.pNext = nullptr; - InputAssemblyCI.flags = 0; // reserved for future use - InputAssemblyCI.primitiveRestartEnable = VK_FALSE; - PipelineCI.pInputAssemblyState = &InputAssemblyCI; +PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVk, + const PipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + m_ResourceLayoutIndex.fill(-1); + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); - VkPipelineTessellationStateCreateInfo TessStateCI = {}; + ShaderStages_t ShaderStages; + ShaderSPIRVs_t ShaderSPIRVs; + ExtractShaders(ShaderStages); - TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO; - TessStateCI.pNext = nullptr; - TessStateCI.flags = 0; // reserved for future use - PipelineCI.pTessellationState = &TessStateCI; + ShaderSPIRVs.resize(ShaderStages.size()); + for (size_t s = 0; s < ShaderSPIRVs.size(); ++s) + { + auto* pShaderVk = ValidatedCast(ShaderStages[s].second); + ShaderSPIRVs[s] = pShaderVk->GetSPIRV(); + } - if (m_Desc.PipelineType == PIPELINE_TYPE_MESH) - { - // Input assembly is not used in the mesh pipeline, so topology may contain any value. - // Validation layers may generate a warning if point_list topology is used, so use MAX_ENUM value. - InputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM; + // clang-format off + static_assert((sizeof(ShaderResourceLayoutVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutVk) is expected to be a multiple of sizeof(void*)"); + static_assert((sizeof(ShaderResourceCacheVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheVk) is expected to be a multiple of sizeof(void*)"); + static_assert((sizeof(ShaderVariableManagerVk) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerVk) is expected to be a multiple of sizeof(void*)"); + // clang-format on + const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * GetNumShaderTypes(); + auto* const pRawMem = + ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk, ShaderResourceCacheVk, and ShaderVariableManagerVk arrays", MemSize); - // Vertex input state and tessellation state are ignored in a mesh pipeline and should be null. - PipelineCI.pVertexInputState = nullptr; - PipelineCI.pTessellationState = nullptr; - } - else - { - PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints); - } + m_ShaderResourceLayouts = reinterpret_cast(pRawMem); + m_StaticResCaches = reinterpret_cast(m_ShaderResourceLayouts + GetNumShaderTypes() * 2); + m_StaticVarsMgrs = reinterpret_cast(m_StaticResCaches + GetNumShaderTypes()); - VkPipelineViewportStateCreateInfo ViewPortStateCI = {}; - - ViewPortStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - ViewPortStateCI.pNext = nullptr; - ViewPortStateCI.flags = 0; // reserved for future use - ViewPortStateCI.viewportCount = - GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used - // by the pipeline is still specified by the viewportCount member (23.5) - ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states - ViewPortStateCI.scissorCount = ViewPortStateCI.viewportCount; // the number of scissors must match the number of viewports (23.5) - // (why the hell it is in the struct then?) - VkRect2D ScissorRect = {}; - if (GraphicsPipeline.RasterizerDesc.ScissorEnable) - { - ViewPortStateCI.pScissors = nullptr; // Ignored if the scissor state is dynamic - } - else - { - const auto& Props = PhysicalDevice.GetProperties(); - // There are limitiations on the viewport width and height (23.5), but - // it is not clear if there are limitations on the scissor rect width and - // height - ScissorRect.extent.width = Props.limits.maxViewportDimensions[0]; - ScissorRect.extent.height = Props.limits.maxViewportDimensions[1]; - ViewPortStateCI.pScissors = &ScissorRect; - } - PipelineCI.pViewportState = &ViewPortStateCI; - - VkPipelineRasterizationStateCreateInfo RasterizerStateCI = - RasterizerStateDesc_To_VkRasterizationStateCI(GraphicsPipeline.RasterizerDesc); - PipelineCI.pRasterizationState = &RasterizerStateCI; - - // Multisample state (24) - VkPipelineMultisampleStateCreateInfo MSStateCI = {}; - - MSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - MSStateCI.pNext = nullptr; - MSStateCI.flags = 0; // reserved for future use - // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of - // pMultisampleState must be the same as the sample count for those subpass attachments - MSStateCI.rasterizationSamples = static_cast(GraphicsPipeline.SmplDesc.Count); - MSStateCI.sampleShadingEnable = VK_FALSE; - MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE. - uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples - MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with - // the coverage information generated during rasterization (25.3) - MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on - // the alpha component of the fragment's first color output - MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one - PipelineCI.pMultisampleState = &MSStateCI; - - VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI = - DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc); - PipelineCI.pDepthStencilState = &DepthStencilStateCI; - - const auto& RPDesc = m_pRenderPass->GetDesc(); - const auto NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount; - VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments); - std::vector ColorBlendAttachmentStates(NumRTAttachments); - - VkPipelineColorBlendStateCreateInfo BlendStateCI = {}; - - BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr; - BlendStateCI.attachmentCount = NumRTAttachments; // must equal the colorAttachmentCount for the subpass - // in which this pipeline is used. - BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates); - PipelineCI.pColorBlendState = &BlendStateCI; - - - VkPipelineDynamicStateCreateInfo DynamicStateCI = {}; - - DynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - DynamicStateCI.pNext = nullptr; - DynamicStateCI.flags = 0; // reserved for future use - std::vector DynamicStates = - { - VK_DYNAMIC_STATE_VIEWPORT, // pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be - // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports - // used by a pipeline is still specified by the viewportCount member of - // VkPipelineViewportStateCreateInfo. + for (size_t s = 0; s < ShaderStages.size(); ++s) + { + new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice}; + + const auto ShaderType = ShaderStages[s].first; + auto& Shaders = ShaderStages[s].second; + const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); + m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); - VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored - // and must be set dynamically with vkCmdSetBlendConstants + auto* pStaticResLayout = new (m_ShaderResourceLayouts + ShaderStages.size() + s) ShaderResourceLayoutVk{LogicalDevice}; + auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources}; + pStaticResLayout->InitializeStaticResourceLayout(Shaders, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); - VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo - // for both front and back will be ignored and must be set dynamically - // with vkCmdSetStencilReference - }; + new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache}; + } + ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(), + m_Desc.ResourceLayout, ShaderSPIRVs, m_PipelineLayout, + (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, + (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); + m_PipelineLayout.Finalize(LogicalDevice); - if (GraphicsPipeline.RasterizerDesc.ScissorEnable) + if (m_Desc.SRBAllocationGranularity > 1) + { + std::array ShaderVariableDataSizes = {}; + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { - // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set - // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles - // used by a pipeline is still specified by the scissorCount member of - // VkPipelineViewportStateCreateInfo. - DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR); + const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; + + Uint32 UnusedNumVars = 0; + ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars); } - DynamicStateCI.dynamicStateCount = static_cast(DynamicStates.size()); - DynamicStateCI.pDynamicStates = DynamicStates.data(); - PipelineCI.pDynamicState = &DynamicStateCI; + Uint32 NumSets = 0; + auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets); + auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data()); + + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderTypes(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize); + } - PipelineCI.renderPass = GetRenderPass()->GetVkRenderPass(); - PipelineCI.subpass = m_Desc.GraphicsPipeline.SubpassIndex; - PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from - PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from + // Create shader modules and initialize shader stages + std::vector VkShaderStages; + std::vector ShaderModules; + InitializeShaderStages(LogicalDevice, ShaderStages, ShaderSPIRVs, ShaderModules, VkShaderStages); - m_Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name); + // Create pipeline + switch (m_Desc.PipelineType) + { + // clang-format off + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: CreateGraphicsPipeline( pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline, m_pRenderPass); break; + case PIPELINE_TYPE_COMPUTE: CreateComputePipeline( pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); break; + default: UNEXPECTED("unknown pipeline type"); + // clang-format on } m_HasStaticResources = false; m_HasNonStaticResources = false; - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { const auto& Layout = m_ShaderResourceLayouts[s]; if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_STATIC) != 0) @@ -493,21 +517,13 @@ PipelineStateVkImpl::~PipelineStateVkImpl() m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask); m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask); - for (auto& ShaderModule : m_ShaderModules) - { - if (ShaderModule != VK_NULL_HANDLE) - { - m_pDevice->SafeReleaseDeviceObject(std::move(ShaderModule), m_Desc.CommandQueueMask); - } - } - auto& RawAllocator = GetRawAllocator(); - for (Uint32 s = 0; s < m_NumShaders * 2; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes() * 2; ++s) { m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); } - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { m_StaticResCaches[s].~ShaderResourceCacheVk(); m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); @@ -547,27 +563,27 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const #ifdef DILIGENT_DEBUG { bool IsCompatibleShaders = true; - if (m_NumShaders != pPSOVk->m_NumShaders) + if (GetNumShaderTypes() != pPSOVk->GetNumShaderTypes()) IsCompatibleShaders = false; if (IsCompatibleShaders) { - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { - auto* pShader0 = GetShader(s); - auto* pShader1 = pPSOVk->GetShader(s); - if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType) + if (GetShaderTypes()[s] != pPSOVk->GetShaderTypes()[s]) { IsCompatibleShaders = false; break; } - const auto* pRes0 = pShader0->GetShaderResources().get(); + + // AZ TODO + /*const auto* pRes0 = pShader0->GetShaderResources().get(); const auto* pRes1 = pShader1->GetShaderResources().get(); if (!pRes0->IsCompatibleWith(*pRes1)) { IsCompatibleShaders = false; break; - } + }*/ } } @@ -621,7 +637,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind auto& ResourceCache = pResBindingVkImpl->GetResourceCache(); #ifdef DILIGENT_DEVELOPMENT - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { m_ShaderResourceLayouts[s].dvpVerifyBindings(ResourceCache); } @@ -656,7 +672,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind // Allocate vulkan descriptor set for dynamic resources DynamicDescrSet = pCtxVkImpl->AllocateDynamicDescriptorSet(DynamicDescriptorSetVkLayout, DynamicDescrSetName); // Commit all dynamic resource descriptors - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { const auto& Layout = m_ShaderResourceLayouts[s]; if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0) @@ -673,7 +689,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind void PipelineStateVkImpl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) { - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { auto ShaderType = GetStaticShaderResLayout(s).GetShaderType(); if ((ShaderType & ShaderFlags) != 0) @@ -717,17 +733,17 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const { - for (Uint32 s = 0; s < m_NumShaders; ++s) + for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) { const auto& StaticResLayout = GetStaticShaderResLayout(s); const auto& StaticResCache = GetStaticResCache(s); + #ifdef DILIGENT_DEVELOPMENT if (!StaticResLayout.dvpVerifyBindings(StaticResCache)) { - const auto* pShaderVk = GetShader(s); LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", GetDesc().Name, "' will not be successfully initialized because not all static resource bindings in shader '", - pShaderVk->GetDesc().Name, + GetShaderTypeLiteralName(GetShaderTypes()[s]), "' 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."); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 53a92a59..75f3bb37 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -49,8 +49,8 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR { m_ResourceLayoutIndex.fill(-1); - auto* ppShaders = pPSO->GetShaders(); - m_NumShaders = static_cast(pPSO->GetNumShaders()); + auto* pShaderTypes = pPSO->GetShaderTypes(); + m_NumShaders = static_cast(pPSO->GetNumShaderTypes()); auto* pRenderDeviceVkImpl = pPSO->GetDevice(); // This will only allocate memory and initialize descriptor sets in the resource cache @@ -62,9 +62,7 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR for (Uint32 s = 0; s < m_NumShaders; ++s) { - auto* pShader = ppShaders[s]; - auto ShaderType = pShader->GetDesc().ShaderType; - auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType); + auto ShaderInd = GetShaderTypePipelineIndex(pShaderTypes[s], pPSO->GetDesc().PipelineType); m_ResourceLayoutIndex[ShaderInd] = static_cast(s); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 4f28af80..1f798eb9 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -103,36 +103,40 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk() GetImmutableSampler(s).~ImmutableSamplerPtrType(); } -void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr pSrcResources, - IMemoryAllocator& Allocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - bool AllocateImmutableSamplers) +void ShaderResourceLayoutVk::AllocateMemory(IShader* pShader, + IMemoryAllocator& Allocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes, + bool AllocateImmutableSamplers) { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); - VERIFY_EXPR(!m_pResources); - VERIFY_EXPR(pSrcResources); + VERIFY_EXPR(pShader != nullptr); + VERIFY_EXPR(m_ShaderType == SHADER_TYPE_UNKNOWN); - m_pResources = std::move(pSrcResources); - - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - const auto ShaderType = m_pResources->GetShaderType(); - const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + m_ShaderType = pShader->GetDesc().ShaderType; // Count the number of resources to allocate all needed memory - m_pResources->ProcessResources( - [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // - { - auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); - if (IsAllowedType(VarType, AllowedTypeBits)) + { + auto* pShaderVk = ValidatedCast(pShader); + auto pResources = pShaderVk->GetShaderResources(); + const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); + VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType); + pResources->ProcessResources( + [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { - // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app + auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); + if (IsAllowedType(VarType, AllowedTypeBits)) + { + // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app - VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits::max()}, "Number of resources exceeds Uint16 maximum representable value"); - ++m_NumResources[VarType]; - } - } // - ); + VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits::max()}, "Number of resources exceeds Uint16 maximum representable value"); + ++m_NumResources[VarType]; + } + } // + ); + m_IsUsingSeparateSamplers = !pResources->IsUsingCombinedSamplers(); + } Uint32 TotalResources = 0; for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) @@ -148,7 +152,7 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderResourceCacheVk& StaticResourceCache) +Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, + const SPIRVShaderResources& Resources, + const SPIRVShaderResourceAttribs& SepImg, + Uint32 CurrResourceCount, + SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) +{ + using VkResource = ShaderResourceLayoutVk::VkResource; + VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); + + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + if (Resources.IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned()) + { + const auto& SepSampler = Resources.GetAssignedSepSampler(SepImg); + for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd) + { + const auto& Res = Layout.GetResource(ImgVarType, SamplerInd); + if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && + strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0) + { + VERIFY(ImgVarType == Res.GetVariableType(), + "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name, + "' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()), + ") of the separate sampler '", SepSampler.Name, + "' that is assigned to it. " + "This should never happen as when HLSL-style combined texture samplers are used, the type of the sampler " + "is derived from the type of the corresponding separate image."); + break; + } + } + if (SamplerInd == CurrResourceCount) + { + LOG_ERROR("Unable to find separate sampler '", SepSampler.Name, "' assigned to separate image '", SepImg.Name, "' in the list of already created resources. This seems to be a bug."); + SamplerInd = VkResource::InvalidSamplerInd; + } + } + return SamplerInd; +} + + +void ShaderResourceLayoutVk::InitializeStaticResourceLayout(IShader* pShader, + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderResourceCacheVk& StaticResourceCache) { const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; // We do not need immutable samplers in static shader resource layout as they // are relevant only when the main layout is initialized constexpr bool AllocateImmutableSamplers = false; - AllocateMemory(std::move(pSrcResources), LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers); + AllocateMemory(pShader, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers); std::array CurrResInd = {}; Uint32 StaticResCacheSize = 0; - const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - const auto ShaderType = m_pResources->GetShaderType(); - const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); + const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); - m_pResources->ProcessResources( - [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // - { - auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); - if (!IsAllowedType(VarType, AllowedTypeBits)) - return; + { + auto* pShaderVk = ValidatedCast(pShader); + auto pResources = pShaderVk->GetShaderResources(); + const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); - Int32 SrcImmutableSamplerInd = -1; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + pResources->ProcessResources( + [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // { - // Only search for the immutable sampler for combined image samplers and separate samplers - SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); - // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app - } + auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); + if (!IsAllowedType(VarType, AllowedTypeBits)) + return; - Uint32 Binding = Attribs.Type; - Uint32 DescriptorSet = 0; - Uint32 CacheOffset = StaticResCacheSize; - StaticResCacheSize += Attribs.ArraySize; + Int32 SrcImmutableSamplerInd = -1; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) + { + // Only search for the immutable sampler for combined image samplers and separate samplers + SrcImmutableSamplerInd = FindImmutableSampler(m_ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); + // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app + } - Uint32 SamplerInd = VkResource::InvalidSamplerInd; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) - { - // Separate samplers are enumerated before separate images, so the sampler - // assigned to this separate image must have already been created. - SamplerInd = FindAssignedSampler(Attribs, CurrResInd[VarType], VarType); - } - ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); - } // - ); + Uint32 Binding = Attribs.Type; + Uint32 DescriptorSet = 0; + Uint32 CacheOffset = StaticResCacheSize; + StaticResCacheSize += Attribs.ArraySize; + + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + { + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must have already been created. + SamplerInd = FindAssignedSampler(*this, *pResources, Attribs, CurrResInd[VarType], VarType); + } + ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); + } // + ); + } #ifdef DILIGENT_DEBUG for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) @@ -235,25 +282,24 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr pShaderResources[], - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - bool VerifyVariables, - bool VerifyStaticSamplers) +void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const ShaderStages_t& ShaderStages, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + bool VerifyVariables, + bool VerifyStaticSamplers) { - auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) // + auto GetAllowedShadersString = [&](SHADER_TYPE Stages) // { std::string ShadersStr; - while (ShaderStages != SHADER_TYPE_UNKNOWN) + while (Stages != SHADER_TYPE_UNKNOWN) { - const auto ShaderType = ShaderStages & static_cast(~(static_cast(ShaderStages) - 1)); + const auto ShaderType = Stages & static_cast(~(static_cast(Stages) - 1)); const char* ShaderName = nullptr; - for (Uint32 s = 0; s < NumShaders; ++s) + + for (size_t s = 0; s < ShaderStages.size(); ++s) { - const auto& Resources = *pShaderResources[s]; - if ((ShaderStages & Resources.GetShaderType()) != 0) + if ((Stages & ShaderStages[s].first) != 0) { - ShaderName = Resources.GetShaderName(); + ShaderName = ShaderStages[s].second->GetDesc().Name; break; } } @@ -274,7 +320,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 } ShadersStr.append(")"); - ShaderStages &= ~ShaderType; + Stages &= ~ShaderType; } return ShadersStr; }; @@ -291,9 +337,10 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 } bool VariableFound = false; - for (Uint32 s = 0; s < NumShaders && !VariableFound; ++s) + for (size_t s = 0; s < ShaderStages.size() && !VariableFound; ++s) { - const auto& Resources = *pShaderResources[s]; + const auto* pShaderVk = ValidatedCast(ShaderStages[s].second); + const auto& Resources = *pShaderVk->GetShaderResources(); if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) { for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) @@ -324,9 +371,10 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 } bool SamplerFound = false; - for (Uint32 s = 0; s < NumShaders && !SamplerFound; ++s) + for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s) { - const auto& Resources = *pShaderResources[s]; + const auto* pShaderVk = ValidatedCast(ShaderStages[s].second); + const auto& Resources = *pShaderVk->GetShaderResources(); if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0) continue; @@ -363,32 +411,31 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 } #endif -void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice, - Uint32 NumShaders, - ShaderResourceLayoutVk Layouts[], - std::shared_ptr pShaderResources[], - IMemoryAllocator& LayoutDataAllocator, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - std::vector SPIRVs[], - class PipelineLayout& PipelineLayout, - bool VerifyVariables, - bool VerifyStaticSamplers) +void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice, + const ShaderStages_t& ShaderStages, + ShaderResourceLayoutVk Layouts[], + IMemoryAllocator& LayoutDataAllocator, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + ShaderSPIRVs_t& SPIRVs, + class PipelineLayout& PipelineLayout, + bool VerifyVariables, + bool VerifyStaticSamplers) { #ifdef DILIGENT_DEVELOPMENT - dvpVerifyResourceLayoutDesc(NumShaders, pShaderResources, ResourceLayoutDesc, VerifyVariables, VerifyStaticSamplers); + dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyStaticSamplers); #endif - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; - const Uint32 NumAllowedTypes = 0; - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; + const Uint32 NumAllowedTypes = 0; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + constexpr bool AllocateImmutableSamplers = true; - for (Uint32 s = 0; s < NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - constexpr bool AllocateImmutableSamplers = true; - Layouts[s].AllocateMemory(std::move(pShaderResources[s]), LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers); + Layouts[s].AllocateMemory(ShaderStages[s].second, LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers); } - VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE); + //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE); std::array, MAX_SHADERS_IN_PIPELINE> CurrResInd = {}; std::array CurrImmutableSamplerInd = {}; #ifdef DILIGENT_DEBUG @@ -414,7 +461,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* { // Separate samplers are enumerated before separate images, so the sampler // assigned to this separate image must have already been created. - SamplerInd = ResLayout.FindAssignedSampler(Attribs, CurrResInd[ShaderInd][VarType], VarType); + SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType); } VkSampler vkImmutableSampler = VK_NULL_HANDLE; @@ -454,42 +501,48 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* }; // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set - for (Uint32 s = 0; s < NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& Layout = Layouts[s]; - const auto& Resources = *Layout.m_pResources; + auto& pShader = ShaderStages[s].second; + auto& Layout = Layouts[s]; + auto* pShaderVk = ValidatedCast(pShader); + auto& Resources = *pShaderVk->GetShaderResources(); for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n) { const auto& UB = Resources.GetUB(n); auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc); if (IsAllowedType(VarType, AllowedTypeBits)) { - AddResource(s, Layout, Resources, UB); + AddResource(static_cast(s), Layout, Resources, UB); } } } // Second, process all storage buffers - for (Uint32 s = 0; s < NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& Layout = Layouts[s]; - const auto& Resources = *Layout.m_pResources; + auto& pShader = ShaderStages[s].second; + auto& Layout = Layouts[s]; + auto* pShaderVk = ValidatedCast(pShader); + auto& Resources = *pShaderVk->GetShaderResources(); for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n) { const auto& SB = Resources.GetSB(n); auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc); if (IsAllowedType(VarType, AllowedTypeBits)) { - AddResource(s, Layout, Resources, SB); + AddResource(static_cast(s), Layout, Resources, SB); } } } // Finally, process all other resource types - for (Uint32 s = 0; s < NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& Layout = Layouts[s]; - const auto& Resources = *Layout.m_pResources; + auto& pShader = ShaderStages[s].second; + auto& Layout = Layouts[s]; + auto* pShaderVk = ValidatedCast(pShader); + auto& Resources = *pShaderVk->GetShaderResources(); // clang-format off Resources.ProcessResources( [&](const SPIRVShaderResourceAttribs& UB, Uint32) @@ -505,39 +558,39 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* [&](const SPIRVShaderResourceAttribs& Img, Uint32) { VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer); - AddResource(s, Layout, Resources, Img); + AddResource(static_cast(s), Layout, Resources, Img); }, [&](const SPIRVShaderResourceAttribs& SmplImg, Uint32) { VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); - AddResource(s, Layout, Resources, SmplImg); + AddResource(static_cast(s), Layout, Resources, SmplImg); }, [&](const SPIRVShaderResourceAttribs& AC, Uint32) { VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter); - AddResource(s, Layout, Resources, AC); + AddResource(static_cast(s), Layout, Resources, AC); }, [&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32) { VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler); - AddResource(s, Layout, Resources, SepSmpl); + AddResource(static_cast(s), Layout, Resources, SepSmpl); }, [&](const SPIRVShaderResourceAttribs& SepImg, Uint32) { VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer); - AddResource(s, Layout, Resources, SepImg); + AddResource(static_cast(s), Layout, Resources, SepImg); }, [&](const SPIRVShaderResourceAttribs& InputAtt, Uint32) { VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment); - AddResource(s, Layout, Resources, InputAtt); + AddResource(static_cast(s), Layout, Resources, InputAtt); } ); // clang-format on } #ifdef DILIGENT_DEBUG - for (Uint32 s = 0; s < NumShaders; ++s) + for (size_t s = 0; s < ShaderStages.size(); ++s) { auto& Layout = Layouts[s]; for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) @@ -551,41 +604,40 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* } -Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg, - Uint32 CurrResourceCount, - SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const +ShaderResourceLayoutVk::VkResource::VkResource(const ShaderResourceLayoutVk& _ParentLayout, + const SPIRVShaderResourceAttribs& _SpirvAttribs, + SHADER_RESOURCE_VARIABLE_TYPE _VariableType, + uint32_t _Binding, + uint32_t _DescriptorSet, + Uint32 _CacheOffset, + Uint32 _SamplerInd, + bool _ImmutableSamplerAssigned) noexcept : + // clang-format off + Binding {static_cast(_Binding) }, + DescriptorSet {static_cast(_DescriptorSet)}, + CacheOffset {_CacheOffset }, + SamplerInd {_SamplerInd }, + VariableType {_VariableType }, + ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, + SpirvAttribs {_SpirvAttribs }, + ParentResLayout {_ParentLayout } +// clang-format on { - VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); - - Uint32 SamplerInd = VkResource::InvalidSamplerInd; - if (m_pResources->IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned()) - { - const auto& SepSampler = m_pResources->GetAssignedSepSampler(SepImg); - for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd) - { - const auto& Res = GetResource(ImgVarType, SamplerInd); - if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler && - strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0) - { - VERIFY(ImgVarType == Res.GetVariableType(), - "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name, - "' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()), - ") of the separate sampler '", SepSampler.Name, - "' that is assigned to it. " - "This should never happen as when HLSL-style combined texture samplers are used, the type of the sampler " - "is derived from the type of the corresponding separate image."); - break; - } - } - if (SamplerInd == CurrResourceCount) - { - LOG_ERROR("Unable to find separate sampler '", SepSampler.Name, "' assigned to separate image '", SepImg.Name, "' in the list of already created resources. This seems to be a bug."); - SamplerInd = VkResource::InvalidSamplerInd; - } - } - return SamplerInd; + VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits)); + VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits)); + VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max()); + VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); + + const size_t Size = strlen(SpirvAttribs.Name) + 1; + char* NameCopy = ALLOCATE(GetRawAllocator(), "SPIRV Attribs Name", char, Size); + std::memcpy(NameCopy, SpirvAttribs.Name, Size); + const_cast(SpirvAttribs).Name = NameCopy; } +ShaderResourceLayoutVk::VkResource::~VkResource() +{ + FREE(GetRawAllocator(), const_cast(SpirvAttribs.Name)); +} void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, uint32_t ArrayElement, @@ -1017,7 +1069,7 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou { auto NumStaticResources = m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC]; VERIFY(NumStaticResources == SrcLayout.m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC], "Inconsistent number of static resources"); - VERIFY(SrcLayout.m_pResources->GetShaderType() == m_pResources->GetShaderType(), "Incosistent shader types"); + VERIFY(SrcLayout.GetShaderType() == GetShaderType(), "Incosistent shader types"); // Static shader resources are stored in one large continuous descriptor set for (Uint32 r = 0; r < NumStaticResources; ++r) diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index fb151407..95261295 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1511,4 +1511,27 @@ VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags) } #undef ASSERT_SAME + +VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType) +{ + static_assert(SHADER_TYPE_LAST == SHADER_TYPE_MESH, "Please update the switch below to handle the new shader type"); + VERIFY((ShaderType & (ShaderType - 1)) == 0, "More than one shader type specified"); + switch (ShaderType) + { + // clang-format off + case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT; + case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; + case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; + case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT; + case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT; + case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT; + case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV; + case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV; + // clang-format on + default: + UNEXPECTED("Unknown shader type"); + return VK_SHADER_STAGE_VERTEX_BIT; + } +} + } // namespace Diligent diff --git a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp index 5c35de33..b7c96523 100644 --- a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp +++ b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp @@ -78,7 +78,7 @@ struct SPIRVShaderResourceAttribs static constexpr const Uint32 InvalidSepSmplrOrImgInd = static_cast(-1); -/* 0 */const char* const Name; +/* 0 */const char* Name; /* 8 */const Uint16 ArraySize; /* 10 */const ResourceType Type; /* 11 */ // unused -- cgit v1.2.3 From e92a0a857a85fad049646dd78d4f742d245cc9cd Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 8 Oct 2020 21:48:49 +0300 Subject: Some minor fixes --- Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp | 6 +++--- Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp | 2 +- Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp | 2 +- Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp | 2 ++ Graphics/ShaderTools/src/SPIRVShaderResources.cpp | 7 ++++++- 5 files changed, 13 insertions(+), 6 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp index e01178a5..9976d014 100644 --- a/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/DeviceContextVkImpl.hpp @@ -135,13 +135,13 @@ public: ITextureView* pDepthStencil, RESOURCE_STATE_TRANSITION_MODE StateTransitionMode) override final; - /// Implementation of IDeviceContext::BeginRenderPass() in Direct3D11 backend. + /// Implementation of IDeviceContext::BeginRenderPass() in Vulkan backend. virtual void DILIGENT_CALL_TYPE BeginRenderPass(const BeginRenderPassAttribs& Attribs) override final; - /// Implementation of IDeviceContext::NextSubpass() in Direct3D11 backend. + /// Implementation of IDeviceContext::NextSubpass() in Vulkan backend. virtual void DILIGENT_CALL_TYPE NextSubpass() override final; - /// Implementation of IDeviceContext::EndRenderPass() in Direct3D11 backend. + /// Implementation of IDeviceContext::EndRenderPass() in Vulkan backend. virtual void DILIGENT_CALL_TYPE EndRenderPass() override final; // clang-format off diff --git a/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp index f449d416..23097d22 100644 --- a/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/FramebufferVkImpl.hpp @@ -40,7 +40,7 @@ namespace Diligent class FixedBlockMemoryAllocator; -/// Render pass implementation in Direct3D11 backend. +/// Framebuffer implementation in Vulkan backend. class FramebufferVkImpl final : public FramebufferBase { public: diff --git a/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp index 5c77784f..05962047 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderPassVkImpl.hpp @@ -41,7 +41,7 @@ namespace Diligent class FixedBlockMemoryAllocator; -/// Render pass implementation in Direct3D11 backend. +/// Render pass implementation in Vulkan backend. class RenderPassVkImpl final : public RenderPassBase { public: diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index c36b98b0..f6e337c2 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -100,6 +100,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, }, EngineCI.MainDescriptorPoolSize.MaxDescriptorSets, true @@ -120,6 +121,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* //{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors}, {VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors}, + {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors}, }, EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets, false // Pools can only be reset diff --git a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp index 876858ae..be683d53 100644 --- a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp +++ b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp @@ -582,6 +582,7 @@ void SPIRVShaderResources::Initialize(IMemoryAllocator& Allocator, VERIFY_EXPR(GetNumACs() == Counters.NumACs); VERIFY_EXPR(GetNumSepSmplrs() == Counters.NumSepSmplrs); VERIFY_EXPR(GetNumSepImgs() == Counters.NumSepImgs); + VERIFY_EXPR(GetNumInptAtts() == Counters.NumInptAtts); // clang-format on if (MemorySize) @@ -618,6 +619,9 @@ SPIRVShaderResources::~SPIRVShaderResources() for (Uint32 n = 0; n < GetNumSepImgs(); ++n) GetSepImg(n).~SPIRVShaderResourceAttribs(); + for (Uint32 n = 0; n < GetNumInptAtts(); ++n) + GetInptAtt(n).~SPIRVShaderResourceAttribs(); + for (Uint32 n = 0; n < GetNumShaderStageInputs(); ++n) GetShaderStageInputAttribs(n).~SPIRVShaderStageInputAttribs(); } @@ -748,7 +752,8 @@ bool SPIRVShaderResources::IsCompatibleWith(const SPIRVShaderResources& Resource GetNumSmpldImgs() != Resources.GetNumSmpldImgs() || GetNumACs() != Resources.GetNumACs() || GetNumSepImgs() != Resources.GetNumSepImgs() || - GetNumSepSmplrs() != Resources.GetNumSepSmplrs()) + GetNumSepSmplrs() != Resources.GetNumSepSmplrs() || + GetNumInptAtts() != Resources.GetNumInptAtts()) return false; // clang-format on VERIFY_EXPR(GetTotalResources() == Resources.GetTotalResources()); -- cgit v1.2.3 From 998165f350cfd8ae6bd9cbf6fc812874c1c3c3da Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 8 Oct 2020 22:14:06 +0300 Subject: Revert some changes in ShaderResourceLayoutVk, fixed PSO comparison --- .../include/ShaderResourceLayoutD3D12.hpp | 2 + .../src/PipelineStateD3D12Impl.cpp | 10 +- .../src/PipelineStateGLImpl.cpp | 18 ++-- .../include/ShaderResourceLayoutVk.hpp | 65 +++++++----- .../src/PipelineStateVkImpl.cpp | 11 +- .../src/ShaderResourceLayoutVk.cpp | 115 +++++++-------------- .../ShaderTools/include/SPIRVShaderResources.hpp | 2 +- 7 files changed, 100 insertions(+), 123 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp index e043cf4a..5426d98b 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp @@ -273,6 +273,8 @@ public: SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); } + const ShaderResourcesD3D12& GetResources() const { return *m_pResources; } + private: const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv) const; D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index d5958ea8..3e8673d5 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -489,14 +489,14 @@ bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState* pPSO) const IsCompatibleShaders = false; break; } - // AZ TODO - /*const ShaderResourcesD3D12* pRes0 = pShader0->GetShaderResources().get(); - const ShaderResourcesD3D12* pRes1 = pShader1->GetShaderResources().get(); - if (!pRes0->IsCompatibleWith(*pRes1)) + + const auto& Res0 = GetShaderResLayout(s).GetResources(); + const auto& Res1 = pPSOD3D12->GetShaderResLayout(s).GetResources(); + if (!Res0.IsCompatibleWith(Res1)) { IsCompatibleShaders = false; break; - }*/ + } } } diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index c61ead8c..48b24c04 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -112,23 +112,23 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun } else { - UNEXPECTED("TODO"); - // AZ TODO - /*m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(m_ppShaders.data(), ShaderStages.size(), false)); - m_ProgramResources.resize(1); - SHADER_TYPE ShaderStages = SHADER_TYPE_UNKNOWN; + std::vector Shaders; + SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; for (size_t i = 0; i < ShaderStages.size(); ++i) { - const auto& ShaderDesc = m_ppShaders[i]->GetDesc(); - ShaderStages |= ShaderDesc.ShaderType; + Shaders.push_back(ShaderStages[i].second); + ActiveStages |= ShaderStages[i].first; } - m_ProgramResources[0].LoadUniforms(ShaderStages, m_GLPrograms[0], GLState, + + m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(ShaderStages.size()), false)); + m_ProgramResources.resize(1); + m_ProgramResources[0].LoadUniforms(ActiveStages, m_GLPrograms[0], GLState, m_TotalUniformBufferBindings, m_TotalSamplerBindings, m_TotalImageBindings, m_TotalStorageBufferBindings); - m_ShaderResourceLayoutHash = m_ProgramResources[0].GetHash();*/ + m_ShaderResourceLayoutHash = m_ProgramResources[0].GetHash(); } // Initialize master resource layout that keeps all variable types and does not reference a resource cache diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 28defd0f..4d29093d 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -177,21 +177,33 @@ public: /* 7.5 */ const Uint32 VariableType : VariableTypeBits; /* 7.7 */ const Uint32 ImmutableSamplerAssigned : ImmutableSamplerFlagBits; -/* 8 */ const SPIRVShaderResourceAttribs SpirvAttribs; -/* 16 */ const ShaderResourceLayoutVk& ParentResLayout; +/* 8 */ const SPIRVShaderResourceAttribs& SpirvAttribs; +/* 16 */ const ShaderResourceLayoutVk& ParentResLayout; + + VkResource(const ShaderResourceLayoutVk& _ParentLayout, + const SPIRVShaderResourceAttribs& _SpirvAttribs, + SHADER_RESOURCE_VARIABLE_TYPE _VariableType, + uint32_t _Binding, + uint32_t _DescriptorSet, + Uint32 _CacheOffset, + Uint32 _SamplerInd, + bool _ImmutableSamplerAssigned = false)noexcept : + Binding {static_cast(_Binding) }, + DescriptorSet {static_cast(_DescriptorSet)}, + CacheOffset {_CacheOffset }, + SamplerInd {_SamplerInd }, + VariableType {_VariableType }, + ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, + SpirvAttribs {_SpirvAttribs }, + ParentResLayout {_ParentLayout } + { + VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits) ); + VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits) ); + VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max() ); + VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); + } // clang-format on - VkResource(const ShaderResourceLayoutVk& _ParentLayout, - const SPIRVShaderResourceAttribs& _SpirvAttribs, - SHADER_RESOURCE_VARIABLE_TYPE _VariableType, - uint32_t _Binding, - uint32_t _DescriptorSet, - Uint32 _CacheOffset, - Uint32 _SamplerInd, - bool _ImmutableSamplerAssigned = false) noexcept; - - ~VkResource(); - // Checks if a resource is bound in ResourceCache at the given ArrayIndex bool IsBound(Uint32 ArrayIndex, const ShaderResourceCacheVk& ResourceCache) const; @@ -289,10 +301,15 @@ public: const Char* GetShaderName() const { - return ""; // AZ TODO + return m_pResources->GetShaderName(); } - SHADER_TYPE GetShaderType() const { return m_ShaderType; } + SHADER_TYPE GetShaderType() const + { + return m_pResources->GetShaderType(); + } + + const SPIRVShaderResources& GetResources() const { return *m_pResources; } const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const { @@ -301,7 +318,7 @@ public: return Resources[GetResourceOffset(VarType, r)]; } - bool IsUsingSeparateSamplers() const { return m_IsUsingSeparateSamplers; } + bool IsUsingSeparateSamplers() const { return !m_pResources->IsUsingCombinedSamplers(); } private: Uint32 GetResourceOffset(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const @@ -348,16 +365,16 @@ private: } // clang-format off -/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; -/* 8 */ std::unique_ptr > m_ResourceBuffer; - -/*24 */ std::array m_NumResources = {}; +/* 0 */ const VulkanUtilities::VulkanLogicalDevice& m_LogicalDevice; +/* 8 */ std::unique_ptr > m_ResourceBuffer; -/*32 */ Uint32 m_NumImmutableSamplers = 0; -/*36 */ bool m_IsUsingSeparateSamplers = false; -/*37 */ SHADER_TYPE m_ShaderType = SHADER_TYPE_UNKNOWN; + // We must use shared_ptr to reference ShaderResources instance, because + // there may be multiple objects referencing the same set of resources +/*24 */ std::shared_ptr m_pResources; -/*40 */ // End of class +/*40 */ std::array m_NumResources = {}; +/*48 */ Uint32 m_NumImmutableSamplers = 0; +/*56*/ // End of class // clang-format on }; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 29d16239..f40f22c8 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -575,15 +575,14 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const IsCompatibleShaders = false; break; } - - // AZ TODO - /*const auto* pRes0 = pShader0->GetShaderResources().get(); - const auto* pRes1 = pShader1->GetShaderResources().get(); - if (!pRes0->IsCompatibleWith(*pRes1)) + + const auto& Res0 = GetShaderResLayout(s).GetResources(); + const auto& Res1 = pPSOVk->GetShaderResLayout(s).GetResources(); + if (!Res0.IsCompatibleWith(Res1)) { IsCompatibleShaders = false; break; - }*/ + } } } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 1f798eb9..a7410210 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -111,21 +111,21 @@ void ShaderResourceLayoutVk::AllocateMemory(IShader* bool AllocateImmutableSamplers) { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); - VERIFY_EXPR(pShader != nullptr); - VERIFY_EXPR(m_ShaderType == SHADER_TYPE_UNKNOWN); + VERIFY_EXPR(!m_pResources); const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - m_ShaderType = pShader->GetDesc().ShaderType; + const auto ShaderType = pShader->GetDesc().ShaderType; // Count the number of resources to allocate all needed memory { auto* pShaderVk = ValidatedCast(pShader); auto pResources = pShaderVk->GetShaderResources(); const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); - VERIFY_EXPR(pResources->GetShaderType() == m_ShaderType); - pResources->ProcessResources( + VERIFY_EXPR(pResources->GetShaderType() == ShaderType); + m_pResources = pResources; + m_pResources->ProcessResources( [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { - auto VarType = FindShaderVariableType(m_ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); + auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix); if (IsAllowedType(VarType, AllowedTypeBits)) { // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app @@ -135,7 +135,6 @@ void ShaderResourceLayoutVk::AllocateMemory(IShader* } } // ); - m_IsUsingSeparateSamplers = !pResources->IsUsingCombinedSamplers(); } Uint32 TotalResources = 0; @@ -152,7 +151,7 @@ void ShaderResourceLayoutVk::AllocateMemory(IShader* for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s) { const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[s]; - if ((StSamDesc.ShaderStages & m_ShaderType) != 0) + if ((StSamDesc.ShaderStages & ShaderType) != 0) ++m_NumImmutableSamplers; } } @@ -227,45 +226,41 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(IShader* Uint32 StaticResCacheSize = 0; - const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); + const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1); + const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); + const auto ShaderType = pShader->GetDesc().ShaderType; - { - auto* pShaderVk = ValidatedCast(pShader); - auto pResources = pShaderVk->GetShaderResources(); - const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); + m_pResources->ProcessResources( + [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // + { + auto VarType = FindShaderVariableType(ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); + if (!IsAllowedType(VarType, AllowedTypeBits)) + return; - pResources->ProcessResources( - [&](const SPIRVShaderResourceAttribs& Attribs, Uint32) // + Int32 SrcImmutableSamplerInd = -1; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || + Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) { - auto VarType = FindShaderVariableType(m_ShaderType, Attribs, ResourceLayoutDesc, CombinedSamplerSuffix); - if (!IsAllowedType(VarType, AllowedTypeBits)) - return; - - Int32 SrcImmutableSamplerInd = -1; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || - Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler) - { - // Only search for the immutable sampler for combined image samplers and separate samplers - SrcImmutableSamplerInd = FindImmutableSampler(m_ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); - // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app - } + // Only search for the immutable sampler for combined image samplers and separate samplers + SrcImmutableSamplerInd = FindImmutableSampler(ShaderType, ResourceLayoutDesc, Attribs, CombinedSamplerSuffix); + // For immutable separate samplers we allocate VkResource instances, but they are never exposed to the app + } - Uint32 Binding = Attribs.Type; - Uint32 DescriptorSet = 0; - Uint32 CacheOffset = StaticResCacheSize; - StaticResCacheSize += Attribs.ArraySize; + Uint32 Binding = Attribs.Type; + Uint32 DescriptorSet = 0; + Uint32 CacheOffset = StaticResCacheSize; + StaticResCacheSize += Attribs.ArraySize; - Uint32 SamplerInd = VkResource::InvalidSamplerInd; - if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) - { - // Separate samplers are enumerated before separate images, so the sampler - // assigned to this separate image must have already been created. - SamplerInd = FindAssignedSampler(*this, *pResources, Attribs, CurrResInd[VarType], VarType); - } - ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); - } // - ); - } + Uint32 SamplerInd = VkResource::InvalidSamplerInd; + if (Attribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage) + { + // Separate samplers are enumerated before separate images, so the sampler + // assigned to this separate image must have already been created. + SamplerInd = FindAssignedSampler(*this, *m_pResources, Attribs, CurrResInd[VarType], VarType); + } + ::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0); + } // + ); #ifdef DILIGENT_DEBUG for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast(VarType + 1)) @@ -603,42 +598,6 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende #endif } - -ShaderResourceLayoutVk::VkResource::VkResource(const ShaderResourceLayoutVk& _ParentLayout, - const SPIRVShaderResourceAttribs& _SpirvAttribs, - SHADER_RESOURCE_VARIABLE_TYPE _VariableType, - uint32_t _Binding, - uint32_t _DescriptorSet, - Uint32 _CacheOffset, - Uint32 _SamplerInd, - bool _ImmutableSamplerAssigned) noexcept : - // clang-format off - Binding {static_cast(_Binding) }, - DescriptorSet {static_cast(_DescriptorSet)}, - CacheOffset {_CacheOffset }, - SamplerInd {_SamplerInd }, - VariableType {_VariableType }, - ImmutableSamplerAssigned {_ImmutableSamplerAssigned ? 1U : 0U}, - SpirvAttribs {_SpirvAttribs }, - ParentResLayout {_ParentLayout } -// clang-format on -{ - VERIFY(_CacheOffset < (1 << CacheOffsetBits), "Cache offset (", _CacheOffset, ") exceeds max representable value ", (1 << CacheOffsetBits)); - VERIFY(_SamplerInd < (1 << SamplerIndBits), "Sampler index (", _SamplerInd, ") exceeds max representable value ", (1 << SamplerIndBits)); - VERIFY(_Binding <= std::numeric_limits::max(), "Binding (", _Binding, ") exceeds max representable value ", std::numeric_limits::max()); - VERIFY(_DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", _DescriptorSet, ") exceeds max representable value ", std::numeric_limits::max()); - - const size_t Size = strlen(SpirvAttribs.Name) + 1; - char* NameCopy = ALLOCATE(GetRawAllocator(), "SPIRV Attribs Name", char, Size); - std::memcpy(NameCopy, SpirvAttribs.Name, Size); - const_cast(SpirvAttribs).Name = NameCopy; -} - -ShaderResourceLayoutVk::VkResource::~VkResource() -{ - FREE(GetRawAllocator(), const_cast(SpirvAttribs.Name)); -} - void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet, uint32_t ArrayElement, const VkDescriptorImageInfo* pImageInfo, diff --git a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp index b7c96523..5c35de33 100644 --- a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp +++ b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp @@ -78,7 +78,7 @@ struct SPIRVShaderResourceAttribs static constexpr const Uint32 InvalidSepSmplrOrImgInd = static_cast(-1); -/* 0 */const char* Name; +/* 0 */const char* const Name; /* 8 */const Uint16 ArraySize; /* 10 */const ResourceType Type; /* 11 */ // unused -- cgit v1.2.3 From bff90b395a3cbcc96a199cf8db95309b13e8e855 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 8 Oct 2020 23:51:30 +0300 Subject: formating --- Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp | 2 +- Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp | 2 +- Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 48b24c04..e6e6a84f 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -113,7 +113,7 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun else { std::vector Shaders; - SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; + SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; for (size_t i = 0; i < ShaderStages.size(); ++i) { Shaders.push_back(ShaderStages[i].second); diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 4d29093d..c6432f4a 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -308,7 +308,7 @@ public: { return m_pResources->GetShaderType(); } - + const SPIRVShaderResources& GetResources() const { return *m_pResources; } const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index f40f22c8..881196ec 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -575,7 +575,7 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const IsCompatibleShaders = false; break; } - + const auto& Res0 = GetShaderResLayout(s).GetResources(); const auto& Res1 = pPSOVk->GetShaderResLayout(s).GetResources(); if (!Res0.IsCompatibleWith(Res1)) -- cgit v1.2.3 From 91aac63f651da1079be93d2fe722cd10e4e15570 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 10 Oct 2020 19:28:54 -0700 Subject: A number of corrections for PSO refactoring --- .../src/GraphicsAccessories.cpp | 2 +- .../GraphicsEngine/include/PipelineStateBase.hpp | 119 +++++++++------------ .../include/PipelineStateD3D11Impl.hpp | 4 +- .../src/DeviceContextD3D11Impl.cpp | 4 +- .../src/PipelineStateD3D11Impl.cpp | 45 ++++---- .../src/ShaderResourceBindingD3D11Impl.cpp | 4 +- .../include/PipelineStateD3D12Impl.hpp | 8 +- .../src/PipelineStateD3D12Impl.cpp | 64 ++++++----- .../src/ShaderResourceBindingD3D12Impl.cpp | 8 +- .../GraphicsEngineOpenGL/include/ShaderGLImpl.hpp | 2 +- .../src/PipelineStateGLImpl.cpp | 46 ++++---- Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp | 6 +- .../include/PipelineStateVkImpl.hpp | 13 ++- .../include/ShaderResourceBindingVkImpl.hpp | 2 +- .../include/ShaderResourceLayoutVk.hpp | 23 ++-- .../src/PipelineStateVkImpl.cpp | 93 +++++++--------- .../src/ShaderResourceBindingVkImpl.cpp | 5 +- .../src/ShaderResourceLayoutVk.cpp | 67 ++++++------ .../src/VulkanTypeConversions.cpp | 2 +- 19 files changed, 262 insertions(+), 255 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index 29e5aff3..b07a2194 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -1316,7 +1316,7 @@ Int32 GetShaderTypePipelineIndex(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineT { VERIFY(IsConsistentShaderType(ShaderType, PipelineType), "Shader type ", GetShaderTypeLiteralName(ShaderType), " is inconsistent with pipeline type ", GetPipelineTypeString(PipelineType)); - VERIFY((ShaderType & (ShaderType - 1)) == 0, "More than one shader type specified"); + VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "More than one shader type is specified"); static_assert(SHADER_TYPE_LAST == 0x080, "Please update the switch below to handle the new shader type"); switch (ShaderType) diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 76760db5..09f1bddc 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -68,6 +68,16 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal} { + switch (PSODesc.PipelineType) + { + // clang-format off + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: ValidateGraphicsPipeline(); break; + case PIPELINE_TYPE_COMPUTE: ValidateComputePipeline(); break; + default: UNEXPECTED("unknown pipeline type"); + // clang-format on + } + const auto& SrcLayout = PSODesc.ResourceLayout; size_t StringPoolSize = 0; if (SrcLayout.Variables != nullptr) @@ -88,14 +98,11 @@ public: } } - switch (PSODesc.PipelineType) + if (PSODesc.IsAnyGraphicsPipeline()) { - // clang-format off - case PIPELINE_TYPE_GRAPHICS: - case PIPELINE_TYPE_MESH: ValidateGraphicsPipeline( StringPoolSize); break; - case PIPELINE_TYPE_COMPUTE: ValidateComputePipeline( StringPoolSize); break; - default: UNEXPECTED("unknown pipeline type"); - // clang-format on + const auto& InputLayout = this->m_Desc.GraphicsPipeline.InputLayout; + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1; } m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); @@ -143,8 +150,8 @@ public: { // clang-format off case PIPELINE_TYPE_GRAPHICS: - case PIPELINE_TYPE_MESH: InitGraphicsPipeline(); break; - case PIPELINE_TYPE_COMPUTE: InitComputePipeline(); break; + case PIPELINE_TYPE_MESH: InitGraphicsPipeline(); break; + case PIPELINE_TYPE_COMPUTE: InitComputePipeline(); break; default: UNEXPECTED("unknown pipeline type"); // clang-format on } @@ -201,8 +208,8 @@ public: return m_BufferSlotsUsed; } - SHADER_TYPE const* GetShaderTypes() const { return m_pShaderTypes.data(); } - Uint32 GetNumShaderTypes() const { return m_NumShaderTypes; } + SHADER_TYPE GetShaderStageType(Uint32 Stage) const { return m_ShaderStageTypes[Stage]; } + Uint32 GetNumShaderStages() const { return m_NumShaderStages; } // This function only compares shader resource layout hashes, so // it can potentially give false negatives @@ -219,10 +226,12 @@ protected: RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object - Uint8 m_NumShaderTypes = 0; ///< Number of shader types that this PSO uses + Uint8 m_NumShaderStages = 0; ///< Number of shader stages in this PSO + + /// Array of shader types for every shader stage used by this PSO + std::array m_ShaderStageTypes = {}; - std::array m_pShaderTypes = {}; ///< Array of shader types used by this PSO - size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout + size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout protected: #define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(this->m_Desc.PipelineType), " PSO '", this->m_Desc.Name, "' is invalid: ", ##__VA_ARGS__) @@ -287,51 +296,50 @@ protected: return LayoutInd; } -public: - using ShaderStages_t = std::vector>; protected: - void ExtractShaders(ShaderStages_t& ShaderStages) + template + void ExtractShaders(TShaderStages& ShaderStages) { + VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + + ShaderStages.clear(); + auto AddShaderStage = [&](IShader*& pShader) { + if (pShader != nullptr) + { + auto ShaderType = pShader->GetDesc().ShaderType; + ShaderStages.emplace_back(ShaderType, ValidatedCast(pShader)); + m_ShaderStageTypes[m_NumShaderStages++] = ShaderType; + + // Reset shader pointers in PSO desc because we don't keep strong references to shaders. + pShader = nullptr; + } + }; + auto& Desc = this->m_Desc; switch (Desc.PipelineType) { case PIPELINE_TYPE_COMPUTE: { - if (Desc.ComputePipeline.pCS) ShaderStages.push_back({SHADER_TYPE_COMPUTE, Desc.ComputePipeline.pCS}); - - // reset shader pointers because we don't keep strong references to shaders - Desc.ComputePipeline.pCS = nullptr; + AddShaderStage(Desc.ComputePipeline.pCS); break; } case PIPELINE_TYPE_GRAPHICS: { - if (Desc.GraphicsPipeline.pVS) ShaderStages.push_back({SHADER_TYPE_VERTEX, Desc.GraphicsPipeline.pVS}); - if (Desc.GraphicsPipeline.pHS) ShaderStages.push_back({SHADER_TYPE_HULL, Desc.GraphicsPipeline.pHS}); - if (Desc.GraphicsPipeline.pDS) ShaderStages.push_back({SHADER_TYPE_DOMAIN, Desc.GraphicsPipeline.pDS}); - if (Desc.GraphicsPipeline.pGS) ShaderStages.push_back({SHADER_TYPE_GEOMETRY, Desc.GraphicsPipeline.pGS}); - if (Desc.GraphicsPipeline.pPS) ShaderStages.push_back({SHADER_TYPE_PIXEL, Desc.GraphicsPipeline.pPS}); - - // reset shader pointers because we don't keep strong references to shaders - Desc.GraphicsPipeline.pVS = nullptr; - Desc.GraphicsPipeline.pHS = nullptr; - Desc.GraphicsPipeline.pDS = nullptr; - Desc.GraphicsPipeline.pGS = nullptr; - Desc.GraphicsPipeline.pPS = nullptr; + AddShaderStage(Desc.GraphicsPipeline.pVS); + AddShaderStage(Desc.GraphicsPipeline.pHS); + AddShaderStage(Desc.GraphicsPipeline.pDS); + AddShaderStage(Desc.GraphicsPipeline.pGS); + AddShaderStage(Desc.GraphicsPipeline.pPS); break; } case PIPELINE_TYPE_MESH: { - if (Desc.GraphicsPipeline.pAS) ShaderStages.push_back({SHADER_TYPE_AMPLIFICATION, Desc.GraphicsPipeline.pAS}); - if (Desc.GraphicsPipeline.pMS) ShaderStages.push_back({SHADER_TYPE_MESH, Desc.GraphicsPipeline.pMS}); - if (Desc.GraphicsPipeline.pPS) ShaderStages.push_back({SHADER_TYPE_PIXEL, Desc.GraphicsPipeline.pPS}); - - // reset shader pointers because we don't keep strong references to shaders - Desc.GraphicsPipeline.pAS = nullptr; - Desc.GraphicsPipeline.pMS = nullptr; - Desc.GraphicsPipeline.pPS = nullptr; + AddShaderStage(Desc.GraphicsPipeline.pAS); + AddShaderStage(Desc.GraphicsPipeline.pMS); + AddShaderStage(Desc.GraphicsPipeline.pPS); break; } @@ -339,14 +347,7 @@ protected: UNEXPECTED("unknown pipeline type"); } -#ifdef DILIGENT_DEVELOPMENT - VERIFY_EXPR(ShaderStages.size() == m_NumShaderTypes); - - for (Uint32 s = 0; s < m_NumShaderTypes; ++s) - { - VERIFY_EXPR(ShaderStages[s].first == m_pShaderTypes[s]); - } -#endif + VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); } @@ -448,7 +449,7 @@ private: } } - void ValidateGraphicsPipeline(size_t& StringPoolSize) + void ValidateGraphicsPipeline() { const auto& GraphicsPipeline = this->m_Desc.GraphicsPipeline; if (GraphicsPipeline.pRenderPass != nullptr) @@ -477,13 +478,9 @@ private: CheckAndCorrectBlendStateDesc(); CheckRasterizerStateDesc(); CheckAndCorrectDepthStencilDesc(); - - const auto& InputLayout = this->m_Desc.GraphicsPipeline.InputLayout; - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1; } - void ValidateComputePipeline(size_t& StringPoolSize) + void ValidateComputePipeline() { if (this->m_Desc.GraphicsPipeline.pRenderPass != nullptr) { @@ -527,16 +524,6 @@ private: "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)"); } - if (GraphicsPipeline.pVS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_VERTEX; - if (GraphicsPipeline.pHS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_HULL; - if (GraphicsPipeline.pDS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_DOMAIN; - if (GraphicsPipeline.pGS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_GEOMETRY; - if (GraphicsPipeline.pAS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_AMPLIFICATION; - if (GraphicsPipeline.pMS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_MESH; - if (GraphicsPipeline.pPS) m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_PIXEL; - - DEV_CHECK_ERR(m_NumShaderTypes > 0, "There must be at least one shader in the Pipeline State"); - m_pRenderPass = PSODesc.GraphicsPipeline.pRenderPass; for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) @@ -682,8 +669,6 @@ private: } VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute"); - - m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_COMPUTE; } #undef VALIDATE_SHADER_TYPE diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 7acb15f0..1d836ab3 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -118,13 +118,13 @@ public: const ShaderResourceLayoutD3D11& GetStaticResourceLayout(Uint32 s) const { - VERIFY_EXPR(s < GetNumShaderTypes()); + VERIFY_EXPR(s < GetNumShaderStages()); return m_pStaticResourceLayouts[s]; } ShaderResourceCacheD3D11& GetStaticResourceCache(Uint32 s) { - VERIFY_EXPR(s < GetNumShaderTypes()); + VERIFY_EXPR(s < GetNumShaderStages()); return m_pStaticResourceCaches[s]; } diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index cd942aed..75ce9094 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -179,7 +179,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* { #ifdef DILIGENT_DEVELOPMENT bool ResourcesPresent = false; - for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaderStages(); ++s) { auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s); if (pShaderD3D11->GetD3D11Resources()->GetTotalResources() > 0) @@ -206,7 +206,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState* #endif auto NumShaders = pShaderResBindingD3D11->GetNumActiveShaders(); - VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaderTypes(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state"); + VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaderStages(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state"); #ifdef DILIGENT_DEVELOPMENT { diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 0e312740..4893f97e 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -131,28 +131,35 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR UNEXPECTED(GetPipelineTypeString(m_Desc.PipelineType), " pipelines are not supported by Direct3D11 backend"); } + // We do not really need ShaderStages, but ExtractShaders() also initializes + // shader stage types and shader stage counter. + std::vector> ShaderStages; + ExtractShaders(ShaderStages); + VERIFY_EXPR(GetNumShaderStages() == ShaderStages.size()); + // clang-format off static_assert((sizeof(ShaderResourceLayoutD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutD3D11) is expected to be a multiple of sizeof(void*)"); static_assert((sizeof(ShaderResourceCacheD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D11) is expected to be a multiple of sizeof(void*)"); // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutD3D11) + sizeof(ShaderResourceCacheD3D11)) * GetNumShaderTypes(); + + const auto MemSize = (sizeof(ShaderResourceLayoutD3D11) + sizeof(ShaderResourceCacheD3D11)) * GetNumShaderStages(); auto* const pRawMem = ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11 and ShaderResourceCacheD3D11 arrays", MemSize); m_pStaticResourceLayouts = reinterpret_cast(pRawMem); - m_pStaticResourceCaches = reinterpret_cast(m_pStaticResourceLayouts + GetNumShaderTypes()); + m_pStaticResourceCaches = reinterpret_cast(m_pStaticResourceLayouts + GetNumShaderStages()); const auto& ResourceLayout = m_Desc.ResourceLayout; #ifdef DILIGENT_DEVELOPMENT { const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {}; - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { auto* pShader = GetShader(s); pResources[s] = &(*pShader->GetD3D11Resources()); } - ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderTypes(), + ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(), (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); } @@ -161,7 +168,7 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR decltype(m_StaticSamplers) StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")); std::array ShaderResLayoutDataSizes = {}; std::array ShaderResCacheDataSizes = {}; - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { const auto* pShader = GetShader(s); const auto& ShaderDesc = pShader->GetDesc(); @@ -221,14 +228,14 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR if (m_Desc.SRBAllocationGranularity > 1) { - m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderTypes(), ShaderResLayoutDataSizes.data(), GetNumShaderTypes(), ShaderResCacheDataSizes.data()); + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderResLayoutDataSizes.data(), GetNumShaderStages(), ShaderResCacheDataSizes.data()); } m_StaticSamplers.reserve(StaticSamplers.size()); for (auto& Sam : StaticSamplers) m_StaticSamplers.emplace_back(std::move(Sam)); - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { // Initialize static samplers in the static resource cache to avoid warning messages SetStaticSamplers(m_pStaticResourceCaches[s], s); @@ -238,19 +245,19 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR PipelineStateD3D11Impl::~PipelineStateD3D11Impl() { - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); } - for (Uint32 l = 0; l < GetNumShaderTypes(); ++l) + for (Uint32 l = 0; l < GetNumShaderStages(); ++l) { m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); } // m_pStaticResourceLayouts and m_pStaticResourceCaches are allocated in contiguous chunks of memory. - auto* pRawMem = m_pStaticResourceLayouts; - GetRawAllocator().Free(pRawMem); + if (auto* pRawMem = m_pStaticResourceLayouts) + GetRawAllocator().Free(pRawMem); } IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase) @@ -297,10 +304,10 @@ bool PipelineStateD3D11Impl::IsCompatibleWith(const IPipelineState* pPSO) const if (m_ShaderResourceLayoutHash != pPSOD3D11->m_ShaderResourceLayoutHash) return false; - if (GetNumShaderTypes() != pPSOD3D11->GetNumShaderTypes()) + if (GetNumShaderStages() != pPSOD3D11->GetNumShaderStages()) return false; - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { auto* pShader0 = GetShader(s); auto* pShader1 = pPSOD3D11->GetShader(s); @@ -360,7 +367,7 @@ ID3D11ComputeShader* PipelineStateD3D11Impl::GetD3D11ComputeShader() void PipelineStateD3D11Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) { - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { auto& StaticResLayout = m_pStaticResourceLayouts[s]; if ((ShaderFlags & StaticResLayout.GetShaderType()) != 0) @@ -374,7 +381,7 @@ Uint32 PipelineStateD3D11Impl::GetStaticVariableCount(SHADER_TYPE ShaderType) co if (LayoutInd < 0) return 0; - VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderTypes()); + VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderStages()); return m_pStaticResourceLayouts[LayoutInd].GetTotalResourceCount(); } @@ -384,7 +391,7 @@ IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByName(SHADER_ if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderTypes()); + VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderStages()); return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Name); } @@ -394,7 +401,7 @@ IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByIndex(SHADER if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderTypes()); + VERIFY_EXPR(static_cast(LayoutInd) <= GetNumShaderStages()); return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Index); } @@ -431,8 +438,8 @@ const ShaderD3D11Impl* PipelineStateD3D11Impl::GetShaderByType(SHADER_TYPE Shade const ShaderD3D11Impl* PipelineStateD3D11Impl::GetShader(Uint32 Index) const { - if (Index < GetNumShaderTypes()) - return GetShaderByType(GetShaderTypes()[Index]); + if (Index < GetNumShaderStages()) + return GetShaderByType(GetShaderStageType(Index)); UNEXPECTED("Shader index is out of range"); return nullptr; diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 17083bbc..88c7b77f 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -50,7 +50,7 @@ ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounter // clang-format on { m_ResourceLayoutIndex.fill(-1); - m_NumActiveShaders = static_cast(pPSO->GetNumShaderTypes()); + m_NumActiveShaders = static_cast(pPSO->GetNumShaderStages()); // clang-format off m_pResourceLayouts = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11", ShaderResourceLayoutD3D11, m_NumActiveShaders); @@ -151,7 +151,7 @@ void ShaderResourceBindingD3D11Impl::InitializeStaticResources(const IPipelineSt } const auto* pPSOD3D11 = ValidatedCast(pPipelineState); - auto NumShaders = pPSOD3D11->GetNumShaderTypes(); + auto NumShaders = pPSOD3D11->GetNumShaderStages(); VERIFY_EXPR(NumShaders == m_NumActiveShaders); for (Uint32 shader = 0; shader < NumShaders; ++shader) diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index 1ce53c24..00b2affd 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -95,19 +95,19 @@ public: const ShaderResourceLayoutD3D12& GetShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < GetNumShaderTypes()); + VERIFY_EXPR(ShaderInd < GetNumShaderStages()); return m_pShaderResourceLayouts[ShaderInd]; } const ShaderResourceLayoutD3D12& GetStaticShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < GetNumShaderTypes()); - return m_pShaderResourceLayouts[GetNumShaderTypes() + ShaderInd]; + VERIFY_EXPR(ShaderInd < GetNumShaderStages()); + return m_pShaderResourceLayouts[GetNumShaderStages() + ShaderInd]; } ShaderResourceCacheD3D12& GetStaticShaderResCache(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < GetNumShaderTypes()); + VERIFY_EXPR(ShaderInd < GetNumShaderStages()); return m_pStaticResourceCaches[ShaderInd]; } diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 3e8673d5..f5d60b60 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -106,8 +106,19 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR { m_ResourceLayoutIndex.fill(-1); - ShaderStages_t ShaderStages; - ExtractShaders(ShaderStages); + struct D3D12PipelineShaderStageInfo + { + const SHADER_TYPE Type; + ShaderD3D12Impl* const pShader; + D3D12PipelineShaderStageInfo(SHADER_TYPE _Type, + ShaderD3D12Impl* _pShader) : + Type{_Type}, + pShader{_pShader} + {} + }; + std::vector ShaderStages; + ExtractShaders(ShaderStages); + VERIFY_EXPR(GetNumShaderStages() == ShaderStages.size()); auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); const auto& ResourceLayout = m_Desc.ResourceLayout; @@ -118,23 +129,23 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR static_assert((sizeof(ShaderResourceCacheD3D12) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D12) is expected to be a multiple of sizeof(void*)"); static_assert((sizeof(ShaderVariableManagerD3D12) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerD3D12) is expected to be a multiple of sizeof(void*)"); // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutD3D12) * 2 + sizeof(ShaderResourceCacheD3D12) + sizeof(ShaderVariableManagerD3D12)) * GetNumShaderTypes(); + const auto MemSize = (sizeof(ShaderResourceLayoutD3D12) * 2 + sizeof(ShaderResourceCacheD3D12) + sizeof(ShaderVariableManagerD3D12)) * GetNumShaderStages(); auto* const pRawMem = ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12, ShaderResourceCacheD3D12, and ShaderVariableManagerD3D12 arrays", MemSize); m_pShaderResourceLayouts = reinterpret_cast(pRawMem); - m_pStaticResourceCaches = reinterpret_cast(m_pShaderResourceLayouts + GetNumShaderTypes() * 2); - m_pStaticVarManagers = reinterpret_cast(m_pStaticResourceCaches + GetNumShaderTypes()); + m_pStaticResourceCaches = reinterpret_cast(m_pShaderResourceLayouts + GetNumShaderStages() * 2); + m_pStaticVarManagers = reinterpret_cast(m_pStaticResourceCaches + GetNumShaderStages()); #ifdef DILIGENT_DEVELOPMENT { const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {}; for (size_t s = 0; s < ShaderStages.size(); ++s) { - const auto* pShader = ValidatedCast(ShaderStages[s].second); + const auto* pShader = ShaderStages[s].pShader; pResources[s] = &(*pShader->GetShaderResources()); } - ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderTypes(), + ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(), (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); } @@ -142,7 +153,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto* pShaderD3D12 = ValidatedCast(ShaderStages[s].second); + auto* pShaderD3D12 = ShaderStages[s].pShader; auto ShaderType = pShaderD3D12->GetDesc().ShaderType; auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); @@ -166,7 +177,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D12{ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources}; const SHADER_RESOURCE_VARIABLE_TYPE StaticVarType[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; - new (m_pShaderResourceLayouts + GetNumShaderTypes() + s) + new (m_pShaderResourceLayouts + GetNumShaderStages() + s) ShaderResourceLayoutD3D12 // { *this, @@ -200,7 +211,8 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR { D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; - auto* pByteCode = ValidatedCast(ShaderStages[0].second)->GetShaderByteCode(); + VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); + auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); @@ -229,10 +241,11 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; - for (size_t s = 0; s < ShaderStages.size(); ++s) + for (const auto& Stage : ShaderStages) { - auto* pShaderD3D12 = ValidatedCast(ShaderStages[s].second); + auto* pShaderD3D12 = Stage.pShader; auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; switch (ShaderType) @@ -333,10 +346,11 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR }; MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; - for (size_t s = 0; s < ShaderStages.size(); ++s) + for (const auto& Stage : ShaderStages) { - auto* pShaderD3D12 = ValidatedCast(ShaderStages[s].second); + auto* pShaderD3D12 = Stage.pShader; auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; switch (ShaderType) @@ -410,7 +424,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR if (m_Desc.SRBAllocationGranularity > 1) { std::array ShaderVarMgrDataSizes = {}; - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { std::array AllowedVarTypes = { @@ -423,7 +437,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR } auto CacheMemorySize = m_RootSig.GetResourceCacheRequiredMemSize(); - m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderTypes(), ShaderVarMgrDataSizes.data(), 1, &CacheMemorySize); + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderVarMgrDataSizes.data(), 1, &CacheMemorySize); } m_ShaderResourceLayoutHash = m_RootSig.GetHash(); @@ -432,13 +446,13 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR PipelineStateD3D12Impl::~PipelineStateD3D12Impl() { auto& ShaderResLayoutAllocator = GetRawAllocator(); - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { m_pStaticVarManagers[s].Destroy(GetRawAllocator()); m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); - m_pShaderResourceLayouts[GetNumShaderTypes() + s].~ShaderResourceLayoutD3D12(); + m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12(); } // m_pShaderResourceLayouts, m_pStaticResourceCaches, and m_pShaderResourceLayouts are allocated in // contiguous chunks of memory. @@ -477,14 +491,14 @@ bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState* pPSO) const #ifdef DILIGENT_DEBUG { bool IsCompatibleShaders = true; - if (GetNumShaderTypes() != pPSOD3D12->GetNumShaderTypes()) + if (GetNumShaderStages() != pPSOD3D12->GetNumShaderStages()) IsCompatibleShaders = false; if (IsCompatibleShaders) { - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { - if (GetShaderTypes()[s] != pPSOD3D12->GetShaderTypes()[s]) + if (GetShaderStageType(s) != pPSOD3D12->GetShaderStageType(s)) { IsCompatibleShaders = false; break; @@ -603,7 +617,7 @@ bool PipelineStateD3D12Impl::ContainsShaderResources() const void PipelineStateD3D12Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) { - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { auto ShaderType = GetStaticShaderResLayout(s).GetShaderType(); if ((ShaderFlags & ShaderType) != 0) @@ -617,7 +631,7 @@ Uint32 PipelineStateD3D12Impl::GetStaticVariableCount(SHADER_TYPE ShaderType) co if (LayoutInd < 0) return 0; - VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderTypes()); + VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderStages()); return m_pStaticVarManagers[LayoutInd].GetVariableCount(); } @@ -627,7 +641,7 @@ IShaderResourceVariable* PipelineStateD3D12Impl::GetStaticVariableByName(SHADER_ if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderTypes()); + VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderStages()); return m_pStaticVarManagers[LayoutInd].GetVariable(Name); } @@ -637,7 +651,7 @@ IShaderResourceVariable* PipelineStateD3D12Impl::GetStaticVariableByIndex(SHADER if (LayoutInd < 0) return nullptr; - VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderTypes()); + VERIFY_EXPR(static_cast(LayoutInd) < GetNumShaderStages()); return m_pStaticVarManagers[LayoutInd].GetVariable(Index); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 17387138..3293283a 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -45,7 +45,7 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter IsPSOInternal }, m_ShaderResourceCache{ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources}, - m_NumShaders {static_cast(pPSO->GetNumShaderTypes())} + m_NumShaders {static_cast(pPSO->GetNumShaderStages())} // clang-format on { m_ResourceLayoutIndex.fill(-1); @@ -58,7 +58,7 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter for (Uint32 s = 0; s < m_NumShaders; ++s) { - auto ShaderType = pPSO->GetShaderTypes()[s]; + auto ShaderType = pPSO->GetShaderStageType(s); auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType); auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); @@ -187,7 +187,7 @@ void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const IPipelineSt } auto* pPSO12 = ValidatedCast(pPSO); - auto NumShaders = pPSO12->GetNumShaderTypes(); + auto NumShaders = pPSO12->GetNumShaderStages(); // Copy static resources for (Uint32 s = 0; s < NumShaders; ++s) { @@ -200,7 +200,7 @@ void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const IPipelineSt { LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", pPSO12->GetDesc().Name, "' will not be successfully initialized because not all static resource bindings in shader type '", - GetShaderTypeLiteralName(pPSO12->GetShaderTypes()[s]), + GetShaderTypeLiteralName(pPSO12->GetShaderStageType(s)), "' 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."); } diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp index bc0f32e6..d4c4b87e 100644 --- a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp @@ -92,7 +92,7 @@ public: /// Implementation of IShader::GetResource() in OpenGL backend. virtual void DILIGENT_CALL_TYPE GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final; - static GLObjectWrappers::GLProgramObj LinkProgram(IShader** ppShaders, Uint32 NumShaders, bool IsSeparableProgram); + static GLObjectWrappers::GLProgramObj LinkProgram(ShaderGLImpl** ppShaders, Uint32 NumShaders, bool IsSeparableProgram); private: GLObjectWrappers::GLShaderObj m_GLShaderObj; diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index e6e6a84f..8590e203 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -52,8 +52,7 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun m_StaticResourceLayout{*this} // clang-format on { - RefCntAutoPtr pTempPS; - + RefCntAutoPtr pTempPS; if (m_Desc.IsAnyGraphicsPipeline() && m_Desc.GraphicsPipeline.pPS == nullptr) { // Some OpenGL implementations fail if fragment shader is not present, so @@ -63,17 +62,23 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun ShaderCI.Source = "void main(){}"; ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; ShaderCI.Desc.Name = "Dummy fragment shader"; - pDeviceGL->CreateShader(ShaderCI, &pTempPS); - } + pDeviceGL->CreateShader(ShaderCI, reinterpret_cast(static_cast(&pTempPS))); - ShaderStages_t ShaderStages; - ExtractShaders(ShaderStages); + m_Desc.GraphicsPipeline.pPS = pTempPS; + } - if (pTempPS) + struct GLPipelineShaderStageInfo { - m_pShaderTypes[m_NumShaderTypes++] = SHADER_TYPE_PIXEL; - ShaderStages.push_back({SHADER_TYPE_PIXEL, pTempPS}); - } + const SHADER_TYPE Type; + ShaderGLImpl* const pShader; + GLPipelineShaderStageInfo(SHADER_TYPE _Type, + ShaderGLImpl* _pShader) : + Type{_Type}, + pShader{_pShader} + {} + }; + std::vector ShaderStages; + ExtractShaders(ShaderStages); auto& DeviceCaps = pDeviceGL->GetDeviceCaps(); VERIFY(DeviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized"); @@ -96,10 +101,9 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun m_GLPrograms.reserve(ShaderStages.size()); for (size_t i = 0; i < ShaderStages.size(); ++i) { - auto* pShader = ShaderStages[i].second; - auto* pShaderGL = ValidatedCast(pShader); + auto* pShaderGL = ShaderStages[i].pShader; const auto& ShaderDesc = pShaderGL->GetDesc(); - m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(&pShader, 1, true)); + m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)); // Load uniforms and assign bindings m_ProgramResources[i].LoadUniforms(ShaderDesc.ShaderType, m_GLPrograms[i], GLState, m_TotalUniformBufferBindings, @@ -112,12 +116,14 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun } else { - std::vector Shaders; - SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; - for (size_t i = 0; i < ShaderStages.size(); ++i) + std::vector Shaders; + + SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN; + for (const auto& Stage : ShaderStages) { - Shaders.push_back(ShaderStages[i].second); - ActiveStages |= ShaderStages[i].first; + Shaders.push_back(Stage.pShader); + VERIFY((ActiveStages & Stage.Type) == 0, "Shader stage ", GetShaderTypeLiteralName(Stage.Type), " is already active"); + ActiveStages |= Stage.Type; } m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(ShaderStages.size()), false)); @@ -226,9 +232,9 @@ GLObjectWrappers::GLPipelineObj& PipelineStateGLImpl::GetGLProgramPipeline(GLCon m_GLProgPipelines.emplace_back(Context, true); auto& ctx_pipeline = m_GLProgPipelines.back(); GLuint Pipeline = ctx_pipeline.second; - for (Uint32 i = 0; i < GetNumShaderTypes(); ++i) + for (Uint32 i = 0; i < GetNumShaderStages(); ++i) { - auto GLShaderBit = ShaderTypeToGLShaderBit(GetShaderTypes()[i]); + auto GLShaderBit = ShaderTypeToGLShaderBit(GetShaderStageType(i)); // If the program has an active code for each stage mentioned in set flags, // then that code will be used by the pipeline. If program is 0, then the given // stages are cleared from the pipeline. diff --git a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp index c7a493cd..e27a8a4c 100644 --- a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp @@ -158,7 +158,7 @@ ShaderGLImpl::ShaderGLImpl(IReferenceCounters* pRefCounters, if (deviceCaps.Features.SeparablePrograms) { - IShader* ThisShader[] = {this}; + ShaderGLImpl* ThisShader[] = {this}; GLObjectWrappers::GLProgramObj Program = LinkProgram(ThisShader, 1, true); Uint32 UniformBufferBinding = 0; Uint32 SamplerBinding = 0; @@ -178,7 +178,7 @@ ShaderGLImpl::~ShaderGLImpl() IMPLEMENT_QUERY_INTERFACE(ShaderGLImpl, IID_ShaderGL, TShaderBase) -GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(IShader** ppShaders, Uint32 NumShaders, bool IsSeparableProgram) +GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(ShaderGLImpl** ppShaders, Uint32 NumShaders, bool IsSeparableProgram) { VERIFY(!IsSeparableProgram || NumShaders == 1, "Number of shaders must be 1 when separable program is created"); @@ -190,7 +190,7 @@ GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(IShader** ppShaders, Ui for (Uint32 i = 0; i < NumShaders; ++i) { - auto* pCurrShader = ValidatedCast(ppShaders[i]); + auto* pCurrShader = ppShaders[i]; glAttachShader(GLProg, pCurrShader->m_GLShaderObj); CHECK_GL_ERROR("glAttachShader() failed"); } diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index 303496bb..2185dabd 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -56,7 +56,6 @@ class PipelineStateVkImpl final : public PipelineStateBase; - using ShaderSPIRVs_t = std::vector>; PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const PipelineStateCreateInfo& CreateInfo); ~PipelineStateVkImpl(); @@ -105,7 +104,7 @@ public: const ShaderResourceLayoutVk& GetShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaderTypes); + VERIFY_EXPR(ShaderInd < GetNumShaderStages()); return m_ShaderResourceLayouts[ShaderInd]; } @@ -128,19 +127,19 @@ public: private: const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaderTypes); - return m_ShaderResourceLayouts[m_NumShaderTypes + ShaderInd]; + VERIFY_EXPR(ShaderInd < GetNumShaderStages()); + return m_ShaderResourceLayouts[GetNumShaderStages() + ShaderInd]; } const ShaderResourceCacheVk& GetStaticResCache(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaderTypes); + VERIFY_EXPR(ShaderInd < GetNumShaderStages()); return m_StaticResCaches[ShaderInd]; } ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const { - VERIFY_EXPR(ShaderInd < m_NumShaderTypes); + VERIFY_EXPR(ShaderInd < GetNumShaderStages()); return m_StaticVarsMgrs[ShaderInd]; } @@ -156,7 +155,7 @@ private: // Resource layout index in m_ShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; bool m_HasStaticResources = false; bool m_HasNonStaticResources = false; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp index 85230b02..026bb9da 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp @@ -81,7 +81,7 @@ private: // Resource layout index in m_ShaderResourceCache array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) - std::array m_ResourceLayoutIndex; + std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; bool m_bStaticResourcesInitialized = false; Uint8 m_NumShaders = 0; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index c6432f4a..62ff38b5 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -110,13 +110,23 @@ namespace Diligent { +class ShaderVkImpl; + /// Diligent::ShaderResourceLayoutVk class // sizeof(ShaderResourceLayoutVk)==56 (MS compiler, x64) class ShaderResourceLayoutVk { public: - using ShaderStages_t = std::vector>; - using ShaderSPIRVs_t = std::vector>; + struct ShaderStageInfo + { + ShaderStageInfo(SHADER_TYPE _Type, + const ShaderVkImpl* _pShader); + + const SHADER_TYPE Type; + const ShaderVkImpl* const pShader; + std::vector SPIRV; + }; + using TShaderStages = std::vector; ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) : m_LogicalDevice{LogicalDevice} @@ -134,7 +144,7 @@ public: // This method is called by PipelineStateVkImpl class instance to initialize static // shader resource layout and the cache - void InitializeStaticResourceLayout(IShader* pShader, + void InitializeStaticResourceLayout(const ShaderVkImpl* pShader, IMemoryAllocator& LayoutDataAllocator, const PipelineResourceLayoutDesc& ResourceLayoutDesc, ShaderResourceCacheVk& StaticResourceCache); @@ -142,11 +152,10 @@ public: // This method is called by PipelineStateVkImpl class instance to initialize resource // layouts for all shader stages in the pipeline. static void Initialize(IRenderDevice* pRenderDevice, - const ShaderStages_t& ShaderStages, + TShaderStages& ShaderStages, ShaderResourceLayoutVk Layouts[], IMemoryAllocator& LayoutDataAllocator, const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderSPIRVs_t& SPIRVs, class PipelineLayout& PipelineLayout, bool VerifyVariables, bool VerifyStaticSamplers); @@ -281,7 +290,7 @@ public: #ifdef DILIGENT_DEVELOPMENT bool dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache) const; - static void dvpVerifyResourceLayoutDesc(const ShaderStages_t& ShaderStages, + static void dvpVerifyResourceLayoutDesc(const TShaderStages& ShaderStages, const PipelineResourceLayoutDesc& ResourceLayoutDesc, bool VerifyVariables, bool VerifyStaticSamplers); @@ -349,7 +358,7 @@ private: return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES]; } - void AllocateMemory(IShader* pShader, + void AllocateMemory(const ShaderVkImpl* pShader, IMemoryAllocator& Allocator, const PipelineResourceLayoutDesc& ResourceLayoutDesc, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 881196ec..fbc5fae3 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -149,26 +149,21 @@ static bool StripReflection(std::vector& SPIRV) #endif } -static void InitializeShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, - const PipelineStateVkImpl::ShaderStages_t& ShaderStages, - PipelineStateVkImpl::ShaderSPIRVs_t& ShaderSPIRVs, - std::vector& ShaderModules, - std::vector& Stages) +static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice, + ShaderResourceLayoutVk::TShaderStages& ShaderStages, + std::vector& vkShaderModules, + std::vector& vkPipelineShaderStages) { - VERIFY_EXPR(ShaderStages.size() == ShaderSPIRVs.size()); - for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto* pShaderVk = ValidatedCast(ShaderStages[s].second); - auto& SPIRV = ShaderSPIRVs[s]; - const auto ShaderType = ShaderStages[s].first; + auto& StageInfo = ShaderStages[s]; VkPipelineShaderStageCreateInfo StageCI = {}; StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; StageCI.pNext = nullptr; StageCI.flags = 0; // reserved for future use - StageCI.stage = ShaderTypeToVkShaderStageFlagBit(ShaderType); + StageCI.stage = ShaderTypeToVkShaderStageFlagBit(StageInfo.Type); VkShaderModuleCreateInfo ShaderModuleCI = {}; @@ -179,22 +174,22 @@ static void InitializeShaderStages(const VulkanUtilities::VulkanLogicalDevice& // We have to strip reflection instructions to fix the follownig validation error: // SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string // Optimizer also performs validation and may catch problems with the byte code. - if (!StripReflection(SPIRV)) - LOG_ERROR("Failed to strip reflection information from shader '", pShaderVk->GetDesc().Name, "'. This may indicate a problem with the byte code."); + if (!StripReflection(StageInfo.SPIRV)) + LOG_ERROR("Failed to strip reflection information from shader '", StageInfo.pShader->GetDesc().Name, "'. This may indicate a problem with the byte code."); - ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t); - ShaderModuleCI.pCode = SPIRV.data(); + ShaderModuleCI.codeSize = StageInfo.SPIRV.size() * sizeof(uint32_t); + ShaderModuleCI.pCode = StageInfo.SPIRV.data(); - ShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name)); + vkShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, StageInfo.pShader->GetDesc().Name)); - StageCI.module = ShaderModules.back(); - StageCI.pName = pShaderVk->GetEntryPoint(); + StageCI.module = vkShaderModules.back(); + StageCI.pName = StageInfo.pShader->GetEntryPoint(); StageCI.pSpecializationInfo = nullptr; - Stages.push_back(StageCI); + vkPipelineShaderStages.push_back(StageCI); } - VERIFY_EXPR(ShaderModules.size() == Stages.size()); + VERIFY_EXPR(vkShaderModules.size() == vkPipelineShaderStages.size()); } @@ -417,47 +412,41 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); - ShaderStages_t ShaderStages; - ShaderSPIRVs_t ShaderSPIRVs; - ExtractShaders(ShaderStages); - - ShaderSPIRVs.resize(ShaderStages.size()); - for (size_t s = 0; s < ShaderSPIRVs.size(); ++s) - { - auto* pShaderVk = ValidatedCast(ShaderStages[s].second); - ShaderSPIRVs[s] = pShaderVk->GetSPIRV(); - } + ShaderResourceLayoutVk::TShaderStages ShaderStages; + ExtractShaders(ShaderStages); // clang-format off static_assert((sizeof(ShaderResourceLayoutVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutVk) is expected to be a multiple of sizeof(void*)"); static_assert((sizeof(ShaderResourceCacheVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheVk) is expected to be a multiple of sizeof(void*)"); static_assert((sizeof(ShaderVariableManagerVk) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerVk) is expected to be a multiple of sizeof(void*)"); // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * GetNumShaderTypes(); + const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * GetNumShaderStages(); auto* const pRawMem = ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk, ShaderResourceCacheVk, and ShaderVariableManagerVk arrays", MemSize); m_ShaderResourceLayouts = reinterpret_cast(pRawMem); - m_StaticResCaches = reinterpret_cast(m_ShaderResourceLayouts + GetNumShaderTypes() * 2); - m_StaticVarsMgrs = reinterpret_cast(m_StaticResCaches + GetNumShaderTypes()); + m_StaticResCaches = reinterpret_cast(m_ShaderResourceLayouts + GetNumShaderStages() * 2); + m_StaticVarsMgrs = reinterpret_cast(m_StaticResCaches + GetNumShaderStages()); for (size_t s = 0; s < ShaderStages.size(); ++s) { + auto& StageInfo = ShaderStages[s]; + const auto ShaderType = StageInfo.Type; + const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); + new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice}; - const auto ShaderType = ShaderStages[s].first; - auto& Shaders = ShaderStages[s].second; - const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); + m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); auto* pStaticResLayout = new (m_ShaderResourceLayouts + ShaderStages.size() + s) ShaderResourceLayoutVk{LogicalDevice}; auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources}; - pStaticResLayout->InitializeStaticResourceLayout(Shaders, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); + pStaticResLayout->InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache}; } ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(), - m_Desc.ResourceLayout, ShaderSPIRVs, m_PipelineLayout, + m_Desc.ResourceLayout, m_PipelineLayout, (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); m_PipelineLayout.Finalize(LogicalDevice); @@ -465,7 +454,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun if (m_Desc.SRBAllocationGranularity > 1) { std::array ShaderVariableDataSizes = {}; - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; @@ -477,13 +466,13 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets); auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data()); - m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderTypes(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize); + m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize); } // Create shader modules and initialize shader stages std::vector VkShaderStages; std::vector ShaderModules; - InitializeShaderStages(LogicalDevice, ShaderStages, ShaderSPIRVs, ShaderModules, VkShaderStages); + InitPipelineShaderStages(LogicalDevice, ShaderStages, ShaderModules, VkShaderStages); // Create pipeline switch (m_Desc.PipelineType) @@ -498,7 +487,7 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun m_HasStaticResources = false; m_HasNonStaticResources = false; - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { const auto& Layout = m_ShaderResourceLayouts[s]; if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_STATIC) != 0) @@ -518,12 +507,12 @@ PipelineStateVkImpl::~PipelineStateVkImpl() m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask); auto& RawAllocator = GetRawAllocator(); - for (Uint32 s = 0; s < GetNumShaderTypes() * 2; ++s) + for (Uint32 s = 0; s < GetNumShaderStages() * 2; ++s) { m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); } - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { m_StaticResCaches[s].~ShaderResourceCacheVk(); m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); @@ -563,14 +552,14 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const #ifdef DILIGENT_DEBUG { bool IsCompatibleShaders = true; - if (GetNumShaderTypes() != pPSOVk->GetNumShaderTypes()) + if (GetNumShaderStages() != pPSOVk->GetNumShaderStages()) IsCompatibleShaders = false; if (IsCompatibleShaders) { - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { - if (GetShaderTypes()[s] != pPSOVk->GetShaderTypes()[s]) + if (GetShaderStageType(s) != pPSOVk->GetShaderStageType(s)) { IsCompatibleShaders = false; break; @@ -636,7 +625,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind auto& ResourceCache = pResBindingVkImpl->GetResourceCache(); #ifdef DILIGENT_DEVELOPMENT - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { m_ShaderResourceLayouts[s].dvpVerifyBindings(ResourceCache); } @@ -671,7 +660,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind // Allocate vulkan descriptor set for dynamic resources DynamicDescrSet = pCtxVkImpl->AllocateDynamicDescriptorSet(DynamicDescriptorSetVkLayout, DynamicDescrSetName); // Commit all dynamic resource descriptors - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { const auto& Layout = m_ShaderResourceLayouts[s]; if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0) @@ -688,7 +677,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind void PipelineStateVkImpl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags) { - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { auto ShaderType = GetStaticShaderResLayout(s).GetShaderType(); if ((ShaderType & ShaderFlags) != 0) @@ -732,7 +721,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const { - for (Uint32 s = 0; s < GetNumShaderTypes(); ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { const auto& StaticResLayout = GetStaticShaderResLayout(s); const auto& StaticResCache = GetStaticResCache(s); @@ -742,7 +731,7 @@ void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& Re { LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", GetDesc().Name, "' will not be successfully initialized because not all static resource bindings in shader '", - GetShaderTypeLiteralName(GetShaderTypes()[s]), + GetShaderTypeLiteralName(GetShaderStageType(s)), "' 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."); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 75f3bb37..91008811 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -49,8 +49,7 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR { m_ResourceLayoutIndex.fill(-1); - auto* pShaderTypes = pPSO->GetShaderTypes(); - m_NumShaders = static_cast(pPSO->GetNumShaderTypes()); + m_NumShaders = static_cast(pPSO->GetNumShaderStages()); auto* pRenderDeviceVkImpl = pPSO->GetDevice(); // This will only allocate memory and initialize descriptor sets in the resource cache @@ -62,7 +61,7 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR for (Uint32 s = 0; s < m_NumShaders; ++s) { - auto ShaderInd = GetShaderTypePipelineIndex(pShaderTypes[s], pPSO->GetDesc().PipelineType); + auto ShaderInd = GetShaderTypePipelineIndex(pPSO->GetShaderStageType(s), pPSO->GetDesc().PipelineType); m_ResourceLayoutIndex[ShaderInd] = static_cast(s); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index a7410210..8b00c394 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -93,6 +93,14 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE } } +ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE _Type, + const ShaderVkImpl* _pShader) : + Type{_Type}, + pShader{_pShader}, + SPIRV{pShader->GetSPIRV()} +{ +} + ShaderResourceLayoutVk::~ShaderResourceLayoutVk() { @@ -103,7 +111,7 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk() GetImmutableSampler(s).~ImmutableSamplerPtrType(); } -void ShaderResourceLayoutVk::AllocateMemory(IShader* pShader, +void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* pShader, IMemoryAllocator& Allocator, const PipelineResourceLayoutDesc& ResourceLayoutDesc, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, @@ -112,16 +120,14 @@ void ShaderResourceLayoutVk::AllocateMemory(IShader* { VERIFY(!m_ResourceBuffer, "Memory has already been initialized"); VERIFY_EXPR(!m_pResources); + m_pResources = pShader->GetShaderResources(); - const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); - const auto ShaderType = pShader->GetDesc().ShaderType; + const auto ShaderType = pShader->GetDesc().ShaderType; + VERIFY_EXPR(m_pResources->GetShaderType() == ShaderType); // Count the number of resources to allocate all needed memory { - auto* pShaderVk = ValidatedCast(pShader); - auto pResources = pShaderVk->GetShaderResources(); - const auto* CombinedSamplerSuffix = pResources->GetCombinedSamplerSuffix(); - VERIFY_EXPR(pResources->GetShaderType() == ShaderType); - m_pResources = pResources; + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); + const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix(); m_pResources->ProcessResources( [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) // { @@ -172,11 +178,11 @@ void ShaderResourceLayoutVk::AllocateMemory(IShader* } -Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, - const SPIRVShaderResources& Resources, - const SPIRVShaderResourceAttribs& SepImg, - Uint32 CurrResourceCount, - SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) +static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, + const SPIRVShaderResources& Resources, + const SPIRVShaderResourceAttribs& SepImg, + Uint32 CurrResourceCount, + SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) { using VkResource = ShaderResourceLayoutVk::VkResource; VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage); @@ -211,7 +217,7 @@ Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout, } -void ShaderResourceLayoutVk::InitializeStaticResourceLayout(IShader* pShader, +void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const ShaderVkImpl* pShader, IMemoryAllocator& LayoutDataAllocator, const PipelineResourceLayoutDesc& ResourceLayoutDesc, ShaderResourceCacheVk& StaticResourceCache) @@ -277,7 +283,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(IShader* } #ifdef DILIGENT_DEVELOPMENT -void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const ShaderStages_t& ShaderStages, +void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& ShaderStages, const PipelineResourceLayoutDesc& ResourceLayoutDesc, bool VerifyVariables, bool VerifyStaticSamplers) @@ -290,11 +296,11 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const ShaderStages_t& const auto ShaderType = Stages & static_cast(~(static_cast(Stages) - 1)); const char* ShaderName = nullptr; - for (size_t s = 0; s < ShaderStages.size(); ++s) + for (const auto& StageInfo : ShaderStages) { - if ((Stages & ShaderStages[s].first) != 0) + if ((Stages & StageInfo.Type) != 0) { - ShaderName = ShaderStages[s].second->GetDesc().Name; + ShaderName = StageInfo.pShader->GetDesc().Name; break; } } @@ -334,8 +340,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const ShaderStages_t& bool VariableFound = false; for (size_t s = 0; s < ShaderStages.size() && !VariableFound; ++s) { - const auto* pShaderVk = ValidatedCast(ShaderStages[s].second); - const auto& Resources = *pShaderVk->GetShaderResources(); + const auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0) { for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res) @@ -368,8 +373,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const ShaderStages_t& bool SamplerFound = false; for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s) { - const auto* pShaderVk = ValidatedCast(ShaderStages[s].second); - const auto& Resources = *pShaderVk->GetShaderResources(); + const auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0) continue; @@ -407,11 +411,10 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const ShaderStages_t& #endif void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice, - const ShaderStages_t& ShaderStages, + TShaderStages& ShaderStages, ShaderResourceLayoutVk Layouts[], IMemoryAllocator& LayoutDataAllocator, const PipelineResourceLayoutDesc& ResourceLayoutDesc, - ShaderSPIRVs_t& SPIRVs, class PipelineLayout& PipelineLayout, bool VerifyVariables, bool VerifyStaticSamplers) @@ -427,7 +430,8 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende for (size_t s = 0; s < ShaderStages.size(); ++s) { - Layouts[s].AllocateMemory(ShaderStages[s].second, LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers); + Layouts[s].AllocateMemory(ShaderStages[s].pShader, LayoutDataAllocator, ResourceLayoutDesc, + AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers); } //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE); @@ -475,7 +479,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende } } - auto& ShaderSPIRV = SPIRVs[ShaderInd]; + auto& ShaderSPIRV = ShaderStages[ShaderInd].SPIRV; PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV); VERIFY(DescriptorSet <= std::numeric_limits::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value"); VERIFY(Binding <= std::numeric_limits::max(), "Binding (", Binding, ") excceeds maximum representable value"); @@ -498,9 +502,8 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende // First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& pShader = ShaderStages[s].second; auto& Layout = Layouts[s]; - auto* pShaderVk = ValidatedCast(pShader); + auto* pShaderVk = ShaderStages[s].pShader; auto& Resources = *pShaderVk->GetShaderResources(); for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n) { @@ -516,10 +519,8 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende // Second, process all storage buffers for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& pShader = ShaderStages[s].second; auto& Layout = Layouts[s]; - auto* pShaderVk = ValidatedCast(pShader); - auto& Resources = *pShaderVk->GetShaderResources(); + auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n) { const auto& SB = Resources.GetSB(n); @@ -534,10 +535,8 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende // Finally, process all other resource types for (size_t s = 0; s < ShaderStages.size(); ++s) { - auto& pShader = ShaderStages[s].second; auto& Layout = Layouts[s]; - auto* pShaderVk = ValidatedCast(pShader); - auto& Resources = *pShaderVk->GetShaderResources(); + auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); // clang-format off Resources.ProcessResources( [&](const SPIRVShaderResourceAttribs& UB, Uint32) diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp index 95261295..55bb7d8f 100644 --- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp +++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp @@ -1515,7 +1515,7 @@ VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags) VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType) { static_assert(SHADER_TYPE_LAST == SHADER_TYPE_MESH, "Please update the switch below to handle the new shader type"); - VERIFY((ShaderType & (ShaderType - 1)) == 0, "More than one shader type specified"); + VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "More than one shader type is specified"); switch (ShaderType) { // clang-format off -- cgit v1.2.3 From dfa6286f153dd5273423f5ab169f6cc8a0a53c76 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 13 Oct 2020 20:25:00 -0700 Subject: Updated shader resource layout tests to work on Metal --- Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h | 1 + Graphics/GraphicsEngineMetal/interface/SamplerMtl.h | 1 + 2 files changed, 2 insertions(+) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h b/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h index 97b36dbc..d5561b58 100644 --- a/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h +++ b/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h @@ -41,6 +41,7 @@ static const INTERFACE_ID IID_BufferViewMtl = class IBufferViewMtl : public IBufferView { public: + virtual id GetMtlTextureView() const = 0; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h b/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h index 51057dad..a8290e07 100644 --- a/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h +++ b/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h @@ -41,6 +41,7 @@ static const INTERFACE_ID IID_SamplerMtl = class ISamplerMtl : public ISampler { public: + virtual id GetMtlSampler() = 0; }; } // namespace Diligent -- cgit v1.2.3 From b3fec8bd40e80115086281bce74774617aa95e23 Mon Sep 17 00:00:00 2001 From: assiduous Date: Wed, 14 Oct 2020 01:04:05 -0700 Subject: Added buffer mode validation when binding buffer views --- Graphics/GraphicsEngine/include/BufferBase.hpp | 10 ++++- Graphics/GraphicsEngine/include/TextureBase.hpp | 3 +- .../src/ShaderResourceLayoutD3D11.cpp | 2 + .../src/ShaderResourceLayoutD3D12.cpp | 12 ++++++ .../include/ShaderVariableD3DBase.hpp | 49 ++++++++++++++++++++++ .../src/GLPipelineResourceLayout.cpp | 30 +++++++++++++ .../src/ShaderResourceLayoutVk.cpp | 20 +++++++++ 7 files changed, 124 insertions(+), 2 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp index 9ae6db92..605bc2ed 100644 --- a/Graphics/GraphicsEngine/include/BufferBase.hpp +++ b/Graphics/GraphicsEngine/include/BufferBase.hpp @@ -30,12 +30,14 @@ /// \file /// Implementation of the Diligent::BufferBase template class +#include + #include "Buffer.h" #include "GraphicsTypes.h" #include "DeviceObjectBase.hpp" #include "GraphicsAccessories.hpp" #include "STDAllocator.hpp" -#include +#include "FormatString.hpp" namespace Diligent { @@ -232,6 +234,9 @@ void BufferBasem_Desc.Name, '\''); + ViewDesc.Name = UAVName.c_str(); + IBufferView* pUAV = nullptr; CreateViewInternal(ViewDesc, &pUAV, true); m_pDefaultUAV.reset(static_cast(pUAV)); @@ -242,6 +247,9 @@ void BufferBasem_Desc.Name, '\''); + ViewDesc.Name = SRVName.c_str(); + IBufferView* pSRV = nullptr; CreateViewInternal(ViewDesc, &pSRV, true); m_pDefaultSRV.reset(static_cast(pSRV)); diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp index 1805f7d3..559df1ea 100644 --- a/Graphics/GraphicsEngine/include/TextureBase.hpp +++ b/Graphics/GraphicsEngine/include/TextureBase.hpp @@ -30,13 +30,14 @@ /// \file /// Implementation of the Diligent::TextureBase template class +#include + #include "Texture.h" #include "GraphicsTypes.h" #include "DeviceObjectBase.hpp" #include "GraphicsAccessories.hpp" #include "STDAllocator.hpp" #include "FormatString.hpp" -#include namespace Diligent { diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index fd6c7299..63b34f44 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -553,6 +553,7 @@ void ShaderResourceLayoutD3D11::BuffSRVBindInfo::BindResource(IDeviceObject* pVi { 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)); @@ -593,6 +594,7 @@ void ShaderResourceLayoutD3D11::BuffUAVBindInfo::BindResource(IDeviceObject* pVi { 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)); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 6c313882..f00d62e7 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -38,6 +38,7 @@ #include "RootSignature.hpp" #include "PipelineStateD3D12Impl.hpp" #include "ShaderResourceVariableBase.hpp" +#include "ShaderVariableD3DBase.hpp" namespace Diligent { @@ -429,6 +430,11 @@ template <> struct ResourceViewTraits { static const INTERFACE_ID& IID; + + static bool VerifyView(ITextureViewD3D12* pViewD3D12, const D3DShaderResourceAttribs& Attribs, const char* ShaderName) + { + return true; + } }; const INTERFACE_ID& ResourceViewTraits::IID = IID_TextureViewD3D12; @@ -436,6 +442,11 @@ template <> struct ResourceViewTraits { static const INTERFACE_ID& IID; + + static bool VerifyView(IBufferViewD3D12* pViewD3D12, const D3DShaderResourceAttribs& Attribs, const char* ShaderName) + { + return VerifyBufferViewModeD3D(pViewD3D12, Attribs, ShaderName); + } }; const INTERFACE_ID& ResourceViewTraits::IID = IID_BufferViewD3D12; @@ -454,6 +465,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject* RefCntAutoPtr pViewD3D12(pView, ResourceViewTraits::IID); #ifdef DILIGENT_DEVELOPMENT VerifyResourceViewBinding(Attribs, GetVariableType(), ArrayIndex, pView, pViewD3D12.RawPtr(), {dbgExpectedViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + ResourceViewTraits::VerifyView(pViewD3D12, Attribs, ParentResLayout.GetShaderName()); #endif if (pViewD3D12) { diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp index 0ea6e397..2497b17d 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp @@ -86,4 +86,53 @@ protected: const SHADER_RESOURCE_VARIABLE_TYPE m_VariableType; }; + +template +bool VerifyBufferViewModeD3D(BufferViewImplType* pViewD3D11, const D3DShaderResourceAttribs& Attribs, const char* ShaderName) +{ + if (pViewD3D11 == nullptr) + return true; + + const auto& ViewDesc = pViewD3D11->GetDesc(); + const auto& BuffDesc = pViewD3D11->GetBuffer()->GetDesc(); + + auto LogBufferBindingError = [&](const char* Msg) // + { + LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, + "' to shader variable '", Attribs.Name, "' in shader '", ShaderName, "': ", Msg); + }; + + switch (Attribs.GetInputType()) + { + case D3D_SIT_TEXTURE: + case D3D_SIT_UAV_RWTYPED: + if (BuffDesc.Mode != BUFFER_MODE_FORMATTED || ViewDesc.Format.ValueType == VT_UNDEFINED) + { + LogBufferBindingError("formatted buffer view is expected."); + return false; + } + break; + + case D3D_SIT_STRUCTURED: + case D3D_SIT_UAV_RWSTRUCTURED: + if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED) + { + LogBufferBindingError("structured buffer view is expected."); + return false; + } + break; + + case D3D_SIT_BYTEADDRESS: + case D3D_SIT_UAV_RWBYTEADDRESS: + if (BuffDesc.Mode != BUFFER_MODE_RAW) + { + LogBufferBindingError("raw buffer view is expected."); + return false; + } + break; + } + + return true; +} + } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp index 0955a54f..914a09bb 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp @@ -307,6 +307,16 @@ void GLPipelineResourceLayout::SamplerBindInfo::BindResource(IDeviceObject* pVie { auto& CachedBuffSampler = ResourceCache.GetConstSampler(m_Attribs.Binding + ArrayIndex); VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE}, CachedBuffSampler.pView.RawPtr()); + if (pViewGL != nullptr) + { + const auto& ViewDesc = pViewGL->GetDesc(); + const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc(); + if (!(BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED || BuffDesc.Mode == BUFFER_MODE_RAW)) + { + LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + m_Attribs.Name, ": formatted buffer view is expected."); + } + } } #endif ResourceCache.SetBufSampler(m_Attribs.Binding + ArrayIndex, std::move(pViewGL)); @@ -347,6 +357,16 @@ void GLPipelineResourceLayout::ImageBindInfo::BindResource(IDeviceObject* pView, { auto& CachedUAV = ResourceCache.GetConstImage(m_Attribs.Binding + ArrayIndex); VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {BUFFER_VIEW_UNORDERED_ACCESS}, CachedUAV.pView.RawPtr()); + if (pViewGL != nullptr) + { + const auto& ViewDesc = pViewGL->GetDesc(); + const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc(); + if (!(BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED || BuffDesc.Mode == BUFFER_MODE_RAW)) + { + LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + m_Attribs.Name, ": formatted buffer view is expected."); + } + } } #endif ResourceCache.SetBufImage(m_Attribs.Binding + ArrayIndex, std::move(pViewGL)); @@ -375,6 +395,16 @@ void GLPipelineResourceLayout::StorageBufferBindInfo::BindResource(IDeviceObject auto& CachedSSBO = ResourceCache.GetConstSSBO(m_Attribs.Binding + ArrayIndex); // HLSL structured buffers are mapped to SSBOs in GLSL VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE, BUFFER_VIEW_UNORDERED_ACCESS}, CachedSSBO.pBufferView.RawPtr()); + if (pViewGL != nullptr) + { + const auto& ViewDesc = pViewGL->GetDesc(); + const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc(); + if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW) + { + LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + m_Attribs.Name, ": structured buffer view is expected."); + } + } } #endif ResourceCache.SetSSBO(m_Attribs.Binding + ArrayIndex, std::move(pViewGL)); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 8b00c394..7f726e69 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -702,6 +702,16 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject* // HLSL buffer SRVs are mapped to storge buffers in GLSL auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS; VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + if (pBufferViewVk != nullptr) + { + const auto& ViewDesc = pBufferViewVk->GetDesc(); + const auto& BuffDesc = pBufferViewVk->GetBuffer()->GetDesc(); + if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW) + { + LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected."); + } + } } #endif @@ -748,6 +758,16 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* // HLSL buffer SRVs are mapped to storge buffers in GLSL auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE; VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); + if (pBufferViewVk != nullptr) + { + const auto& ViewDesc = pBufferViewVk->GetDesc(); + const auto& BuffDesc = pBufferViewVk->GetBuffer()->GetDesc(); + if (!(BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED || BuffDesc.Mode == BUFFER_MODE_RAW)) + { + LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", + SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected."); + } + } } #endif -- cgit v1.2.3 From 259a9d5897937dcaaca1b4b294bb8d5250371e76 Mon Sep 17 00:00:00 2001 From: azhirnov Date: Thu, 15 Oct 2020 20:55:38 +0300 Subject: Added GraphicsPipelineCreateInfo and ComputePipelineCreateInfo instead of single PipelineCreateInfo. Some optimizations for dynamic memory allocations in PipelineState. --- .../GraphicsEngine/include/DeviceContextBase.hpp | 2 +- .../GraphicsEngine/include/PipelineStateBase.hpp | 439 ++++++++-------- Graphics/GraphicsEngine/interface/InputLayout.h | 2 +- Graphics/GraphicsEngine/interface/PipelineState.h | 89 ++-- Graphics/GraphicsEngine/interface/RenderDevice.h | 49 +- Graphics/GraphicsEngine/src/APIInfo.cpp | 1 - .../include/PipelineStateD3D11Impl.hpp | 17 +- .../include/RenderDeviceD3D11Impl.hpp | 10 +- .../src/DeviceContextD3D11Impl.cpp | 10 +- .../src/PipelineStateD3D11Impl.cpp | 229 ++++---- .../src/RenderDeviceD3D11Impl.cpp | 13 +- .../include/PipelineStateD3D12Impl.hpp | 24 +- .../include/RenderDeviceD3D12Impl.hpp | 7 +- .../src/DeviceContextD3D12Impl.cpp | 65 ++- .../src/PipelineStateD3D12Impl.cpp | 575 +++++++++++---------- .../src/RenderDeviceD3D12Impl.cpp | 13 +- .../include/PipelineStateGLImpl.hpp | 35 +- .../include/RenderDeviceGLImpl.hpp | 20 +- .../src/DeviceContextGLImpl.cpp | 6 +- .../src/PipelineStateGLImpl.cpp | 140 +++-- .../src/RenderDeviceGLImpl.cpp | 25 +- .../GraphicsEngineOpenGL/src/TexRegionRender.cpp | 17 +- Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp | 2 +- .../include/PipelineStateVkImpl.hpp | 14 +- .../include/RenderDeviceVkImpl.hpp | 7 +- .../src/DeviceContextVkImpl.cpp | 68 +-- .../src/GenerateMipsVkHelper.cpp | 12 +- .../src/PipelineStateVkImpl.cpp | 147 ++++-- .../src/RenderDeviceVkImpl.cpp | 16 +- 29 files changed, 1198 insertions(+), 856 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 86cccc7b..90285834 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1678,7 +1678,7 @@ inline void DeviceContextBase:: BoundDSVFormat = m_pBoundDepthStencil ? m_pBoundDepthStencil->GetDesc().Format : TEX_FORMAT_UNKNOWN; const auto& PSODesc = m_pPipelineState->GetDesc(); - const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; + const auto& GraphicsPipeline = m_pPipelineState->GetGraphicsPipelineDesc(); if (GraphicsPipeline.NumRenderTargets != m_NumBoundRenderTargets) { LOG_WARNING_MESSAGE("The number of currently bound render targets (", m_NumBoundRenderTargets, diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index 09f1bddc..d8cb09bb 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -38,7 +38,7 @@ #include "STDAllocator.hpp" #include "EngineMemory.h" #include "GraphicsAccessories.hpp" -#include "StringPool.hpp" +#include "LinearAllocator.hpp" namespace Diligent { @@ -59,7 +59,7 @@ public: /// \param pRefCounters - reference counters object that controls the lifetime of this PSO /// \param pDevice - pointer to the device. - /// \param PSODesc - pipeline state description. + /// \param CreateInfo - graphics pipeline state create info. /// \param bIsDeviceInternal - flag indicating if the pipeline state is an internal device object and /// must not keep a strong reference to the device. PipelineStateBase(IReferenceCounters* pRefCounters, @@ -68,96 +68,6 @@ public: bool bIsDeviceInternal = false) : TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal} { - switch (PSODesc.PipelineType) - { - // clang-format off - case PIPELINE_TYPE_GRAPHICS: - case PIPELINE_TYPE_MESH: ValidateGraphicsPipeline(); break; - case PIPELINE_TYPE_COMPUTE: ValidateComputePipeline(); break; - default: UNEXPECTED("unknown pipeline type"); - // clang-format on - } - - const auto& SrcLayout = PSODesc.ResourceLayout; - size_t StringPoolSize = 0; - if (SrcLayout.Variables != nullptr) - { - for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) - { - VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); - StringPoolSize += strlen(SrcLayout.Variables[i].Name) + 1; - } - } - - if (SrcLayout.StaticSamplers != nullptr) - { - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) - { - VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); - StringPoolSize += strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1; - } - } - - if (PSODesc.IsAnyGraphicsPipeline()) - { - const auto& InputLayout = this->m_Desc.GraphicsPipeline.InputLayout; - for (Uint32 i = 0; i < InputLayout.NumElements; ++i) - StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1; - } - - m_StringPool.Reserve(StringPoolSize, GetRawAllocator()); - - auto& DstLayout = this->m_Desc.ResourceLayout; - if (SrcLayout.Variables != nullptr) - { - ShaderResourceVariableDesc* Variables = - ALLOCATE(GetRawAllocator(), "Memory for ShaderResourceVariableDesc array", ShaderResourceVariableDesc, SrcLayout.NumVariables); - DstLayout.Variables = Variables; - for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) - { - Variables[i] = SrcLayout.Variables[i]; - Variables[i].Name = m_StringPool.CopyString(SrcLayout.Variables[i].Name); - } - } - - if (SrcLayout.StaticSamplers != nullptr) - { - StaticSamplerDesc* StaticSamplers = - ALLOCATE(GetRawAllocator(), "Memory for StaticSamplerDesc array", StaticSamplerDesc, SrcLayout.NumStaticSamplers); - DstLayout.StaticSamplers = StaticSamplers; - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) - { -#ifdef DILIGENT_DEVELOPMENT - { - const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor; - if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) || - (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) || - (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1))) - { - LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcLayout.StaticSamplers[i].SamplerOrTextureName, "\" specifies border color (", - BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3], - "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors"); - } - } -#endif - - StaticSamplers[i] = SrcLayout.StaticSamplers[i]; - StaticSamplers[i].SamplerOrTextureName = m_StringPool.CopyString(SrcLayout.StaticSamplers[i].SamplerOrTextureName); - } - } - - switch (PSODesc.PipelineType) - { - // clang-format off - case PIPELINE_TYPE_GRAPHICS: - case PIPELINE_TYPE_MESH: InitGraphicsPipeline(); break; - case PIPELINE_TYPE_COMPUTE: InitComputePipeline(); break; - default: UNEXPECTED("unknown pipeline type"); - // clang-format on - } - - VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0); - Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask(); DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0, "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask, @@ -184,16 +94,6 @@ public: RasterizerStateRegistry.ReportDeletedObject(); DSSRegistry.ReportDeletedObject(); */ - - auto& RawAllocator = GetRawAllocator(); - if (this->m_Desc.ResourceLayout.Variables != nullptr) - RawAllocator.Free(const_cast(this->m_Desc.ResourceLayout.Variables)); - if (this->m_Desc.ResourceLayout.StaticSamplers != nullptr) - RawAllocator.Free(const_cast(this->m_Desc.ResourceLayout.StaticSamplers)); - if (this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements != nullptr) - RawAllocator.Free(const_cast(this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements)); - if (m_pStrides != nullptr) - RawAllocator.Free(m_pStrides); } IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase) @@ -218,20 +118,28 @@ public: return m_ShaderResourceLayoutHash != ValidatedCast(pPSO)->m_ShaderResourceLayoutHash; } -protected: - Uint32 m_BufferSlotsUsed = 0; - Uint32* m_pStrides = nullptr; + const GraphicsPipelineDesc& GetGraphicsPipelineDesc() const override final + { + VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline()); + VERIFY_EXPR(m_pGraphicsPipelineDesc != nullptr); + return *m_pGraphicsPipelineDesc; + } - StringPool m_StringPool; - RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object +protected: + size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout + + Uint32* m_pStrides = nullptr; + Uint8 m_BufferSlotsUsed = 0; Uint8 m_NumShaderStages = 0; ///< Number of shader stages in this PSO /// Array of shader types for every shader stage used by this PSO std::array m_ShaderStageTypes = {}; - size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout + RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object + + GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr; protected: #define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(this->m_Desc.PipelineType), " PSO '", this->m_Desc.Name, "' is invalid: ", ##__VA_ARGS__) @@ -296,74 +204,19 @@ protected: return LayoutInd; } - -protected: - template - void ExtractShaders(TShaderStages& ShaderStages) - { - VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); - - ShaderStages.clear(); - auto AddShaderStage = [&](IShader*& pShader) { - if (pShader != nullptr) - { - auto ShaderType = pShader->GetDesc().ShaderType; - ShaderStages.emplace_back(ShaderType, ValidatedCast(pShader)); - m_ShaderStageTypes[m_NumShaderStages++] = ShaderType; - - // Reset shader pointers in PSO desc because we don't keep strong references to shaders. - pShader = nullptr; - } - }; - - auto& Desc = this->m_Desc; - switch (Desc.PipelineType) - { - case PIPELINE_TYPE_COMPUTE: - { - AddShaderStage(Desc.ComputePipeline.pCS); - break; - } - - case PIPELINE_TYPE_GRAPHICS: - { - AddShaderStage(Desc.GraphicsPipeline.pVS); - AddShaderStage(Desc.GraphicsPipeline.pHS); - AddShaderStage(Desc.GraphicsPipeline.pDS); - AddShaderStage(Desc.GraphicsPipeline.pGS); - AddShaderStage(Desc.GraphicsPipeline.pPS); - break; - } - - case PIPELINE_TYPE_MESH: - { - AddShaderStage(Desc.GraphicsPipeline.pAS); - AddShaderStage(Desc.GraphicsPipeline.pMS); - AddShaderStage(Desc.GraphicsPipeline.pPS); - break; - } - - default: - UNEXPECTED("unknown pipeline type"); - } - - VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); - } - - private: - void CheckRasterizerStateDesc() const + void CheckRasterizerStateDesc(GraphicsPipelineDesc& GraphicsPipeline) const { - const auto& RSDesc = this->m_Desc.GraphicsPipeline.RasterizerDesc; + const auto& RSDesc = GraphicsPipeline.RasterizerDesc; if (RSDesc.FillMode == FILL_MODE_UNDEFINED) LOG_PSO_ERROR_AND_THROW("RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED"); if (RSDesc.CullMode == CULL_MODE_UNDEFINED) LOG_PSO_ERROR_AND_THROW("RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED"); } - void CheckAndCorrectDepthStencilDesc() + void CheckAndCorrectDepthStencilDesc(GraphicsPipelineDesc& GraphicsPipeline) const { - auto& DSSDesc = this->m_Desc.GraphicsPipeline.DepthStencilDesc; + auto& DSSDesc = GraphicsPipeline.DepthStencilDesc; if (DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN) { if (DSSDesc.DepthEnable) @@ -401,9 +254,9 @@ private: CheckAndCorrectStencilOpDesc(DSSDesc.BackFace, "BackFace"); } - void CheckAndCorrectBlendStateDesc() + void CheckAndCorrectBlendStateDesc(GraphicsPipelineDesc& GraphicsPipeline) const { - auto& BlendDesc = this->m_Desc.GraphicsPipeline.BlendDesc; + auto& BlendDesc = GraphicsPipeline.BlendDesc; for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) { auto& RTDesc = BlendDesc.RenderTargets[rt]; @@ -449,9 +302,31 @@ private: } } - void ValidateGraphicsPipeline() + void ValidateResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) const + { + if (SrcLayout.Variables != nullptr) + { + MemPool.AddRequiredSize(SrcLayout.NumVariables); + for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) + { + VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); + MemPool.AddRequiredSize(strlen(SrcLayout.Variables[i].Name) + 1); + } + } + + if (SrcLayout.StaticSamplers != nullptr) + { + MemPool.AddRequiredSize(SrcLayout.NumStaticSamplers); + for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + { + VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); + MemPool.AddRequiredSize(strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1); + } + } + } + + void ValidateGraphicsPipeline(const GraphicsPipelineDesc& GraphicsPipeline, LinearAllocator& MemPool) const { - const auto& GraphicsPipeline = this->m_Desc.GraphicsPipeline; if (GraphicsPipeline.pRenderPass != nullptr) { if (GraphicsPipeline.NumRenderTargets != 0) @@ -475,48 +350,182 @@ private: LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used"); } - CheckAndCorrectBlendStateDesc(); - CheckRasterizerStateDesc(); - CheckAndCorrectDepthStencilDesc(); + const auto& InputLayout = GraphicsPipeline.InputLayout; + Uint32 BufferSlotsUsed = 0; + MemPool.AddRequiredSize(InputLayout.NumElements); + for (Uint32 i = 0; i < InputLayout.NumElements; ++i) + { + auto& LayoutElem = InputLayout.LayoutElements[i]; + MemPool.AddRequiredSize(strlen(LayoutElem.HLSLSemantic) + 1); + BufferSlotsUsed = std::max(BufferSlotsUsed, LayoutElem.BufferSlot + 1); + } + + MemPool.AddRequiredSize(BufferSlotsUsed); } - void ValidateComputePipeline() + void InitResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) const { - if (this->m_Desc.GraphicsPipeline.pRenderPass != nullptr) + if (SrcLayout.Variables != nullptr) { - LOG_PSO_ERROR_AND_THROW("GraphicsPipeline.pRenderPass must be null for compute pipelines"); + auto* Variables = MemPool.Allocate(SrcLayout.NumVariables); + DstLayout.Variables = Variables; + for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) + { + Variables[i] = SrcLayout.Variables[i]; + Variables[i].Name = MemPool.CopyString(SrcLayout.Variables[i].Name); + } + } + + if (SrcLayout.StaticSamplers != nullptr) + { + auto* StaticSamplers = MemPool.Allocate(SrcLayout.NumStaticSamplers); + DstLayout.StaticSamplers = StaticSamplers; + for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + { +#ifdef DILIGENT_DEVELOPMENT + { + const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor; + if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) || + (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) || + (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1))) + { + LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcLayout.StaticSamplers[i].SamplerOrTextureName, "\" specifies border color (", + BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3], + "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors"); + } + } +#endif + + StaticSamplers[i] = SrcLayout.StaticSamplers[i]; + StaticSamplers[i].SamplerOrTextureName = MemPool.CopyString(SrcLayout.StaticSamplers[i].SamplerOrTextureName); + } } - DEV_CHECK_ERR(this->m_Desc.GraphicsPipeline.InputLayout.NumElements == 0, "Compute pipelines must not have input layout elements"); } +protected: #define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \ if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \ { \ LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ } - void InitGraphicsPipeline() + void ValidateAndReserveSpace(const GraphicsPipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) const + { + VALIDATE_SHADER_TYPE(CreateInfo.pVS, SHADER_TYPE_VERTEX, "vertex") + VALIDATE_SHADER_TYPE(CreateInfo.pPS, SHADER_TYPE_PIXEL, "pixel") + VALIDATE_SHADER_TYPE(CreateInfo.pGS, SHADER_TYPE_GEOMETRY, "geometry") + VALIDATE_SHADER_TYPE(CreateInfo.pHS, SHADER_TYPE_HULL, "hull") + VALIDATE_SHADER_TYPE(CreateInfo.pDS, SHADER_TYPE_DOMAIN, "domain") + VALIDATE_SHADER_TYPE(CreateInfo.pAS, SHADER_TYPE_AMPLIFICATION, "amplification") + VALIDATE_SHADER_TYPE(CreateInfo.pMS, SHADER_TYPE_MESH, "mesh") + + MemPool.AddRequiredSize(1); + ValidateResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + + ValidateGraphicsPipeline(CreateInfo.GraphicsPipeline, MemPool); + } + + void ValidateAndReserveSpace(const ComputePipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) const { + if (CreateInfo.pCS == nullptr) + { + LOG_ERROR_AND_THROW("Compute shader is not provided"); + } + VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute"); + + ValidateResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); + } + + template + void ExtractShaders(const GraphicsPipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages) + { + VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + + ShaderStages.clear(); + auto AddShaderStage = [&](IShader* pShader) { + if (pShader != nullptr) + { + auto ShaderType = pShader->GetDesc().ShaderType; + ShaderStages.emplace_back(ShaderType, ValidatedCast(pShader)); + m_ShaderStageTypes[m_NumShaderStages++] = ShaderType; + } + }; + + switch (CreateInfo.PSODesc.PipelineType) + { + case PIPELINE_TYPE_GRAPHICS: + { + AddShaderStage(CreateInfo.pVS); + AddShaderStage(CreateInfo.pHS); + AddShaderStage(CreateInfo.pDS); + AddShaderStage(CreateInfo.pGS); + AddShaderStage(CreateInfo.pPS); + break; + } + + case PIPELINE_TYPE_MESH: + { + AddShaderStage(CreateInfo.pAS); + AddShaderStage(CreateInfo.pMS); + AddShaderStage(CreateInfo.pPS); + break; + } + + default: + UNEXPECTED("unknown pipeline type"); + } + + VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); + } + + template + void ExtractShaders(const ComputePipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages) + { + VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); + + ShaderStages.clear(); + auto AddShaderStage = [&](IShader* pShader) { + if (pShader != nullptr) + { + auto ShaderType = pShader->GetDesc().ShaderType; + ShaderStages.emplace_back(ShaderType, ValidatedCast(pShader)); + m_ShaderStageTypes[m_NumShaderStages++] = ShaderType; + } + }; + + AddShaderStage(CreateInfo.pCS); + + VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); + } + + + void InitGraphicsPipeline(const GraphicsPipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) + { + this->m_pGraphicsPipelineDesc = MemPool.CopyArray(&CreateInfo.GraphicsPipeline, 1); + + InitResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + + auto& GraphicsPipeline = *this->m_pGraphicsPipelineDesc; const auto& PSODesc = this->m_Desc; - const auto& GraphicsPipeline = PSODesc.GraphicsPipeline; - VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pAS, SHADER_TYPE_AMPLIFICATION, "amplification") - VALIDATE_SHADER_TYPE(GraphicsPipeline.pMS, SHADER_TYPE_MESH, "mesh") + CheckAndCorrectBlendStateDesc(GraphicsPipeline); + CheckRasterizerStateDesc(GraphicsPipeline); + CheckAndCorrectDepthStencilDesc(GraphicsPipeline); if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) { - DEV_CHECK_ERR(GraphicsPipeline.pVS, "Vertex shader must be defined"); - DEV_CHECK_ERR(!GraphicsPipeline.pAS && !GraphicsPipeline.pMS, "Mesh shaders are not supported in graphics pipeline"); + DEV_CHECK_ERR(CreateInfo.pVS, "Vertex shader must be defined"); + DEV_CHECK_ERR(!CreateInfo.pAS && !CreateInfo.pMS, "Mesh shaders are not supported in graphics pipeline"); } else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH) { - DEV_CHECK_ERR(GraphicsPipeline.pMS, "Mesh shader must be defined"); - DEV_CHECK_ERR(!GraphicsPipeline.pVS && !GraphicsPipeline.pGS && !GraphicsPipeline.pDS && !GraphicsPipeline.pHS, + DEV_CHECK_ERR(CreateInfo.pMS, "Mesh shader must be defined"); + DEV_CHECK_ERR(!CreateInfo.pVS && !CreateInfo.pGS && !CreateInfo.pDS && !CreateInfo.pHS, "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline"); DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout ignored in mesh shader"); DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || @@ -524,7 +533,7 @@ private: "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)"); } - m_pRenderPass = PSODesc.GraphicsPipeline.pRenderPass; + m_pRenderPass = GraphicsPipeline.pRenderPass; for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) { @@ -542,14 +551,14 @@ private: VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount); const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex]; - this->m_Desc.GraphicsPipeline.NumRenderTargets = static_cast(Subpass.RenderTargetAttachmentCount); + GraphicsPipeline.NumRenderTargets = static_cast(Subpass.RenderTargetAttachmentCount); for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt) { const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt]; if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) { VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); - this->m_Desc.GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format; + GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format; } } @@ -559,23 +568,19 @@ private: if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED) { VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount); - this->m_Desc.GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format; + GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format; } } } - const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout; - LayoutElement* pLayoutElements = nullptr; - if (InputLayout.NumElements > 0) - { - pLayoutElements = ALLOCATE(GetRawAllocator(), "Raw memory for input layout elements", LayoutElement, InputLayout.NumElements); - } + const auto& InputLayout = GraphicsPipeline.InputLayout; + LayoutElement* pLayoutElements = MemPool.Allocate(InputLayout.NumElements); for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem) { pLayoutElements[Elem] = InputLayout.LayoutElements[Elem]; - pLayoutElements[Elem].HLSLSemantic = m_StringPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic); + pLayoutElements[Elem].HLSLSemantic = MemPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic); } - this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements; + GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements; // Correct description and compute offsets and tight strides @@ -597,7 +602,7 @@ private: UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")"); continue; } - m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1); + m_BufferSlotsUsed = static_cast(std::max(m_BufferSlotsUsed, BuffSlot + 1)); auto& CurrAutoStride = TightStrides[BuffSlot]; // If offset is not explicitly specified, use current auto stride value @@ -647,28 +652,20 @@ private: LayoutElem.Stride = Strides[BuffSlot]; } - if (m_BufferSlotsUsed > 0) - { - m_pStrides = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", Uint32, m_BufferSlotsUsed); + m_pStrides = MemPool.Allocate(m_BufferSlotsUsed); - // Set strides for all unused slots to 0 - for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i) - { - auto Stride = Strides[i]; - m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0; - } + // Set strides for all unused slots to 0 + for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i) + { + auto Stride = Strides[i]; + m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0; } } - void InitComputePipeline() + void InitComputePipeline(const ComputePipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) { - const auto& ComputePipeline = this->m_Desc.ComputePipeline; - if (ComputePipeline.pCS == nullptr) - { - LOG_ERROR_AND_THROW("Compute shader is not provided"); - } - - VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute"); + InitResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); } #undef VALIDATE_SHADER_TYPE diff --git a/Graphics/GraphicsEngine/interface/InputLayout.h b/Graphics/GraphicsEngine/interface/InputLayout.h index 19904974..c7b18965 100644 --- a/Graphics/GraphicsEngine/interface/InputLayout.h +++ b/Graphics/GraphicsEngine/interface/InputLayout.h @@ -179,7 +179,7 @@ typedef struct LayoutElement LayoutElement; /// Layout description -/// This structure is used by IRenderDevice::CreatePipelineState(). +/// This structure is used by IRenderDevice::CreateGraphicsPipelineState(). struct InputLayoutDesc { /// Array of layout elements diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index 2d22c826..e5682e58 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -151,29 +151,6 @@ typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc; /// This structure describes the graphics pipeline state and is part of the PipelineStateDesc structure. struct GraphicsPipelineDesc { - /// Vertex shader to be used with the pipeline. - IShader* pVS DEFAULT_INITIALIZER(nullptr); - - /// Pixel shader to be used with the pipeline. - IShader* pPS DEFAULT_INITIALIZER(nullptr); - - /// Domain shader to be used with the pipeline. - IShader* pDS DEFAULT_INITIALIZER(nullptr); - - /// Hull shader to be used with the pipeline. - IShader* pHS DEFAULT_INITIALIZER(nullptr); - - /// Geometry shader to be used with the pipeline. - IShader* pGS DEFAULT_INITIALIZER(nullptr); - - /// Amplification shader to be used with the pipeline. - IShader* pAS DEFAULT_INITIALIZER(nullptr); - - /// Mesh shader to be used with the pipeline. - IShader* pMS DEFAULT_INITIALIZER(nullptr); - - //D3D12_STREAM_OUTPUT_DESC StreamOutput; - /// Blend state description. BlendStateDesc BlendDesc; @@ -234,17 +211,6 @@ struct GraphicsPipelineDesc typedef struct GraphicsPipelineDesc GraphicsPipelineDesc; -/// Compute pipeline state description - -/// This structure describes the compute pipeline state and is part of the PipelineStateDesc structure. -struct ComputePipelineDesc -{ - /// Compute shader to be used with the pipeline - IShader* pCS DEFAULT_INITIALIZER(nullptr); -}; -typedef struct ComputePipelineDesc ComputePipelineDesc; - - /// Pipeline type DILIGENT_TYPED_ENUM(PIPELINE_TYPE, Uint8) { @@ -278,12 +244,6 @@ struct PipelineStateDesc DILIGENT_DERIVE(DeviceObjectAttribs) /// Pipeline layout description PipelineResourceLayoutDesc ResourceLayout; - /// Graphics pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_GRAPHICS or PIPELINE_TYPE_MESH - GraphicsPipelineDesc GraphicsPipeline; - - /// Compute pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_COMPUTE - ComputePipelineDesc ComputePipeline; - #if DILIGENT_CPP_INTERFACE bool IsAnyGraphicsPipeline() const { return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH; } bool IsComputePipeline() const { return PipelineType == PIPELINE_TYPE_COMPUTE; } @@ -324,10 +284,50 @@ struct PipelineStateCreateInfo PipelineStateDesc PSODesc; /// Pipeline state creation flags, see Diligent::PSO_CREATE_FLAGS. - PSO_CREATE_FLAGS Flags DEFAULT_INITIALIZER(PSO_CREATE_FLAG_NONE); + PSO_CREATE_FLAGS Flags DEFAULT_INITIALIZER(PSO_CREATE_FLAG_NONE); }; typedef struct PipelineStateCreateInfo PipelineStateCreateInfo; + +/// Graphics pipeline state creation attributes +struct GraphicsPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) + + /// Graphics pipeline state description. + GraphicsPipelineDesc GraphicsPipeline; + + /// Vertex shader to be used with the pipeline. + IShader* pVS DEFAULT_INITIALIZER(nullptr); + + /// Pixel shader to be used with the pipeline. + IShader* pPS DEFAULT_INITIALIZER(nullptr); + + /// Domain shader to be used with the pipeline. + IShader* pDS DEFAULT_INITIALIZER(nullptr); + + /// Hull shader to be used with the pipeline. + IShader* pHS DEFAULT_INITIALIZER(nullptr); + + /// Geometry shader to be used with the pipeline. + IShader* pGS DEFAULT_INITIALIZER(nullptr); + + /// Amplification shader to be used with the pipeline. + IShader* pAS DEFAULT_INITIALIZER(nullptr); + + /// Mesh shader to be used with the pipeline. + IShader* pMS DEFAULT_INITIALIZER(nullptr); +}; +typedef struct GraphicsPipelineStateCreateInfo GraphicsPipelineStateCreateInfo; + + +/// Compute pipeline state description. +struct ComputePipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) + + /// Compute shader to be used with the pipeline + IShader* pCS DEFAULT_INITIALIZER(nullptr); +}; +typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo; + + // {06084AE5-6A71-4FE8-84B9-395DD489A28C} static const struct INTERFACE_ID IID_PipelineState = {0x6084ae5, 0x6a71, 0x4fe8, {0x84, 0xb9, 0x39, 0x5d, 0xd4, 0x89, 0xa2, 0x8c}}; @@ -345,10 +345,12 @@ static const struct INTERFACE_ID IID_PipelineState = DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) { #if DILIGENT_CPP_INTERFACE - /// Returns the blend state description used to create the object - virtual const PipelineStateDesc& METHOD(GetDesc)()const override = 0; + /// Returns the pipeline description used to create the object + virtual const PipelineStateDesc& METHOD(GetDesc)() const override = 0; #endif + /// Returns the graphics pipeline description used to create the object + VIRTUAL const GraphicsPipelineDesc REF METHOD(GetGraphicsPipelineDesc)(THIS) CONST PURE; /// Binds resources for all shaders in the pipeline state @@ -438,6 +440,7 @@ DILIGENT_END_INTERFACE # define IPipelineState_GetDesc(This) (const struct PipelineStateDesc*)IDeviceObject_GetDesc(This) +# define IPipelineState_GetGraphicsPipelineDesc(This) CALL_IFACE_METHOD(PipelineState, GetGraphicsPipelineDesc, This) # define IPipelineState_BindStaticResources(This, ...) CALL_IFACE_METHOD(PipelineState, BindStaticResources, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableCount(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableCount, This, __VA_ARGS__) # define IPipelineState_GetStaticVariableByName(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByName, This, __VA_ARGS__) diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index 0cea79eb..ea4e05af 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -153,17 +153,27 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) const ResourceMappingDesc REF MappingDesc, IResourceMapping** ppMapping) PURE; - /// Creates a new pipeline state object + /// Creates a new graphics pipeline state object - /// \param [in] PSOCreateInfo - Pipeline state create info, see Diligent::PipelineStateCreateInfo for details. + /// \param [in] PSOCreateInfo - Pipeline state create info, see Diligent::GraphicsPipelineStateCreateInfo for details. /// \param [out] ppPipelineState - Address of the memory location where the pointer to the /// pipeline state interface will be stored. /// The function calls AddRef(), so that the new object will contain /// one reference. - VIRTUAL void METHOD(CreatePipelineState)(THIS_ - const PipelineStateCreateInfo REF PSOCreateInfo, - IPipelineState** ppPipelineState) PURE; + VIRTUAL void METHOD(CreateGraphicsPipelineState)(THIS_ + const GraphicsPipelineStateCreateInfo REF PSOCreateInfo, + IPipelineState** ppPipelineState) PURE; + + /// Creates a new compute pipeline state object + /// \param [in] PSOCreateInfo - Pipeline state create info, see Diligent::ComputePipelineStateCreateInfo for details. + /// \param [out] ppPipelineState - Address of the memory location where the pointer to the + /// pipeline state interface will be stored. + /// The function calls AddRef(), so that the new object will contain + /// one reference. + VIRTUAL void METHOD(CreateComputePipelineState)(THIS_ + const ComputePipelineStateCreateInfo REF PSOCreateInfo, + IPipelineState** ppPipelineState) PURE; /// Creates a new fence object @@ -273,20 +283,21 @@ DILIGENT_END_INTERFACE // clang-format off -# define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__) -# define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__) -# define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__) -# define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__) -# define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__) -# define IRenderDevice_CreatePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreatePipelineState, This, __VA_ARGS__) -# define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__) -# define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__) -# define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This) -# define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__) -# define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt,This, __VA_ARGS__) -# define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__) -# define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This) -# define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This) +# define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__) +# define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__) +# define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__) +# define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__) +# define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__) +# define IRenderDevice_CreateGraphicsPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateGraphicsPipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateComputePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateComputePipelineState, This, __VA_ARGS__) +# define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__) +# define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__) +# define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This) +# define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__) +# define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt, This, __VA_ARGS__) +# define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__) +# define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This) +# define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This) // clang-format on diff --git a/Graphics/GraphicsEngine/src/APIInfo.cpp b/Graphics/GraphicsEngine/src/APIInfo.cpp index f71b943e..05aef568 100644 --- a/Graphics/GraphicsEngine/src/APIInfo.cpp +++ b/Graphics/GraphicsEngine/src/APIInfo.cpp @@ -90,7 +90,6 @@ static APIInfo InitAPIInfo() INIT_STRUCTURE_SIZE(StaticSamplerDesc); INIT_STRUCTURE_SIZE(PipelineResourceLayoutDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineDesc); - INIT_STRUCTURE_SIZE(ComputePipelineDesc); INIT_STRUCTURE_SIZE(PipelineStateDesc); INIT_STRUCTURE_SIZE(RasterizerStateDesc); INIT_STRUCTURE_SIZE(ResourceMappingEntry); diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 1d836ab3..99062706 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -49,9 +49,12 @@ class PipelineStateD3D11Impl final : public PipelineStateBase; - PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, - class RenderDeviceD3D11Impl* pDeviceD3D11, - const PipelineStateCreateInfo& CreateInfo); + PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const GraphicsPipelineStateCreateInfo& CreateInfo); + PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, + class RenderDeviceD3D11Impl* pDeviceD3D11, + const ComputePipelineStateCreateInfo& CreateInfo); ~PipelineStateD3D11Impl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; @@ -134,6 +137,10 @@ public: void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; private: + void InitResourceLayouts(RenderDeviceD3D11Impl* pRenderDeviceD3D11, + const PipelineStateCreateInfo& CreateInfo, + const std::vector>& ShaderStages); + CComPtr m_pd3d11BlendState; CComPtr m_pd3d11RasterizerState; CComPtr m_pd3d11DepthStencilState; @@ -147,8 +154,8 @@ private: RefCntAutoPtr m_pCS; // The caches are indexed by the shader order in the PSO, not shader index - ShaderResourceCacheD3D11* m_pStaticResourceCaches = nullptr; - ShaderResourceLayoutD3D11* m_pStaticResourceLayouts = nullptr; + 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; diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp index 8003615e..1a1e01af 100644 --- a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp @@ -69,9 +69,13 @@ public: virtual void DILIGENT_CALL_TYPE CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler) override final; - /// Implementation of IRenderDevice::CreatePipelineState() in Direct3D11 backend. - virtual void DILIGENT_CALL_TYPE CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, - IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateGraphicsPipelineState() in Direct3D11 backend. + virtual void DILIGENT_CALL_TYPE CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; + + /// Implementation of IRenderDevice::CreateComputePipelineState() in Direct3D11 backend. + virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; /// Implementation of IRenderDevice::CreateFence() in Direct3D11 backend. virtual void DILIGENT_CALL_TYPE CreateFence(const FenceDesc& Desc, diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index 75ce9094..39560453 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -75,7 +75,7 @@ void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState) TDeviceContextBase::SetPipelineState(pPipelineStateD3D11, 0 /*Dummy*/); auto& Desc = pPipelineStateD3D11->GetDesc(); - if (Desc.IsComputePipeline()) + if (Desc.PipelineType == PIPELINE_TYPE_COMPUTE) { auto* pd3d11CS = pPipelineStateD3D11->GetD3D11ComputeShader(); if (pd3d11CS == nullptr) @@ -106,7 +106,9 @@ void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState) COMMIT_SHADER(DS, DomainShader); #undef COMMIT_SHADER - m_pd3d11DeviceContext->OMSetBlendState(pPipelineStateD3D11->GetD3D11BlendState(), m_BlendFactors, Desc.GraphicsPipeline.SampleMask); + auto& GraphicsPipeline = pPipelineStateD3D11->GetGraphicsPipelineDesc(); + + m_pd3d11DeviceContext->OMSetBlendState(pPipelineStateD3D11->GetD3D11BlendState(), m_BlendFactors, GraphicsPipeline.SampleMask); m_pd3d11DeviceContext->RSSetState(pPipelineStateD3D11->GetD3D11RasterizerState()); m_pd3d11DeviceContext->OMSetDepthStencilState(pPipelineStateD3D11->GetD3D11DepthStencilState(), m_StencilRef); @@ -119,7 +121,7 @@ void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState) m_CommittedD3D11InputLayout = pd3d11InputLayout; } - auto PrimTopology = Desc.GraphicsPipeline.PrimitiveTopology; + auto PrimTopology = GraphicsPipeline.PrimitiveTopology; if (m_CommittedPrimitiveTopology != PrimTopology) { m_CommittedPrimitiveTopology = PrimTopology; @@ -673,7 +675,7 @@ void DeviceContextD3D11Impl::SetBlendFactors(const float* pBlendFactors) ID3D11BlendState* pd3d11BS = nullptr; if (m_pPipelineState) { - SampleMask = m_pPipelineState->GetDesc().GraphicsPipeline.SampleMask; + SampleMask = m_pPipelineState->GetGraphicsPipelineDesc().SampleMask; pd3d11BS = m_pPipelineState->GetD3D11BlendState(); } m_pd3d11DeviceContext->OMSetBlendState(pd3d11BS, m_BlendFactors, SampleMask); diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 4893f97e..d20e0c32 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -35,9 +35,9 @@ namespace Diligent { -PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D11Impl* pRenderDeviceD3D11, - const PipelineStateCreateInfo& CreateInfo) : +PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pRenderDeviceD3D11, + const GraphicsPipelineStateCreateInfo& CreateInfo) : // clang-format off TPipelineStateBase { @@ -51,28 +51,33 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR { m_ResourceLayoutIndex.fill(-1); - if (m_Desc.IsComputePipeline()) - { - auto* pCS = ValidatedCast(m_Desc.ComputePipeline.pCS); - m_pCS = pCS; - if (m_pCS == nullptr) - { - LOG_ERROR_AND_THROW("Compute shader is null"); - } + // We do not really need ShaderStages, but ExtractShaders() also initializes + // shader stage types and shader stage counter. + std::vector> ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); - if (m_pCS && 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 = pCS->GetD3D11Resources()->GetHash(); - } - else if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) - { + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); + + m_pStaticResourceLayouts = MemPool.Allocate(GetNumShaderStages()); + m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); + + InitGraphicsPipeline(CreateInfo, MemPool); + InitResourceLayouts(pRenderDeviceD3D11, CreateInfo, ShaderStages); + + auto& GraphicsPipeline = GetGraphicsPipelineDesc(); #define INIT_SHADER(ShortName, ExpectedType) \ do \ { \ - auto* pShader = ValidatedCast(m_Desc.GraphicsPipeline.p##ShortName); \ + auto* pShader = ValidatedCast(CreateInfo.p##ShortName); \ m_p##ShortName = pShader; \ if (m_p##ShortName && m_p##ShortName->GetDesc().ShaderType != ExpectedType) \ { \ @@ -82,81 +87,140 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR 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); + 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 - if (m_pVS == nullptr) - { - LOG_ERROR_AND_THROW("Vertex shader is null"); - } + if (m_pVS == nullptr) + { + LOG_ERROR_AND_THROW("Vertex shader is null"); + } - auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); + auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); - D3D11_BLEND_DESC D3D11BSDesc = {}; - BlendStateDesc_To_D3D11_BLEND_DESC(m_Desc.GraphicsPipeline.BlendDesc, D3D11BSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateBlendState(&D3D11BSDesc, &m_pd3d11BlendState), - "Failed to create D3D11 blend state object"); + D3D11_BLEND_DESC D3D11BSDesc = {}; + BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateBlendState(&D3D11BSDesc, &m_pd3d11BlendState), + "Failed to create D3D11 blend state object"); - D3D11_RASTERIZER_DESC D3D11RSDesc = {}; - RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(m_Desc.GraphicsPipeline.RasterizerDesc, D3D11RSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateRasterizerState(&D3D11RSDesc, &m_pd3d11RasterizerState), - "Failed to create D3D11 rasterizer state"); + D3D11_RASTERIZER_DESC D3D11RSDesc = {}; + RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, D3D11RSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateRasterizerState(&D3D11RSDesc, &m_pd3d11RasterizerState), + "Failed to create D3D11 rasterizer state"); - D3D11_DEPTH_STENCIL_DESC D3D11DSSDesc = {}; - DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(m_Desc.GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateDepthStencilState(&D3D11DSSDesc, &m_pd3d11DepthStencilState), - "Failed to create D3D11 depth stencil state"); + D3D11_DEPTH_STENCIL_DESC D3D11DSSDesc = {}; + DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateDepthStencilState(&D3D11DSSDesc, &m_pd3d11DepthStencilState), + "Failed to create D3D11 depth stencil state"); - // Create input layout - const auto& InputLayout = m_Desc.GraphicsPipeline.InputLayout; - if (InputLayout.NumElements > 0) - { - std::vector> d311InputElements(STD_ALLOCATOR_RAW_MEM(D3D11_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); - LayoutElements_To_D3D11_INPUT_ELEMENT_DESCs(InputLayout, d311InputElements); + // Create input layout + const auto& InputLayout = GraphicsPipeline.InputLayout; + if (InputLayout.NumElements > 0) + { + 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 = m_pVS.RawPtr()->GetBytecode(); + if (!pVSByteCode) + LOG_ERROR_AND_THROW("Vertex Shader byte code does not exist"); - 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"); - } + 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"); } - else + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); +} + +PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pRenderDeviceD3D11, + const ComputePipelineStateCreateInfo& CreateInfo) : + // clang-format off + TPipelineStateBase { - UNEXPECTED(GetPipelineTypeString(m_Desc.PipelineType), " pipelines are not supported by Direct3D11 backend"); - } + pRefCounters, + pRenderDeviceD3D11, + CreateInfo.PSODesc + }, + m_SRBMemAllocator{GetRawAllocator()}, + m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")) +// clang-format on +{ + m_ResourceLayoutIndex.fill(-1); // We do not really need ShaderStages, but ExtractShaders() also initializes // shader stage types and shader stage counter. std::vector> ShaderStages; - ExtractShaders(ShaderStages); - VERIFY_EXPR(GetNumShaderStages() == ShaderStages.size()); + ExtractShaders(CreateInfo, ShaderStages); - // clang-format off - static_assert((sizeof(ShaderResourceLayoutD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutD3D11) is expected to be a multiple of sizeof(void*)"); - static_assert((sizeof(ShaderResourceCacheD3D11) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D11) is expected to be a multiple of sizeof(void*)"); - // clang-format on + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); - const auto MemSize = (sizeof(ShaderResourceLayoutD3D11) + sizeof(ShaderResourceCacheD3D11)) * GetNumShaderStages(); - auto* const pRawMem = - ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11 and ShaderResourceCacheD3D11 arrays", MemSize); + m_pStaticResourceLayouts = MemPool.Allocate(GetNumShaderStages()); + m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); - m_pStaticResourceLayouts = reinterpret_cast(pRawMem); - m_pStaticResourceCaches = reinterpret_cast(m_pStaticResourceLayouts + GetNumShaderStages()); + InitComputePipeline(CreateInfo, MemPool); + InitResourceLayouts(pRenderDeviceD3D11, CreateInfo, ShaderStages); + auto* pCS = ValidatedCast(CreateInfo.pCS); + m_pCS = pCS; + if (m_pCS == nullptr) + { + LOG_ERROR_AND_THROW("Compute shader is null"); + } + + if (m_pCS && 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 = pCS->GetD3D11Resources()->GetHash(); + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); +} + +PipelineStateD3D11Impl::~PipelineStateD3D11Impl() +{ + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + { + m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); + m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); + } + + for (Uint32 l = 0; l < GetNumShaderStages(); ++l) + { + m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); + } + // m_pStaticResourceLayouts and m_pStaticResourceCaches are allocated in contiguous chunks of memory. + if (auto* pRawMem = m_pStaticResourceLayouts) + GetRawAllocator().Free(pRawMem); +} + +IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase) + + +void PipelineStateD3D11Impl::InitResourceLayouts(RenderDeviceD3D11Impl* pRenderDeviceD3D11, + const PipelineStateCreateInfo& CreateInfo, + const std::vector>& ShaderStages) +{ const auto& ResourceLayout = m_Desc.ResourceLayout; #ifdef DILIGENT_DEVELOPMENT { const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {}; - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + for (Uint32 s = 0; s < ShaderStages.size(); ++s) { - auto* pShader = GetShader(s); + auto* pShader = ShaderStages[s].second; pResources[s] = &(*pShader->GetD3D11Resources()); } ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(), @@ -168,9 +232,9 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR decltype(m_StaticSamplers) StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")); std::array ShaderResLayoutDataSizes = {}; std::array ShaderResCacheDataSizes = {}; - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + for (Uint32 s = 0; s < ShaderStages.size(); ++s) { - const auto* pShader = GetShader(s); + const auto* pShader = ShaderStages[s].second; const auto& ShaderDesc = pShader->GetDesc(); const auto& ShaderResources = *pShader->GetD3D11Resources(); VERIFY_EXPR(ShaderDesc.ShaderType == ShaderResources.GetShaderType()); @@ -242,27 +306,6 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR } } - -PipelineStateD3D11Impl::~PipelineStateD3D11Impl() -{ - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) - { - m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); - m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); - } - - for (Uint32 l = 0; l < GetNumShaderStages(); ++l) - { - m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); - } - // m_pStaticResourceLayouts and m_pStaticResourceCaches are allocated in contiguous chunks of memory. - if (auto* pRawMem = m_pStaticResourceLayouts) - GetRawAllocator().Free(pRawMem); -} - -IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase) - - ID3D11BlendState* PipelineStateD3D11Impl::GetD3D11BlendState() { return m_pd3d11BlendState; diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index 76020ed8..537d9db2 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -385,7 +385,18 @@ void RenderDeviceD3D11Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampl }); } -void RenderDeviceD3D11Impl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +void RenderDeviceD3D11Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& 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); + }); +} + +void RenderDeviceD3D11Impl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) { CreateDeviceObject("Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState, [&]() // diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index 00b2affd..821ff951 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -38,6 +38,7 @@ #include "SRBMemoryAllocator.hpp" #include "RenderDeviceD3D12Impl.hpp" #include "ShaderVariableD3D12.hpp" +#include "ShaderD3D12Impl.hpp" namespace Diligent { @@ -50,7 +51,8 @@ class PipelineStateD3D12Impl final : public PipelineStateBase; - PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const PipelineStateCreateInfo& CreateInfo); + PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const GraphicsPipelineStateCreateInfo& CreateInfo); + PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, RenderDeviceD3D12Impl* pDeviceD3D12, const ComputePipelineStateCreateInfo& CreateInfo); ~PipelineStateD3D12Impl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; @@ -119,15 +121,29 @@ public: } private: + struct D3D12PipelineShaderStageInfo + { + const SHADER_TYPE Type; + ShaderD3D12Impl* const pShader; + D3D12PipelineShaderStageInfo(SHADER_TYPE _Type, + ShaderD3D12Impl* _pShader) : + Type{_Type}, + pShader{_pShader} + {} + }; + void InitResourceLayouts(RenderDeviceD3D12Impl* pDeviceD3D12, + const PipelineStateCreateInfo& CreateInfo, + std::vector& ShaderStages); + CComPtr m_pd3d12PSO; RootSignature m_RootSig; // Must be defined before default SRB SRBMemoryAllocator m_SRBMemAllocator; - ShaderResourceLayoutD3D12* m_pShaderResourceLayouts = nullptr; - ShaderResourceCacheD3D12* m_pStaticResourceCaches = nullptr; - ShaderVariableManagerD3D12* m_pStaticVarManagers = nullptr; + ShaderResourceLayoutD3D12* m_pShaderResourceLayouts = nullptr; // [m_NumShaderStages * 2] + ShaderResourceCacheD3D12* m_pStaticResourceCaches = nullptr; // [m_NumShaderStages] + ShaderVariableManagerD3D12* m_pStaticVarManagers = nullptr; // [m_NumShaderStages] // Resource layout index in m_pShaderResourceLayouts array for every shader stage, // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp index 0dc4201e..7083e30d 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp @@ -62,8 +62,11 @@ public: virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - /// Implementation of IRenderDevice::CreatePipelineState() in Direct3D12 backend. - virtual void DILIGENT_CALL_TYPE CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateGraphicsPipelineState() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + + /// Implementation of IRenderDevice::CreateComputePipelineState() in Direct3D12 backend. + virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; /// Implementation of IRenderDevice::CreateBuffer() in Direct3D12 backend. virtual void DILIGENT_CALL_TYPE CreateBuffer(const BufferDesc& BuffDesc, diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index 546c9de8..f1bc35eb 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -211,49 +211,58 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) // This is necessary because if the command list had been flushed // and the first PSO set on the command list was a compute pipeline, // the states would otherwise never be committed (since m_pPipelineState != nullptr) - CommitStates = OldPSODesc.IsComputePipeline(); + CommitStates = !OldPSODesc.IsAnyGraphicsPipeline(); // We also need to update scissor rect if ScissorEnable state has changed - CommitScissor = OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable != PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable; + if (OldPSODesc.IsAnyGraphicsPipeline() && PSODesc.IsAnyGraphicsPipeline()) + CommitScissor = m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable != pPipelineStateD3D12->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable; } TDeviceContextBase::SetPipelineState(pPipelineStateD3D12, 0 /*Dummy*/); - auto& CmdCtx = GetCmdContext(); - + auto& CmdCtx = GetCmdContext(); auto* pd3d12PSO = pPipelineStateD3D12->GetD3D12PipelineState(); - if (PSODesc.IsComputePipeline()) - { - CmdCtx.AsComputeContext().SetPipelineState(pd3d12PSO); - } - else + + switch (PSODesc.PipelineType) { - VERIFY_EXPR(PSODesc.IsAnyGraphicsPipeline()); + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: + { + auto& GraphicsPipeline = pPipelineStateD3D12->GetGraphicsPipelineDesc(); + auto& GraphicsCtx = CmdCtx.AsGraphicsContext(); + GraphicsCtx.SetPipelineState(pd3d12PSO); - auto& GraphicsCtx = CmdCtx.AsGraphicsContext(); - GraphicsCtx.SetPipelineState(pd3d12PSO); + if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) + { + auto D3D12Topology = TopologyToD3D12Topology(GraphicsPipeline.PrimitiveTopology); + GraphicsCtx.SetPrimitiveTopology(D3D12Topology); + } - if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) - { - auto D3D12Topology = TopologyToD3D12Topology(PSODesc.GraphicsPipeline.PrimitiveTopology); - GraphicsCtx.SetPrimitiveTopology(D3D12Topology); - } + if (CommitStates) + { + GraphicsCtx.SetStencilRef(m_StencilRef); + GraphicsCtx.SetBlendFactor(m_BlendFactors); + if (GraphicsPipeline.pRenderPass == nullptr) + { + CommitRenderTargets(RESOURCE_STATE_TRANSITION_MODE_VERIFY); + } + CommitViewports(); + } - if (CommitStates) - { - GraphicsCtx.SetStencilRef(m_StencilRef); - GraphicsCtx.SetBlendFactor(m_BlendFactors); - if (PSODesc.GraphicsPipeline.pRenderPass == nullptr) + if (CommitStates || CommitScissor) { - CommitRenderTargets(RESOURCE_STATE_TRANSITION_MODE_VERIFY); + CommitScissorRects(GraphicsCtx, GraphicsPipeline.RasterizerDesc.ScissorEnable); } - CommitViewports(); + break; } - - if (CommitStates || CommitScissor) + case PIPELINE_TYPE_COMPUTE: { - CommitScissorRects(GraphicsCtx, PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable); + CmdCtx.AsComputeContext().SetPipelineState(pd3d12PSO); + break; } + default: + UNEXPECTED("unknown pipeline type"); } + m_State.pCommittedResourceCache = nullptr; m_State.bRootViewsCommitted = false; } @@ -964,7 +973,7 @@ void DeviceContextD3D12Impl::SetScissorRects(Uint32 NumRects, const Rect* pRects if (m_pPipelineState) { const auto& PSODesc = m_pPipelineState->GetDesc(); - if (PSODesc.IsAnyGraphicsPipeline() && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable) + if (PSODesc.IsAnyGraphicsPipeline() && m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable) { VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects"); auto& Ctx = GetCmdContext().AsGraphicsContext(); diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index f5d60b60..0d26db2a 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -98,44 +98,324 @@ private: std::array m_Map; }; -PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDeviceD3D12, - const PipelineStateCreateInfo& CreateInfo) : +PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDeviceD3D12, + const GraphicsPipelineStateCreateInfo& CreateInfo) : TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { m_ResourceLayoutIndex.fill(-1); - struct D3D12PipelineShaderStageInfo + std::vector ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages() * 2); + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); + + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + m_RootSig.AllocateStaticSamplers(m_Desc.ResourceLayout); + + m_pShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); + m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); + m_pStaticVarManagers = MemPool.Allocate(GetNumShaderStages()); + + InitGraphicsPipeline(CreateInfo, MemPool); + InitResourceLayouts(pDeviceD3D12, CreateInfo, ShaderStages); + + if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) + { + const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; + + for (const auto& Stage : ShaderStages) + { + auto* pShaderD3D12 = Stage.pShader; + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off + case SHADER_TYPE_VERTEX: pd3d12ShaderBytecode = &d3d12PSODesc.VS; break; + case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; + case SHADER_TYPE_GEOMETRY: pd3d12ShaderBytecode = &d3d12PSODesc.GS; break; + case SHADER_TYPE_HULL: pd3d12ShaderBytecode = &d3d12PSODesc.HS; break; + case SHADER_TYPE_DOMAIN: pd3d12ShaderBytecode = &d3d12PSODesc.DS; break; + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); + } + + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + + memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); + + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); + // The sample mask for the blend state. + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); + + std::vector> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); + + const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout; + if (InputLayout.NumElements > 0) + { + LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); + d3d12PSODesc.InputLayout.NumElements = static_cast(d312InputElements.size()); + d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); + } + else + { + d3d12PSODesc.InputLayout.NumElements = 0; + d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; + } + + d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; + static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; + d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; + + d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormats); ++rt) + d3d12PSODesc.RTVFormats[rt] = DXGI_FORMAT_UNKNOWN; + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + + d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; + + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; + + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); + } + +#ifdef D3D12_H_HAS_MESH_SHADER + else if (m_Desc.PipelineType == PIPELINE_TYPE_MESH) { - const SHADER_TYPE Type; - ShaderD3D12Impl* const pShader; - D3D12PipelineShaderStageInfo(SHADER_TYPE _Type, - ShaderD3D12Impl* _pShader) : - Type{_Type}, - pShader{_pShader} - {} - }; + const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + + struct MESH_SHADER_PIPELINE_STATE_DESC + { + PSS_SubObject Flags; + PSS_SubObject NodeMask; + PSS_SubObject pRootSignature; + PSS_SubObject PS; + PSS_SubObject AS; + PSS_SubObject MS; + PSS_SubObject BlendState; + PSS_SubObject DepthStencilState; + PSS_SubObject RasterizerState; + PSS_SubObject SampleDesc; + PSS_SubObject SampleMask; + PSS_SubObject DSVFormat; + PSS_SubObject RTVFormatArray; + PSS_SubObject CachedPSO; + }; + MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; + + for (const auto& Stage : ShaderStages) + { + auto* pShaderD3D12 = Stage.pShader; + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off + case SHADER_TYPE_AMPLIFICATION: pd3d12ShaderBytecode = &d3d12PSODesc.AS; break; + case SHADER_TYPE_MESH: pd3d12ShaderBytecode = &d3d12PSODesc.MS; break; + case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); + } + + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, *d3d12PSODesc.BlendState); + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, *d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, *d3d12PSODesc.DepthStencilState); + + d3d12PSODesc.RTVFormatArray->NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormatArray->RTFormats); ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = DXGI_FORMAT_UNKNOWN; + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + + d3d12PSODesc.SampleDesc->Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc->Quality = GraphicsPipeline.SmplDesc.Quality; + + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; + + d3d12PSODesc.CachedPSO->pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO->CachedBlobSizeInBytes = 0; + + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + D3D12_PIPELINE_STATE_STREAM_DESC streamDesc; + streamDesc.SizeInBytes = sizeof(d3d12PSODesc); + streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; + + auto* device2 = pDeviceD3D12->GetD3D12Device2(); + + CHECK_D3D_RESULT_THROW(device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)), "Failed to create pipeline state"); + } +#endif // D3D12_H_HAS_MESH_SHADER + else + { + LOG_ERROR_AND_THROW("Unsupported pipeline type"); + } + + if (*m_Desc.Name != 0) + { + m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); + String RootSignatureDesc("Root signature for PSO '"); + RootSignatureDesc.append(m_Desc.Name); + RootSignatureDesc.push_back('\''); + m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + } + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_pShaderResourceLayouts); +} + +PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDeviceD3D12, + const ComputePipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + m_ResourceLayoutIndex.fill(-1); + std::vector ShaderStages; - ExtractShaders(ShaderStages); - VERIFY_EXPR(GetNumShaderStages() == ShaderStages.size()); + ExtractShaders(CreateInfo, ShaderStages); - auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); - const auto& ResourceLayout = m_Desc.ResourceLayout; - m_RootSig.AllocateStaticSamplers(ResourceLayout); + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages() * 2); + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); + + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + m_RootSig.AllocateStaticSamplers(m_Desc.ResourceLayout); + + m_pShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); + m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); + m_pStaticVarManagers = MemPool.Allocate(GetNumShaderStages()); + + InitComputePipeline(CreateInfo, MemPool); + InitResourceLayouts(pDeviceD3D12, CreateInfo, ShaderStages); + + D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; + + VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); + auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); + d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); + d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); + + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; + + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + + HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); + + if (*m_Desc.Name != 0) + { + m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); + String RootSignatureDesc("Root signature for PSO '"); + RootSignatureDesc.append(m_Desc.Name); + RootSignatureDesc.push_back('\''); + m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + } + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_pShaderResourceLayouts); +} + +PipelineStateD3D12Impl::~PipelineStateD3D12Impl() +{ + auto& ShaderResLayoutAllocator = GetRawAllocator(); + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + { + m_pStaticVarManagers[s].Destroy(GetRawAllocator()); + m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); + m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); + m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); + m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12(); + } + // m_pShaderResourceLayouts, m_pStaticResourceCaches, and m_pShaderResourceLayouts are allocated in + // contiguous chunks of memory. + auto* pRawMem = m_pShaderResourceLayouts; + ShaderResLayoutAllocator.Free(pRawMem); - // clang-format off - static_assert((sizeof(ShaderResourceLayoutD3D12) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutD3D12) is expected to be a multiple of sizeof(void*)"); - static_assert((sizeof(ShaderResourceCacheD3D12) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheD3D12) is expected to be a multiple of sizeof(void*)"); - static_assert((sizeof(ShaderVariableManagerD3D12) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerD3D12) is expected to be a multiple of sizeof(void*)"); - // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutD3D12) * 2 + sizeof(ShaderResourceCacheD3D12) + sizeof(ShaderVariableManagerD3D12)) * GetNumShaderStages(); - auto* const pRawMem = - ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D12, ShaderResourceCacheD3D12, and ShaderVariableManagerD3D12 arrays", MemSize); + // D3D12 object can only be destroyed when it is no longer used by the GPU + m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask); +} + +IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase) - m_pShaderResourceLayouts = reinterpret_cast(pRawMem); - m_pStaticResourceCaches = reinterpret_cast(m_pShaderResourceLayouts + GetNumShaderStages() * 2); - m_pStaticVarManagers = reinterpret_cast(m_pStaticResourceCaches + GetNumShaderStages()); + +void PipelineStateD3D12Impl::InitResourceLayouts(RenderDeviceD3D12Impl* pDeviceD3D12, + const PipelineStateCreateInfo& CreateInfo, + std::vector& ShaderStages) +{ + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + const auto& ResourceLayout = m_Desc.ResourceLayout; #ifdef DILIGENT_DEVELOPMENT { @@ -205,222 +485,6 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR } m_RootSig.Finalize(pd3d12Device); - switch (m_Desc.PipelineType) - { - case PIPELINE_TYPE_COMPUTE: - { - D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; - - VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); - auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); - d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); - d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); - - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; - - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - - HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); - break; - } - - case PIPELINE_TYPE_GRAPHICS: - { - const auto& GraphicsPipeline = m_Desc.GraphicsPipeline; - - D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; - - for (const auto& Stage : ShaderStages) - { - auto* pShaderD3D12 = Stage.pShader; - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; - VERIFY_EXPR(ShaderType == Stage.Type); - - D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; - switch (ShaderType) - { - // clang-format off - case SHADER_TYPE_VERTEX: pd3d12ShaderBytecode = &d3d12PSODesc.VS; break; - case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; - case SHADER_TYPE_GEOMETRY: pd3d12ShaderBytecode = &d3d12PSODesc.GS; break; - case SHADER_TYPE_HULL: pd3d12ShaderBytecode = &d3d12PSODesc.HS; break; - case SHADER_TYPE_DOMAIN: pd3d12ShaderBytecode = &d3d12PSODesc.DS; break; - // clang-format on - default: UNEXPECTED("Unexpected shader type"); - } - auto* pByteCode = pShaderD3D12->GetShaderByteCode(); - - pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); - pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); - } - - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - - memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); - - BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); - // The sample mask for the blend state. - d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; - - RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); - DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); - - std::vector> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); - - const auto& InputLayout = m_Desc.GraphicsPipeline.InputLayout; - if (InputLayout.NumElements > 0) - { - LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); - d3d12PSODesc.InputLayout.NumElements = static_cast(d312InputElements.size()); - d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); - } - else - { - d3d12PSODesc.InputLayout.NumElements = 0; - d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; - } - - d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; - static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; - d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; - - d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; - for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) - d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormats); ++rt) - d3d12PSODesc.RTVFormats[rt] = DXGI_FORMAT_UNKNOWN; - d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); - - d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; - d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; - - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; - - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - - HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); - break; - } - -#ifdef D3D12_H_HAS_MESH_SHADER - case PIPELINE_TYPE_MESH: - { - const auto& GraphicsPipeline = m_Desc.GraphicsPipeline; - - struct MESH_SHADER_PIPELINE_STATE_DESC - { - PSS_SubObject Flags; - PSS_SubObject NodeMask; - PSS_SubObject pRootSignature; - PSS_SubObject PS; - PSS_SubObject AS; - PSS_SubObject MS; - PSS_SubObject BlendState; - PSS_SubObject DepthStencilState; - PSS_SubObject RasterizerState; - PSS_SubObject SampleDesc; - PSS_SubObject SampleMask; - PSS_SubObject DSVFormat; - PSS_SubObject RTVFormatArray; - PSS_SubObject CachedPSO; - }; - MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; - - for (const auto& Stage : ShaderStages) - { - auto* pShaderD3D12 = Stage.pShader; - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; - VERIFY_EXPR(ShaderType == Stage.Type); - - D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; - switch (ShaderType) - { - // clang-format off - case SHADER_TYPE_AMPLIFICATION: pd3d12ShaderBytecode = &d3d12PSODesc.AS; break; - case SHADER_TYPE_MESH: pd3d12ShaderBytecode = &d3d12PSODesc.MS; break; - case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; - // clang-format on - default: UNEXPECTED("Unexpected shader type"); - } - auto* pByteCode = pShaderD3D12->GetShaderByteCode(); - - pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); - pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); - } - - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - - BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, *d3d12PSODesc.BlendState); - d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; - - RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, *d3d12PSODesc.RasterizerState); - DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, *d3d12PSODesc.DepthStencilState); - - d3d12PSODesc.RTVFormatArray->NumRenderTargets = GraphicsPipeline.NumRenderTargets; - for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) - d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormatArray->RTFormats); ++rt) - d3d12PSODesc.RTVFormatArray->RTFormats[rt] = DXGI_FORMAT_UNKNOWN; - d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); - - d3d12PSODesc.SampleDesc->Count = GraphicsPipeline.SmplDesc.Count; - d3d12PSODesc.SampleDesc->Quality = GraphicsPipeline.SmplDesc.Quality; - - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; - - d3d12PSODesc.CachedPSO->pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO->CachedBlobSizeInBytes = 0; - - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - - D3D12_PIPELINE_STATE_STREAM_DESC streamDesc; - streamDesc.SizeInBytes = sizeof(d3d12PSODesc); - streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; - - auto* device2 = pDeviceD3D12->GetD3D12Device2(); - - CHECK_D3D_RESULT_THROW(device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)), "Failed to create pipeline state"); - break; - } -#endif // D3D12_H_HAS_MESH_SHADER - - default: - LOG_ERROR_AND_THROW("Unsupported pipeline type"); - } - - if (*m_Desc.Name != 0) - { - m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); - String RootSignatureDesc("Root signature for PSO '"); - RootSignatureDesc.append(m_Desc.Name); - RootSignatureDesc.push_back('\''); - m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); - } - if (m_Desc.SRBAllocationGranularity > 1) { std::array ShaderVarMgrDataSizes = {}; @@ -443,29 +507,6 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR m_ShaderResourceLayoutHash = m_RootSig.GetHash(); } -PipelineStateD3D12Impl::~PipelineStateD3D12Impl() -{ - auto& ShaderResLayoutAllocator = GetRawAllocator(); - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) - { - m_pStaticVarManagers[s].Destroy(GetRawAllocator()); - m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); - m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); - m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); - m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12(); - } - // m_pShaderResourceLayouts, m_pStaticResourceCaches, and m_pShaderResourceLayouts are allocated in - // contiguous chunks of memory. - auto* pRawMem = m_pShaderResourceLayouts; - ShaderResLayoutAllocator.Free(pRawMem); - - // D3D12 object can only be destroyed when it is no longer used by the GPU - m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask); -} - -IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase) - - void PipelineStateD3D12Impl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) { auto& SRBAllocator = m_pDevice->GetSRBAllocator(); diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index db86d662..97069bd2 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -534,7 +534,18 @@ void RenderDeviceD3D12Impl::TestTextureFormat(TEXTURE_FORMAT TexFormat) IMPLEMENT_QUERY_INTERFACE(RenderDeviceD3D12Impl, IID_RenderDeviceD3D12, TRenderDeviceBase) -void RenderDeviceD3D12Impl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +void RenderDeviceD3D12Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreateDeviceObject("Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, + [&]() // + { + PipelineStateD3D12Impl* pPipelineStateD3D12(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D12Impl instance", PipelineStateD3D12Impl)(this, PSOCreateInfo)); + pPipelineStateD3D12->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); + OnCreateDeviceObject(pPipelineStateD3D12); + }); +} + +void RenderDeviceD3D12Impl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) { CreateDeviceObject("Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, [&]() // diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp index dea1d6c8..55c53c25 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp @@ -37,6 +37,7 @@ #include "GLProgramResources.hpp" #include "GLPipelineResourceLayout.hpp" #include "GLProgramResourceCache.hpp" +#include "ShaderGLImpl.hpp" namespace Diligent { @@ -49,10 +50,14 @@ class PipelineStateGLImpl final : public PipelineStateBase; - PipelineStateGLImpl(IReferenceCounters* pRefCounters, - RenderDeviceGLImpl* pDeviceGL, - const PipelineStateCreateInfo& CreateInfo, - bool IsDeviceInternal = false); + PipelineStateGLImpl(IReferenceCounters* pRefCounters, + RenderDeviceGLImpl* pDeviceGL, + const GraphicsPipelineStateCreateInfo& CreateInfo, + bool IsDeviceInternal = false); + PipelineStateGLImpl(IReferenceCounters* pRefCounters, + RenderDeviceGLImpl* pDeviceGL, + const ComputePipelineStateCreateInfo& CreateInfo, + bool IsDeviceInternal = false); ~PipelineStateGLImpl(); /// Queries the specific interface, see IObject::QueryInterface() for details @@ -92,10 +97,25 @@ private: void InitStaticSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const; + struct GLPipelineShaderStageInfo + { + const SHADER_TYPE Type; + ShaderGLImpl* const pShader; + GLPipelineShaderStageInfo(SHADER_TYPE _Type, + ShaderGLImpl* _pShader) : + Type{_Type}, + pShader{_pShader} + {} + }; + void InitResourceLayouts(RenderDeviceGLImpl* pDeviceVk, + const std::vector& ShaderStages, + LinearAllocator& MemPool); + // Linked GL programs for every shader stage. Every pipeline needs to have its own programs // because resource bindings assigned by GLProgramResources::LoadUniforms depend on other // shader stages. - std::vector m_GLPrograms; + using GLProgramObj = GLObjectWrappers::GLProgramObj; + GLProgramObj* m_GLPrograms = nullptr; // [m_NumShaderStages] ThreadingTools::LockFlag m_ProgPipelineLockFlag; @@ -113,14 +133,15 @@ private: GLProgramResourceCache m_StaticResourceCache; // Program resources for all shader stages in the pipeline - std::vector m_ProgramResources; + GLProgramResources* m_ProgramResources = nullptr; // [m_NumShaderStages] Uint32 m_TotalUniformBufferBindings = 0; Uint32 m_TotalSamplerBindings = 0; Uint32 m_TotalImageBindings = 0; Uint32 m_TotalStorageBufferBindings = 0; - std::vector> m_StaticSamplers; + using SamplerPtr = RefCntAutoPtr; + SamplerPtr* m_StaticSamplers = nullptr; // [m_Desc.ResourceLayout.NumStaticSamplers] }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp index afb46edb..d23142e0 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp @@ -86,12 +86,20 @@ public: virtual void DILIGENT_CALL_TYPE CreateSampler(const SamplerDesc& SamplerDesc, ISampler** ppSampler) override final; - /// Implementation of IRenderDevice::CreatePipelineState() in OpenGL backend. - void CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, - IPipelineState** ppPipelineState, - bool bIsDeviceInternal); - virtual void DILIGENT_CALL_TYPE CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, - IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateGraphicsPipelineState() in OpenGL backend. + virtual void CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; + + /// Implementation of IRenderDevice::CreateComputePipelineState() in OpenGL backend. + virtual void CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; + + void CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState, + bool bIsDeviceInternal); + void CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState, + bool bIsDeviceInternal); /// Implementation of IRenderDevice::CreateFence() in OpenGL backend. virtual void DILIGENT_CALL_TYPE CreateFence(const FenceDesc& Desc, IFence** ppFence) override final; diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp index f4ef1136..d8af2feb 100644 --- a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp @@ -85,12 +85,12 @@ void DeviceContextGLImpl::SetPipelineState(IPipelineState* pPipelineState) TDeviceContextBase::SetPipelineState(pPipelineStateGLImpl, 0 /*Dummy*/); const auto& Desc = pPipelineStateGLImpl->GetDesc(); - if (Desc.IsComputePipeline()) + if (Desc.PipelineType == PIPELINE_TYPE_COMPUTE) { } else if (Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) { - const auto& GraphicsPipeline = Desc.GraphicsPipeline; + const auto& GraphicsPipeline = pPipelineStateGLImpl->GetGraphicsPipelineDesc(); // Set rasterizer state { const auto& RasterizerDesc = GraphicsPipeline.RasterizerDesc; @@ -896,7 +896,7 @@ void DeviceContextGLImpl::PrepareForDraw(DRAW_FLAGS Flags, bool IsIndexed, GLenu m_pPipelineState->CommitProgram(m_ContextState); auto CurrNativeGLContext = m_pDevice->m_GLContext.GetCurrentNativeGLContext(); - const auto& PipelineDesc = m_pPipelineState->GetDesc().GraphicsPipeline; + const auto& PipelineDesc = m_pPipelineState->GetGraphicsPipelineDesc(); if (!m_ContextState.IsValidVAOBound()) { auto& VAOCache = m_pDevice->GetVAOCache(CurrNativeGLContext); diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 8590e203..4ac36396 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -36,10 +36,10 @@ namespace Diligent { -PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, - RenderDeviceGLImpl* pDeviceGL, - const PipelineStateCreateInfo& CreateInfo, - bool bIsDeviceInternal) : +PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, + RenderDeviceGLImpl* pDeviceGL, + const GraphicsPipelineStateCreateInfo& CreateInfo, + bool bIsDeviceInternal) : // clang-format off TPipelineStateBase { @@ -52,8 +52,11 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun m_StaticResourceLayout{*this} // clang-format on { + std::vector ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + RefCntAutoPtr pTempPS; - if (m_Desc.IsAnyGraphicsPipeline() && m_Desc.GraphicsPipeline.pPS == nullptr) + if (CreateInfo.pPS == nullptr) { // Some OpenGL implementations fail if fragment shader is not present, so // create a dummy one. @@ -64,22 +67,92 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun ShaderCI.Desc.Name = "Dummy fragment shader"; pDeviceGL->CreateShader(ShaderCI, reinterpret_cast(static_cast(&pTempPS))); - m_Desc.GraphicsPipeline.pPS = pTempPS; + ShaderStages.emplace_back(SHADER_TYPE_PIXEL, pTempPS); + m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_PIXEL; } - struct GLPipelineShaderStageInfo + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(m_Desc.ResourceLayout.NumStaticSamplers); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); + + InitResourceLayouts(pDeviceGL, ShaderStages, MemPool); + InitGraphicsPipeline(CreateInfo, MemPool); + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_GLPrograms); +} + +PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, + RenderDeviceGLImpl* pDeviceGL, + const ComputePipelineStateCreateInfo& CreateInfo, + bool bIsDeviceInternal) : + // clang-format off + TPipelineStateBase { - const SHADER_TYPE Type; - ShaderGLImpl* const pShader; - GLPipelineShaderStageInfo(SHADER_TYPE _Type, - ShaderGLImpl* _pShader) : - Type{_Type}, - pShader{_pShader} - {} - }; + pRefCounters, + pDeviceGL, + CreateInfo.PSODesc, + bIsDeviceInternal + }, + m_ResourceLayout {*this}, + m_StaticResourceLayout{*this} +// clang-format on +{ std::vector ShaderStages; - ExtractShaders(ShaderStages); + ExtractShaders(CreateInfo, ShaderStages); + + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(m_Desc.ResourceLayout.NumStaticSamplers); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); + + InitResourceLayouts(pDeviceGL, ShaderStages, MemPool); + InitComputePipeline(CreateInfo, MemPool); + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_GLPrograms); +} +PipelineStateGLImpl::~PipelineStateGLImpl() +{ + auto& RawAllocator = GetRawAllocator(); + m_StaticResourceCache.Destroy(RawAllocator); + GetDevice()->OnDestroyPSO(this); + + for (Uint32 i = 0; i < GetNumShaderStages(); ++i) + { + m_GLPrograms[i].~GLProgramObj(); + m_ProgramResources[i].~GLProgramResources(); + } + for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumStaticSamplers; ++i) + { + m_StaticSamplers[i].~SamplerPtr(); + } + + void* pRawMem = m_GLPrograms; + RawAllocator.Free(pRawMem); +} + +IMPLEMENT_QUERY_INTERFACE(PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase) + + +void PipelineStateGLImpl::InitResourceLayouts(RenderDeviceGLImpl* pDeviceGL, + const std::vector& ShaderStages, + LinearAllocator& MemPool) +{ auto& DeviceCaps = pDeviceGL->GetDeviceCaps(); VERIFY(DeviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized"); @@ -97,13 +170,13 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun // Program pipelines are not shared between GL contexts, so we cannot create // it now m_ShaderResourceLayoutHash = 0; - m_ProgramResources.resize(ShaderStages.size()); - m_GLPrograms.reserve(ShaderStages.size()); + m_GLPrograms = MemPool.Allocate(ShaderStages.size()); + m_ProgramResources = MemPool.ConstructArray(ShaderStages.size()); for (size_t i = 0; i < ShaderStages.size(); ++i) { auto* pShaderGL = ShaderStages[i].pShader; const auto& ShaderDesc = pShaderGL->GetDesc(); - m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)); + new (m_GLPrograms + i) GLProgramObj{ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)}; // Load uniforms and assign bindings m_ProgramResources[i].LoadUniforms(ShaderDesc.ShaderType, m_GLPrograms[i], GLState, m_TotalUniformBufferBindings, @@ -126,8 +199,9 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun ActiveStages |= Stage.Type; } - m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(ShaderStages.size()), false)); - m_ProgramResources.resize(1); + m_GLPrograms = MemPool.Construct(ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(ShaderStages.size()), false)); + m_ProgramResources = MemPool.Construct(); + m_ProgramResources[0].LoadUniforms(ActiveStages, m_GLPrograms[0], GLState, m_TotalUniformBufferBindings, m_TotalSamplerBindings, @@ -138,10 +212,10 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun } // Initialize master resource layout that keeps all variable types and does not reference a resource cache - m_ResourceLayout.Initialize(m_ProgramResources.data(), static_cast(m_GLPrograms.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr); + m_ResourceLayout.Initialize(m_ProgramResources, static_cast(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr); } - m_StaticSamplers.resize(m_Desc.ResourceLayout.NumStaticSamplers); + m_StaticSamplers = MemPool.ConstructArray(m_Desc.ResourceLayout.NumStaticSamplers); for (Uint32 s = 0; s < m_Desc.ResourceLayout.NumStaticSamplers; ++s) { pDeviceGL->CreateSampler(m_Desc.ResourceLayout.StaticSamplers[s].Desc, &m_StaticSamplers[s]); @@ -150,26 +224,16 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun { // Clone only static variables into static resource layout, assign and initialize static resource cache const SHADER_RESOURCE_VARIABLE_TYPE StaticVars[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; - m_StaticResourceLayout.Initialize(m_ProgramResources.data(), static_cast(m_GLPrograms.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache); + m_StaticResourceLayout.Initialize(m_ProgramResources, static_cast(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache); InitStaticSamplersInResourceCache(m_StaticResourceLayout, m_StaticResourceCache); } } - -PipelineStateGLImpl::~PipelineStateGLImpl() -{ - m_StaticResourceCache.Destroy(GetRawAllocator()); - GetDevice()->OnDestroyPSO(this); -} - -IMPLEMENT_QUERY_INTERFACE(PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase) - - void PipelineStateGLImpl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) { auto* pRenderDeviceGL = GetDevice(); auto& SRBAllocator = pRenderDeviceGL->GetSRBAllocator(); - auto pResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingGLImpl instance", ShaderResourceBindingGLImpl)(this, m_ProgramResources.data(), static_cast(m_ProgramResources.size())); + auto pResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingGLImpl instance", ShaderResourceBindingGLImpl)(this, m_ProgramResources, GetNumShaderStages()); if (InitStaticResources) pResBinding->InitializeStaticResources(this); pResBinding->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast(ppShaderResourceBinding)); @@ -186,10 +250,10 @@ bool PipelineStateGLImpl::IsCompatibleWith(const IPipelineState* pPSO) const if (m_ShaderResourceLayoutHash != pPSOGL->m_ShaderResourceLayoutHash) return false; - if (m_ProgramResources.size() != pPSOGL->m_ProgramResources.size()) + if (GetNumShaderStages() != pPSOGL->GetNumShaderStages()) return false; - for (size_t i = 0; i < m_ProgramResources.size(); ++i) + for (size_t i = 0; i < GetNumShaderStages(); ++i) { if (!m_ProgramResources[i].IsCompatibleWith(pPSOGL->m_ProgramResources[i])) return false; @@ -214,7 +278,7 @@ void PipelineStateGLImpl::CommitProgram(GLContextState& State) } else { - VERIFY_EXPR(m_GLPrograms.size() == 1); + VERIFY_EXPR(m_GLPrograms != nullptr); State.SetProgram(m_GLPrograms[0]); } } diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index 466f1387..59b4bdfd 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -696,13 +696,20 @@ void RenderDeviceGLImpl::CreateSampler(const SamplerDesc& SamplerDesc, ISampler* CreateSampler(SamplerDesc, ppSampler, false); } - -void RenderDeviceGLImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +void RenderDeviceGLImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal) { - CreatePipelineState(PSOCreateInfo, ppPipelineState, false); + CreateDeviceObject( + "Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState, + [&]() // + { + PipelineStateGLImpl* pPipelineStateOGL(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateGLImpl instance", PipelineStateGLImpl)(this, PSOCreateInfo, bIsDeviceInternal)); + pPipelineStateOGL->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); + OnCreateDeviceObject(pPipelineStateOGL); + } // + ); } -void RenderDeviceGLImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal) +void RenderDeviceGLImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal) { CreateDeviceObject( "Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState, @@ -715,6 +722,16 @@ void RenderDeviceGLImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOC ); } +void RenderDeviceGLImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + return CreateGraphicsPipelineState(PSOCreateInfo, ppPipelineState, false); +} + +void RenderDeviceGLImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + return CreateComputePipelineState(PSOCreateInfo, ppPipelineState, false); +} + void RenderDeviceGLImpl::CreateFence(const FenceDesc& Desc, IFence** ppFence) { CreateDeviceObject( diff --git a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp index bd47e4ac..1a9c99c0 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp @@ -105,16 +105,15 @@ TexRegionRender::TexRegionRender(class RenderDeviceGLImpl* pDeviceGL) CBDesc.CPUAccessFlags = CPU_ACCESS_WRITE; pDeviceGL->CreateBuffer(CBDesc, nullptr, &m_pConstantBuffer, IsInternalDeviceObject); - PipelineStateCreateInfo PSOCreateInfo; - PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; + GraphicsPipelineStateCreateInfo PSOCreateInfo; - auto& GraphicsPipeline = PSODesc.GraphicsPipeline; + auto& GraphicsPipeline = PSOCreateInfo.GraphicsPipeline; GraphicsPipeline.RasterizerDesc.CullMode = CULL_MODE_NONE; GraphicsPipeline.RasterizerDesc.FillMode = FILL_MODE_SOLID; GraphicsPipeline.DepthStencilDesc.DepthEnable = False; GraphicsPipeline.DepthStencilDesc.DepthWriteEnable = False; - GraphicsPipeline.pVS = m_pVertexShader; + PSOCreateInfo.pVS = m_pVertexShader; GraphicsPipeline.PrimitiveTopology = PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; static const char* CmpTypePrefix[3] = {"", "i", "u"}; @@ -150,17 +149,17 @@ TexRegionRender::TexRegionRender(class RenderDeviceGLImpl* pDeviceGL) ShaderAttrs.Source = Source.c_str(); auto& FragmetShader = m_pFragmentShaders[Dim * 3 + Fmt]; pDeviceGL->CreateShader(ShaderAttrs, &FragmetShader, IsInternalDeviceObject); - GraphicsPipeline.pPS = FragmetShader; + PSOCreateInfo.pPS = FragmetShader; - PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; + PSOCreateInfo.PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; ShaderResourceVariableDesc Vars[] = { {SHADER_TYPE_PIXEL, "cbConstants", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE} // }; - PSODesc.ResourceLayout.NumVariables = _countof(Vars); - PSODesc.ResourceLayout.Variables = Vars; + PSOCreateInfo.PSODesc.ResourceLayout.NumVariables = _countof(Vars); + PSOCreateInfo.PSODesc.ResourceLayout.Variables = Vars; - pDeviceGL->CreatePipelineState(PSOCreateInfo, &m_pPSO[Dim * 3 + Fmt], IsInternalDeviceObject); + pDeviceGL->CreateGraphicsPipelineState(PSOCreateInfo, &m_pPSO[Dim * 3 + Fmt], IsInternalDeviceObject); } } m_pPSO[RESOURCE_DIM_TEX_2D * 3]->CreateShaderResourceBinding(&m_pSRB); diff --git a/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp index 8838b968..acb22e2a 100644 --- a/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp @@ -93,7 +93,7 @@ const GLObjectWrappers::GLVertexArrayObj& VAOCache::GetVAO(IPipelineState* // Get layout auto* pPSOGL = ValidatedCast(pPSO); auto* pIndexBufferGL = ValidatedCast(pIndexBuffer); - const auto& InputLayout = pPSOGL->GetDesc().GraphicsPipeline.InputLayout; + const auto& InputLayout = pPSOGL->GetGraphicsPipelineDesc().InputLayout; const LayoutElement* LayoutElems = InputLayout.LayoutElements; Uint32 NumElems = InputLayout.NumElements; // Construct the key diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index 2185dabd..1773e743 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -57,7 +57,8 @@ class PipelineStateVkImpl final : public PipelineStateBase; - PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const PipelineStateCreateInfo& CreateInfo); + PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const GraphicsPipelineStateCreateInfo& CreateInfo); + PipelineStateVkImpl(IReferenceCounters* pRefCounters, RenderDeviceVkImpl* pDeviceVk, const ComputePipelineStateCreateInfo& CreateInfo); ~PipelineStateVkImpl(); virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; @@ -125,6 +126,11 @@ public: void InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const; private: + using TShaderStages = ShaderResourceLayoutVk::TShaderStages; + void InitResourceLayouts(RenderDeviceVkImpl* pDeviceVk, + const PipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages); + const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const { VERIFY_EXPR(ShaderInd < GetNumShaderStages()); @@ -143,9 +149,9 @@ private: return m_StaticVarsMgrs[ShaderInd]; } - ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; - ShaderResourceCacheVk* m_StaticResCaches = nullptr; - ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr; + ShaderResourceLayoutVk* m_ShaderResourceLayouts = nullptr; // [m_NumShaderStages * 2] + ShaderResourceCacheVk* m_StaticResCaches = nullptr; // [m_NumShaderStages] + ShaderVariableManagerVk* m_StaticVarsMgrs = nullptr; // [m_NumShaderStages] // SRB memory allocator must be declared before m_pDefaultShaderResBinding SRBMemoryAllocator m_SRBMemAllocator; diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 25a9f44b..24f3345c 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -72,8 +72,11 @@ public: virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final; - /// Implementation of IRenderDevice::CreatePipelineState() in Vulkan backend. - virtual void DILIGENT_CALL_TYPE CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + /// Implementation of IRenderDevice::CreateGraphicsPipelineState() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; + + /// Implementation of IRenderDevice::CreateComputePipelineState() in Vulkan backend. + virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) override final; /// Implementation of IRenderDevice::CreateBuffer() in Vulkan backend. virtual void DILIGENT_CALL_TYPE CreateBuffer(const BufferDesc& BuffDesc, diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp index 2d7b9591..c8b231c2 100644 --- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp @@ -257,39 +257,49 @@ void DeviceContextVkImpl::SetPipelineState(IPipelineState* pPipelineState) else { const auto& OldPSODesc = m_pPipelineState->GetDesc(); - // Commit all graphics states when switching from compute pipeline + // Commit all graphics states when switching from non-graphics pipeline // This is necessary because if the command list had been flushed // and the first PSO set on the command list was a compute pipeline, // the states would otherwise never be committed (since m_pPipelineState != nullptr) - CommitStates = OldPSODesc.IsComputePipeline(); + CommitStates = !OldPSODesc.IsAnyGraphicsPipeline(); // We also need to update scissor rect if ScissorEnable state was disabled in previous pipeline - CommitScissor = !OldPSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable; + if (OldPSODesc.IsAnyGraphicsPipeline()) + CommitScissor = !m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable; } TDeviceContextBase::SetPipelineState(pPipelineStateVk, 0 /*Dummy*/); EnsureVkCmdBuffer(); - if (PSODesc.IsComputePipeline()) - { - auto vkPipeline = pPipelineStateVk->GetVkPipeline(); - m_CommandBuffer.BindComputePipeline(vkPipeline); - } - else - { - auto vkPipeline = pPipelineStateVk->GetVkPipeline(); - m_CommandBuffer.BindGraphicsPipeline(vkPipeline); + auto vkPipeline = pPipelineStateVk->GetVkPipeline(); - if (CommitStates) + switch (PSODesc.PipelineType) + { + case PIPELINE_TYPE_GRAPHICS: + case PIPELINE_TYPE_MESH: { - m_CommandBuffer.SetStencilReference(m_StencilRef); - m_CommandBuffer.SetBlendConstants(m_BlendFactors); - CommitViewports(); - } + auto& GraphicsPipeline = pPipelineStateVk->GetGraphicsPipelineDesc(); + m_CommandBuffer.BindGraphicsPipeline(vkPipeline); + + if (CommitStates) + { + m_CommandBuffer.SetStencilReference(m_StencilRef); + m_CommandBuffer.SetBlendConstants(m_BlendFactors); + CommitViewports(); + } - if (PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable && (CommitStates || CommitScissor)) + if (GraphicsPipeline.RasterizerDesc.ScissorEnable && (CommitStates || CommitScissor)) + { + CommitScissorRects(); + } + break; + } + case PIPELINE_TYPE_COMPUTE: { - CommitScissorRects(); + m_CommandBuffer.BindComputePipeline(vkPipeline); + break; } + default: + UNEXPECTED("unknown pipeline type"); } m_DescrSetBindInfo.Reset(); @@ -381,8 +391,11 @@ void DeviceContextVkImpl::CommitVkVertexBuffers() void DeviceContextVkImpl::DvpLogRenderPass_PSOMismatch() { + const auto& Desc = m_pPipelineState->GetDesc(); + const auto& GrPipeline = m_pPipelineState->GetGraphicsPipelineDesc(); + std::stringstream ss; - ss << "Active render pass is incomaptible with PSO '" << m_pPipelineState->GetDesc().Name + ss << "Active render pass is incomaptible with PSO '" << Desc.Name << "'. This indicates the mismatch between the number and/or format of bound render " "targets and/or depth stencil buffer and the PSO. Vulkand requires exact match.\n" " Bound render targets (" @@ -411,7 +424,6 @@ void DeviceContextVkImpl::DvpLogRenderPass_PSOMismatch() ss << ""; ss << "; Sample count: " << SampleCount; - const auto& GrPipeline = m_pPipelineState->GetDesc().GraphicsPipeline; ss << "\n PSO: render targets (" << Uint32{GrPipeline.NumRenderTargets} << "): "; for (Uint32 rt = 0; rt < GrPipeline.NumRenderTargets; ++rt) ss << ' ' << GetTextureFormatAttribs(GrPipeline.RTVFormats[rt]).Name; @@ -472,7 +484,7 @@ void DeviceContextVkImpl::PrepareForDraw(DRAW_FLAGS Flags) # endif #endif - if (m_pPipelineState->GetDesc().GraphicsPipeline.pRenderPass == nullptr) + if (m_pPipelineState->GetGraphicsPipelineDesc().pRenderPass == nullptr) { #ifdef DILIGENT_DEVELOPMENT if (m_pPipelineState->GetRenderPass()->GetVkRenderPass() != m_vkRenderPass) @@ -1110,7 +1122,7 @@ void DeviceContextVkImpl::SetViewports(Uint32 NumViewports, const Viewport* pVie void DeviceContextVkImpl::CommitScissorRects() { - VERIFY(m_pPipelineState && m_pPipelineState->GetDesc().GraphicsPipeline.RasterizerDesc.ScissorEnable, "Scissor test must be enabled in the graphics pipeline"); + VERIFY(m_pPipelineState && m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable, "Scissor test must be enabled in the graphics pipeline"); if (m_NumScissorRects == 0) return; // Scissors have not been set in the context yet @@ -1136,14 +1148,10 @@ void DeviceContextVkImpl::SetScissorRects(Uint32 NumRects, const Rect* pRects, U // Only commit scissor rects if scissor test is enabled in the rasterizer state. // If scissor is currently disabled, or no PSO is bound, scissor rects will be committed by // the SetPipelineState() when a PSO with enabled scissor test is set. - if (m_pPipelineState) + if (m_pPipelineState && m_pPipelineState->GetDesc().IsAnyGraphicsPipeline() && m_pPipelineState->GetGraphicsPipelineDesc().RasterizerDesc.ScissorEnable) { - const auto& PSODesc = m_pPipelineState->GetDesc(); - if (PSODesc.IsAnyGraphicsPipeline() && PSODesc.GraphicsPipeline.RasterizerDesc.ScissorEnable) - { - VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects"); - CommitScissorRects(); - } + VERIFY(NumRects == m_NumScissorRects, "Unexpected number of scissor rects"); + CommitScissorRects(); } } diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp index 5110c873..d6f4b0be 100644 --- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp +++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp @@ -154,12 +154,12 @@ std::array, 4> GenerateMipsVkHelper::CreatePSOs(TE m_DeviceVkImpl.CreateShader(CSCreateInfo, &pCS); - PipelineStateCreateInfo PSOCreateInfo; - PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; + ComputePipelineStateCreateInfo PSOCreateInfo; + PipelineStateDesc& PSODesc = PSOCreateInfo.PSODesc; - PSODesc.PipelineType = PIPELINE_TYPE_COMPUTE; - PSODesc.Name = name.c_str(); - PSODesc.ComputePipeline.pCS = pCS; + PSODesc.PipelineType = PIPELINE_TYPE_COMPUTE; + PSODesc.Name = name.c_str(); + PSOCreateInfo.pCS = pCS; PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; ShaderResourceVariableDesc VarDesc{SHADER_TYPE_COMPUTE, "CB", SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; @@ -170,7 +170,7 @@ std::array, 4> GenerateMipsVkHelper::CreatePSOs(TE PSODesc.ResourceLayout.StaticSamplers = &StaticSampler; PSODesc.ResourceLayout.NumStaticSamplers = 1; - m_DeviceVkImpl.CreatePipelineState(PSOCreateInfo, &PSOs[NonPowOfTwo]); + m_DeviceVkImpl.CreateComputePipelineState(PSOCreateInfo, &PSOs[NonPowOfTwo]); PSOs[NonPowOfTwo]->GetStaticVariableByName(SHADER_TYPE_COMPUTE, "CB")->Set(m_ConstantsCB); } #endif diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index fbc5fae3..3e4154be 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -196,7 +196,7 @@ static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk, std::vector& Stages, const PipelineLayout& Layout, - const PipelineStateDesc& Desc, + const PipelineStateDesc& PSODesc, VulkanUtilities::PipelineWrapper& Pipeline) { const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); @@ -214,21 +214,21 @@ static void CreateComputePipeline(RenderDeviceVkImpl* PipelineCI.stage = Stages[0]; PipelineCI.layout = Layout.GetVkPipelineLayout(); - Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, Desc.Name); + Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); } static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk, std::vector& Stages, const PipelineLayout& Layout, - const PipelineStateDesc& Desc, + const PipelineStateDesc& PSODesc, + const GraphicsPipelineDesc& GraphicsPipeline, VulkanUtilities::PipelineWrapper& Pipeline, RefCntAutoPtr& pRenderPass) { - const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); - const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); - auto& GraphicsPipeline = Desc.GraphicsPipeline; - auto& RPCache = pDeviceVk->GetImplicitRenderPassCache(); + const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); + const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice(); + auto& RPCache = pDeviceVk->GetImplicitRenderPassCache(); if (pRenderPass == nullptr) { @@ -276,7 +276,7 @@ static void CreateGraphicsPipeline(RenderDeviceVkImpl* TessStateCI.flags = 0; // reserved for future use PipelineCI.pTessellationState = &TessStateCI; - if (Desc.PipelineType == PIPELINE_TYPE_MESH) + if (PSODesc.PipelineType == PIPELINE_TYPE_MESH) { // Input assembly is not used in the mesh pipeline, so topology may contain any value. // Validation layers may generate a warning if point_list topology is used, so use MAX_ENUM value. @@ -394,40 +394,19 @@ static void CreateGraphicsPipeline(RenderDeviceVkImpl* PipelineCI.renderPass = pRenderPass.RawPtr()->GetVkRenderPass(); - PipelineCI.subpass = Desc.GraphicsPipeline.SubpassIndex; + PipelineCI.subpass = GraphicsPipeline.SubpassIndex; PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from PipelineCI.basePipelineIndex = -1; // an index into the pCreateInfos parameter to use as a pipeline to derive from - Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, Desc.Name); + Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); } - -PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, - RenderDeviceVkImpl* pDeviceVk, - const PipelineStateCreateInfo& CreateInfo) : - TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, - m_SRBMemAllocator{GetRawAllocator()} +void PipelineStateVkImpl::InitResourceLayouts(RenderDeviceVkImpl* pDeviceVk, + const PipelineStateCreateInfo& CreateInfo, + TShaderStages& ShaderStages) { - m_ResourceLayoutIndex.fill(-1); - const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); - ShaderResourceLayoutVk::TShaderStages ShaderStages; - ExtractShaders(ShaderStages); - - // clang-format off - static_assert((sizeof(ShaderResourceLayoutVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceLayoutVk) is expected to be a multiple of sizeof(void*)"); - static_assert((sizeof(ShaderResourceCacheVk) % sizeof(void*)) == 0, "sizeof(ShaderResourceCacheVk) is expected to be a multiple of sizeof(void*)"); - static_assert((sizeof(ShaderVariableManagerVk) % sizeof(void*)) == 0, "sizeof(ShaderVariableManagerVk) is expected to be a multiple of sizeof(void*)"); - // clang-format on - const auto MemSize = (sizeof(ShaderResourceLayoutVk) * 2 + sizeof(ShaderResourceCacheVk) + sizeof(ShaderVariableManagerVk)) * GetNumShaderStages(); - auto* const pRawMem = - ALLOCATE_RAW(GetRawAllocator(), "Raw memory for ShaderResourceLayoutVk, ShaderResourceCacheVk, and ShaderVariableManagerVk arrays", MemSize); - - m_ShaderResourceLayouts = reinterpret_cast(pRawMem); - m_StaticResCaches = reinterpret_cast(m_ShaderResourceLayouts + GetNumShaderStages() * 2); - m_StaticVarsMgrs = reinterpret_cast(m_StaticResCaches + GetNumShaderStages()); - for (size_t s = 0; s < ShaderStages.size(); ++s) { auto& StageInfo = ShaderStages[s]; @@ -436,7 +415,6 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice}; - m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); auto* pStaticResLayout = new (m_ShaderResourceLayouts + ShaderStages.size() + s) ShaderResourceLayoutVk{LogicalDevice}; @@ -469,22 +447,6 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize); } - // Create shader modules and initialize shader stages - std::vector VkShaderStages; - std::vector ShaderModules; - InitPipelineShaderStages(LogicalDevice, ShaderStages, ShaderModules, VkShaderStages); - - // Create pipeline - switch (m_Desc.PipelineType) - { - // clang-format off - case PIPELINE_TYPE_GRAPHICS: - case PIPELINE_TYPE_MESH: CreateGraphicsPipeline( pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline, m_pRenderPass); break; - case PIPELINE_TYPE_COMPUTE: CreateComputePipeline( pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); break; - default: UNEXPECTED("unknown pipeline type"); - // clang-format on - } - m_HasStaticResources = false; m_HasNonStaticResources = false; for (Uint32 s = 0; s < GetNumShaderStages(); ++s) @@ -501,6 +463,89 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun m_ShaderResourceLayoutHash = m_PipelineLayout.GetHash(); } + +PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVk, + const GraphicsPipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + m_ResourceLayoutIndex.fill(-1); + + ShaderResourceLayoutVk::TShaderStages ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages() * 2); + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); + + m_ShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); + m_StaticResCaches = MemPool.Allocate(GetNumShaderStages()); + m_StaticVarsMgrs = MemPool.Allocate(GetNumShaderStages()); + + InitGraphicsPipeline(CreateInfo, MemPool); + InitResourceLayouts(pDeviceVk, CreateInfo, ShaderStages); + + // Create shader modules and initialize shader stages + std::vector VkShaderStages; + std::vector ShaderModules; + InitPipelineShaderStages(pDeviceVk->GetLogicalDevice(), ShaderStages, ShaderModules, VkShaderStages); + + CreateGraphicsPipeline(pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); +} + + +PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVk, + const ComputePipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + m_ResourceLayoutIndex.fill(-1); + + ShaderResourceLayoutVk::TShaderStages ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddRequiredSize(GetNumShaderStages() * 2); + MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddRequiredSize(GetNumShaderStages()); + + ValidateAndReserveSpace(CreateInfo, MemPool); + + MemPool.Reserve(); + + m_ShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); + m_StaticResCaches = MemPool.Allocate(GetNumShaderStages()); + m_StaticVarsMgrs = MemPool.Allocate(GetNumShaderStages()); + + InitComputePipeline(CreateInfo, MemPool); + InitResourceLayouts(pDeviceVk, CreateInfo, ShaderStages); + + // Create shader modules and initialize shader stages + std::vector VkShaderStages; + std::vector ShaderModules; + InitPipelineShaderStages(pDeviceVk->GetLogicalDevice(), ShaderStages, ShaderModules, VkShaderStages); + + CreateComputePipeline(pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); +} + + PipelineStateVkImpl::~PipelineStateVkImpl() { m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask); diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index f6e337c2..ca729479 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -541,7 +541,21 @@ void RenderDeviceVkImpl::TestTextureFormat(TEXTURE_FORMAT TexFormat) IMPLEMENT_QUERY_INTERFACE(RenderDeviceVkImpl, IID_RenderDeviceVk, TRenderDeviceBase) -void RenderDeviceVkImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +void RenderDeviceVkImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreateDeviceObject( + "Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, + [&]() // + { + PipelineStateVkImpl* pPipelineStateVk(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateVkImpl instance", PipelineStateVkImpl)(this, PSOCreateInfo)); + pPipelineStateVk->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); + OnCreateDeviceObject(pPipelineStateVk); + } // + ); +} + + +void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) { CreateDeviceObject( "Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, -- cgit v1.2.3 From e7b18160a758b30dd6b701b4aa6f43c9c2061ccf Mon Sep 17 00:00:00 2001 From: assiduous Date: Sat, 17 Oct 2020 09:56:34 -0700 Subject: All backends: added resource dimension validation when setting shader variables --- .../src/GraphicsAccessories.cpp | 14 ++--- .../include/ShaderResourceVariableBase.hpp | 61 ++++++++++++++++++++-- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 20 +++---- .../src/ShaderResourceLayoutD3D11.cpp | 24 +++++---- .../src/ShaderResourceLayoutD3D12.cpp | 2 +- .../include/ShaderResources.hpp | 4 ++ .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 33 ++++++++++++ .../include/GLProgramResources.hpp | 10 ++++ .../ShaderTools/include/SPIRVShaderResources.hpp | 19 +++++-- Graphics/ShaderTools/src/SPIRVShaderResources.cpp | 42 +++++++++++++++ 10 files changed, 194 insertions(+), 35 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index b07a2194..7cc46ea1 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -791,13 +791,13 @@ const Char* GetResourceDimString(RESOURCE_DIMENSION TexType) { TexTypeStrings[RESOURCE_DIM_UNDEFINED] = "Undefined"; TexTypeStrings[RESOURCE_DIM_BUFFER] = "Buffer"; - TexTypeStrings[RESOURCE_DIM_TEX_1D] = "Tex 1D"; - TexTypeStrings[RESOURCE_DIM_TEX_1D_ARRAY] = "Tex 1D Array"; - TexTypeStrings[RESOURCE_DIM_TEX_2D] = "Tex 2D"; - TexTypeStrings[RESOURCE_DIM_TEX_2D_ARRAY] = "Tex 2D Array"; - TexTypeStrings[RESOURCE_DIM_TEX_3D] = "Tex 3D"; - TexTypeStrings[RESOURCE_DIM_TEX_CUBE] = "Tex Cube"; - TexTypeStrings[RESOURCE_DIM_TEX_CUBE_ARRAY] = "Tex Cube Array"; + TexTypeStrings[RESOURCE_DIM_TEX_1D] = "Texture 1D"; + TexTypeStrings[RESOURCE_DIM_TEX_1D_ARRAY] = "Texture 1D Array"; + TexTypeStrings[RESOURCE_DIM_TEX_2D] = "Texture 2D"; + TexTypeStrings[RESOURCE_DIM_TEX_2D_ARRAY] = "Texture 2D Array"; + TexTypeStrings[RESOURCE_DIM_TEX_3D] = "Texture 3D"; + TexTypeStrings[RESOURCE_DIM_TEX_CUBE] = "Texture Cube"; + TexTypeStrings[RESOURCE_DIM_TEX_CUBE_ARRAY] = "Texture Cube Array"; static_assert(RESOURCE_DIM_NUM_DIMENSIONS == RESOURCE_DIM_TEX_CUBE_ARRAY + 1, "Not all texture type strings initialized."); bTexTypeStrsInit = true; diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp index f82f18cf..78c1832d 100644 --- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp @@ -215,6 +215,28 @@ inline const char* GetResourceTypeName() return "buffer view"; } +inline RESOURCE_DIMENSION GetResourceViewDimension(const ITextureView* pTexView) +{ + VERIFY_EXPR(pTexView != nullptr); + return pTexView->GetDesc().TextureDim; +} + +inline RESOURCE_DIMENSION GetResourceViewDimension(const IBufferView* /*pBuffView*/) +{ + return RESOURCE_DIM_BUFFER; +} + +inline Uint32 GetResourceSampleCount(const ITextureView* pTexView) +{ + VERIFY_EXPR(pTexView != nullptr); + return const_cast(pTexView)->GetTexture()->GetDesc().SampleCount; +} + +inline Uint32 GetResourceSampleCount(const IBufferView* /*pBuffView*/) +{ + return 0; +} + template @@ -255,8 +277,6 @@ bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs, if (!IsExpectedViewType) { - std::string ExpectedViewTypeName; - std::stringstream ss; ss << "Error binding " << ExpectedResourceType << " '" << pViewImpl->GetDesc().Name << "' to variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; @@ -280,11 +300,45 @@ bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs, BindingOK = false; } + + const auto ExpectedResourceDim = Attribs.GetResourceDimension(); + if (ExpectedResourceDim != RESOURCE_DIM_UNDEFINED) + { + auto ResourceDim = GetResourceViewDimension(pViewImpl); + if (ResourceDim != ExpectedResourceDim) + { + LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '", + Attribs.GetPrintName(ArrayIndex), "': incorrect resource dimension: ", + GetResourceDimString(ExpectedResourceDim), " is expected, but the actual dimension is ", + GetResourceDimString(ResourceDim)); + + BindingOK = false; + } + + if (ResourceDim == RESOURCE_DIM_TEX_2D || ResourceDim == RESOURCE_DIM_TEX_2D_ARRAY) + { + auto SampleCount = GetResourceSampleCount(pViewImpl); + auto IsMS = Attribs.IsMultisample(); + if (IsMS && SampleCount == 1) + { + LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '", + Attribs.GetPrintName(ArrayIndex), "': multisample texture is expected."); + BindingOK = false; + } + else if (!IsMS && SampleCount > 1) + { + LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '", + Attribs.GetPrintName(ArrayIndex), "': single-sample texture is expected."); + BindingOK = false; + } + } + } } if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedView != nullptr && pCachedView != pViewImpl) { - auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType); + const auto* VarTypeStr = GetShaderVariableTypeLiteralName(VarType); + std::stringstream ss; ss << "Non-null resource '" << pCachedView->GetDesc().Name << "' is already bound to " << VarTypeStr << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\''; @@ -306,6 +360,7 @@ bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs, BindingOK = false; } + return BindingOK; } diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index b681c498..74e16535 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -211,16 +211,16 @@ DEFINE_FLAG_ENUM_OPERATORS(MAP_FLAGS) /// - TextureViewDesc to describe texture view type DILIGENT_TYPED_ENUM(RESOURCE_DIMENSION, Uint8) { - RESOURCE_DIM_UNDEFINED = 0, ///< Texture type undefined - RESOURCE_DIM_BUFFER, ///< Buffer - RESOURCE_DIM_TEX_1D, ///< One-dimensional texture - RESOURCE_DIM_TEX_1D_ARRAY, ///< One-dimensional texture array - RESOURCE_DIM_TEX_2D, ///< Two-dimensional texture - RESOURCE_DIM_TEX_2D_ARRAY, ///< Two-dimensional texture array - RESOURCE_DIM_TEX_3D, ///< Three-dimensional texture - RESOURCE_DIM_TEX_CUBE, ///< Cube-map texture - RESOURCE_DIM_TEX_CUBE_ARRAY, ///< Cube-map array texture - RESOURCE_DIM_NUM_DIMENSIONS ///< Helper value that stores the total number of texture types in the enumeration + RESOURCE_DIM_UNDEFINED = 0, ///< Texture type undefined + RESOURCE_DIM_BUFFER, ///< Buffer + RESOURCE_DIM_TEX_1D, ///< One-dimensional texture + RESOURCE_DIM_TEX_1D_ARRAY, ///< One-dimensional texture array + RESOURCE_DIM_TEX_2D, ///< Two-dimensional texture + RESOURCE_DIM_TEX_2D_ARRAY, ///< Two-dimensional texture array + RESOURCE_DIM_TEX_3D, ///< Three-dimensional texture + RESOURCE_DIM_TEX_CUBE, ///< Cube-map texture + RESOURCE_DIM_TEX_CUBE_ARRAY, ///< Cube-map array texture + RESOURCE_DIM_NUM_DIMENSIONS ///< Helper value that stores the total number of texture types in the enumeration }; /// Texture view type diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index 63b34f44..723e190a 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -429,7 +429,7 @@ void ShaderResourceLayoutD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* p // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type - RefCntAutoPtr pBuffD3D11Impl(pBuffer, IID_BufferD3D11); + RefCntAutoPtr pBuffD3D11Impl{pBuffer, IID_BufferD3D11}; #ifdef DILIGENT_DEVELOPMENT { auto& CachedCB = m_ParentResLayout.m_ResourceCache.GetCB(m_Attribs.BindPoint + ArrayIndex); @@ -448,11 +448,12 @@ void ShaderResourceLayoutD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pVie // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11(pView, IID_TextureViewD3D11); + 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()); + VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, + CachedSRV.pView.RawPtr(), m_ParentResLayout.GetShaderName()); } #endif @@ -505,7 +506,7 @@ void ShaderResourceLayoutD3D11::SamplerBindInfo::BindResource(IDeviceObject* pSa // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type - RefCntAutoPtr pSamplerD3D11(pSampler, IID_SamplerD3D11); + RefCntAutoPtr pSamplerD3D11{pSampler, IID_SamplerD3D11}; #ifdef DILIGENT_DEVELOPMENT if (pSampler && !pSamplerD3D11) @@ -548,11 +549,12 @@ void ShaderResourceLayoutD3D11::BuffSRVBindInfo::BindResource(IDeviceObject* pVi // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11(pView, IID_BufferViewD3D11); + 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()); + 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 @@ -569,11 +571,12 @@ void ShaderResourceLayoutD3D11::TexUAVBindInfo::BindResource(IDeviceObject* pVie // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11(pView, IID_TextureViewD3D11); + 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()); + 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)); @@ -589,11 +592,12 @@ void ShaderResourceLayoutD3D11::BuffUAVBindInfo::BindResource(IDeviceObject* pVi // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D11(pView, IID_BufferViewD3D11); + 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()); + 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 diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index f00d62e7..c0029da5 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -462,7 +462,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject* { // We cannot use ValidatedCast<> here as the resource retrieved from the // resource mapping can be of wrong type - RefCntAutoPtr pViewD3D12(pView, ResourceViewTraits::IID); + RefCntAutoPtr pViewD3D12{pView, ResourceViewTraits::IID}; #ifdef DILIGENT_DEVELOPMENT VerifyResourceViewBinding(Attribs, GetVariableType(), ArrayIndex, pView, pViewD3D12.RawPtr(), {dbgExpectedViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName()); ResourceViewTraits::VerifyView(pViewD3D12, Attribs, ParentResLayout.GetShaderName()); diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp index b5446ec3..2843f9f0 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp @@ -192,6 +192,10 @@ public: return static_cast(SRVDimension); } + RESOURCE_DIMENSION GetResourceDimension() const; + + bool IsMultisample() const; + bool IsCombinedWithSampler() const { return GetCombinedSamplerId() != InvalidSamplerId; diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 75ec17ea..498e31a2 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -454,6 +454,39 @@ HLSLShaderResourceDesc D3DShaderResourceAttribs::GetHLSLResourceDesc() const return ResourceDesc; } +RESOURCE_DIMENSION D3DShaderResourceAttribs::GetResourceDimension() const +{ + switch (GetSRVDimension()) + { + // clang-format off + case D3D_SRV_DIMENSION_BUFFER: return RESOURCE_DIM_BUFFER; + case D3D_SRV_DIMENSION_TEXTURE1D: return RESOURCE_DIM_TEX_1D; + case D3D_SRV_DIMENSION_TEXTURE1DARRAY: return RESOURCE_DIM_TEX_1D_ARRAY; + case D3D_SRV_DIMENSION_TEXTURE2D: return RESOURCE_DIM_TEX_2D; + case D3D_SRV_DIMENSION_TEXTURE2DARRAY: return RESOURCE_DIM_TEX_2D_ARRAY; + case D3D_SRV_DIMENSION_TEXTURE2DMS: return RESOURCE_DIM_TEX_2D; + case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: return RESOURCE_DIM_TEX_2D_ARRAY; + case D3D_SRV_DIMENSION_TEXTURE3D: return RESOURCE_DIM_TEX_3D; + case D3D_SRV_DIMENSION_TEXTURECUBE: return RESOURCE_DIM_TEX_CUBE; + case D3D_SRV_DIMENSION_TEXTURECUBEARRAY: return RESOURCE_DIM_TEX_CUBE_ARRAY; + // clang-format on + default: + return RESOURCE_DIM_BUFFER; + } +} + +bool D3DShaderResourceAttribs::IsMultisample() const +{ + switch (GetSRVDimension()) + { + case D3D_SRV_DIMENSION_TEXTURE2DMS: + case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: + return true; + default: + return false; + } +} + HLSLShaderResourceDesc ShaderResources::GetHLSLShaderResourceDesc(Uint32 Index) const { DEV_CHECK_ERR(Index < m_TotalResources, "Resource index (", Index, ") is out of range"); diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp b/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp index a3b13b6d..091d0e31 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp @@ -147,6 +147,16 @@ public: ResourceDesc.Type = ResourceType; return ResourceDesc; } + + RESOURCE_DIMENSION GetResourceDimension() const + { + return RESOURCE_DIM_UNDEFINED; + } + + bool IsMultisample() const + { + return false; + } }; struct UniformBufferInfo final : GLResourceAttribs diff --git a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp index 5c35de33..091e2343 100644 --- a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp +++ b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp @@ -78,10 +78,11 @@ struct SPIRVShaderResourceAttribs static constexpr const Uint32 InvalidSepSmplrOrImgInd = static_cast(-1); -/* 0 */const char* const Name; -/* 8 */const Uint16 ArraySize; -/* 10 */const ResourceType Type; -/* 11 */ // unused +/* 0 */const char* const Name; +/* 8 */const Uint16 ArraySize; +/* 10 */const ResourceType Type; +/* 11.0*/const Uint8 ResourceDim : 7; +/* 11.7*/const Uint8 IsMS : 1; private: // Defines the mapping between separate samplers and seperate images when HLSL-style // combined texture samplers are in use (i.e. texture2D g_Tex + sampler g_Tex_sampler). @@ -159,6 +160,16 @@ public: } ShaderResourceDesc GetResourceDesc() const; + + RESOURCE_DIMENSION GetResourceDimension() const + { + return static_cast(ResourceDim); + } + + bool IsMultisample() const + { + return IsMS != 0; + } }; static_assert(sizeof(SPIRVShaderResourceAttribs) % sizeof(void*) == 0, "Size of SPIRVShaderResourceAttribs struct must be multiple of sizeof(void*)"); diff --git a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp index be683d53..7fe1ed62 100644 --- a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp +++ b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp @@ -53,6 +53,46 @@ Type GetResourceArraySize(const diligent_spirv_cross::Compiler& Compiler, return static_cast(arrSize); } +static RESOURCE_DIMENSION GetResourceDimension(const diligent_spirv_cross::Compiler& Compiler, + const diligent_spirv_cross::Resource& Res) +{ + const auto& type = Compiler.get_type(Res.type_id); + if (type.basetype == diligent_spirv_cross::SPIRType::BaseType::Image || + type.basetype == diligent_spirv_cross::SPIRType::BaseType::SampledImage) + { + switch (type.image.dim) + { + // clang-format off + case spv::Dim1D: return type.image.arrayed ? RESOURCE_DIM_TEX_1D_ARRAY : RESOURCE_DIM_TEX_1D; + case spv::Dim2D: return type.image.arrayed ? RESOURCE_DIM_TEX_2D_ARRAY : RESOURCE_DIM_TEX_2D; + case spv::Dim3D: return RESOURCE_DIM_TEX_3D; + case spv::DimCube: return type.image.arrayed ? RESOURCE_DIM_TEX_CUBE_ARRAY : RESOURCE_DIM_TEX_CUBE; + case spv::DimBuffer: return RESOURCE_DIM_BUFFER; + // clang-format on + default: return RESOURCE_DIM_UNDEFINED; + } + } + else + { + return RESOURCE_DIM_UNDEFINED; + } +} + +static bool IsMultisample(const diligent_spirv_cross::Compiler& Compiler, + const diligent_spirv_cross::Resource& Res) +{ + const auto& type = Compiler.get_type(Res.type_id); + if (type.basetype == diligent_spirv_cross::SPIRType::BaseType::Image || + type.basetype == diligent_spirv_cross::SPIRType::BaseType::SampledImage) + { + return type.image.ms; + } + else + { + return RESOURCE_DIM_UNDEFINED; + } +} + static uint32_t GetDecorationOffset(const diligent_spirv_cross::Compiler& Compiler, const diligent_spirv_cross::Resource& Res, spv::Decoration Decoration) @@ -74,6 +114,8 @@ SPIRVShaderResourceAttribs::SPIRVShaderResourceAttribs(const diligent_spirv_cros Name {_Name}, ArraySize {GetResourceArraySize(Compiler, Res)}, Type {_Type}, + ResourceDim {Diligent::GetResourceDimension(Compiler, Res)}, + IsMS {Diligent::IsMultisample(Compiler, Res) ? Uint8{1} : Uint8{0}}, SepSmplrOrImgInd {_SepSmplrOrImgInd}, BindingDecorationOffset {GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationBinding)}, DescriptorSetDecorationOffset {GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationDescriptorSet)} -- cgit v1.2.3 From e8f439dc0f87f6820e3db53ecd8ee41cc878d90c Mon Sep 17 00:00:00 2001 From: azhirnov Date: Sat, 17 Oct 2020 20:02:58 +0300 Subject: Fixed compilation, some fixes after review --- Graphics/GraphicsEngine/include/PipelineStateBase.hpp | 2 +- Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index d8cb09bb..ef5b38c2 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -118,7 +118,7 @@ public: return m_ShaderResourceLayoutHash != ValidatedCast(pPSO)->m_ShaderResourceLayoutHash; } - const GraphicsPipelineDesc& GetGraphicsPipelineDesc() const override final + virtual const GraphicsPipelineDesc& DILIGENT_CALL_TYPE GetGraphicsPipelineDesc() const override final { VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline()); VERIFY_EXPR(m_pGraphicsPipelineDesc != nullptr); diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp index d23142e0..5c8037c3 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp @@ -87,12 +87,12 @@ public: ISampler** ppSampler) override final; /// Implementation of IRenderDevice::CreateGraphicsPipelineState() in OpenGL backend. - virtual void CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, - IPipelineState** ppPipelineState) override final; + virtual void DILIGENT_CALL_TYPE CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; /// Implementation of IRenderDevice::CreateComputePipelineState() in OpenGL backend. - virtual void CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, - IPipelineState** ppPipelineState) override final; + virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, + IPipelineState** ppPipelineState) override final; void CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, -- cgit v1.2.3 From 645ef7e425d6ff4ee64b782d27767e0a5732be50 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 18 Oct 2020 13:06:48 -0700 Subject: A number of fixes for PSO creation refactoring (API240075) --- Graphics/GraphicsEngine/CMakeLists.txt | 1 + .../GraphicsEngine/include/DeviceContextBase.hpp | 8 +- .../GraphicsEngine/include/PipelineStateBase.hpp | 450 +++++++-------------- Graphics/GraphicsEngine/interface/APIInfo.h | 119 +++--- Graphics/GraphicsEngine/interface/PipelineState.h | 10 +- Graphics/GraphicsEngine/interface/RenderDevice.h | 4 +- Graphics/GraphicsEngine/src/APIInfo.cpp | 2 + Graphics/GraphicsEngine/src/PipelineStateBase.cpp | 260 ++++++++++++ .../include/PipelineStateD3D11Impl.hpp | 6 +- .../include/RenderDeviceD3D11Impl.hpp | 3 + .../src/DeviceContextD3D11Impl.cpp | 4 +- .../src/PipelineStateD3D11Impl.cpp | 93 ++--- .../src/RenderDeviceD3D11Impl.cpp | 41 +- .../include/PipelineStateD3D12Impl.hpp | 7 +- .../include/RenderDeviceD3D12Impl.hpp | 3 + .../src/DeviceContextD3D12Impl.cpp | 2 + .../src/PipelineStateD3D12Impl.cpp | 70 ++-- .../src/RenderDeviceD3D12Impl.cpp | 41 +- .../include/PipelineStateGLImpl.hpp | 7 +- .../include/RenderDeviceGLImpl.hpp | 3 + .../src/PipelineStateGLImpl.cpp | 62 ++- .../src/RenderDeviceGLImpl.cpp | 18 +- .../GraphicsEngineOpenGL/src/TexRegionRender.cpp | 8 +- .../include/PipelineStateVkImpl.hpp | 9 +- .../include/RenderDeviceVkImpl.hpp | 3 + .../src/PipelineStateVkImpl.cpp | 77 ++-- .../src/RenderDeviceVkImpl.cpp | 18 +- 27 files changed, 721 insertions(+), 608 deletions(-) create mode 100644 Graphics/GraphicsEngine/src/PipelineStateBase.cpp (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt index b99138ca..d95257fe 100644 --- a/Graphics/GraphicsEngine/CMakeLists.txt +++ b/Graphics/GraphicsEngine/CMakeLists.txt @@ -66,6 +66,7 @@ set(SOURCE src/DefaultShaderSourceStreamFactory.cpp src/EngineMemory.cpp src/FramebufferBase.cpp + src/PipelineStateBase.cpp src/ResourceMappingBase.cpp src/RenderPassBase.cpp src/TextureBase.cpp diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp index 90285834..4eebd683 100644 --- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp +++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp @@ -1664,6 +1664,13 @@ inline void DeviceContextBase:: return; } + const auto& PSODesc = m_pPipelineState->GetDesc(); + if (!PSODesc.IsAnyGraphicsPipeline()) + { + LOG_ERROR_MESSAGE("Pipeline state '", PSODesc.Name, "' is not a graphics pipeline"); + return; + } + TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN}; TEXTURE_FORMAT BoundDSVFormat = TEX_FORMAT_UNKNOWN; @@ -1677,7 +1684,6 @@ inline void DeviceContextBase:: BoundDSVFormat = m_pBoundDepthStencil ? m_pBoundDepthStencil->GetDesc().Format : TEX_FORMAT_UNKNOWN; - const auto& PSODesc = m_pPipelineState->GetDesc(); const auto& GraphicsPipeline = m_pPipelineState->GetGraphicsPipelineDesc(); if (GraphicsPipeline.NumRenderTargets != m_NumBoundRenderTargets) { diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index ef5b38c2..cda2247e 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -43,6 +43,11 @@ namespace Diligent { +void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false); +void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false); + +void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept; + /// Template class implementing base functionality for a pipeline state object. /// \tparam BaseInterface - base interface that this class will inheret @@ -57,10 +62,10 @@ class PipelineStateBase : public DeviceObjectBase; - /// \param pRefCounters - reference counters object that controls the lifetime of this PSO - /// \param pDevice - pointer to the device. - /// \param CreateInfo - graphics pipeline state create info. - /// \param bIsDeviceInternal - flag indicating if the pipeline state is an internal device object and + /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO + /// \param pDevice - Pointer to the device. + /// \param CreateInfo - Pipeline state create info. + /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and /// must not keep a strong reference to the device. PipelineStateBase(IReferenceCounters* pRefCounters, RenderDeviceImplType* pDevice, @@ -75,6 +80,35 @@ public: this->m_Desc.CommandQueueMask &= DeviceQueuesMask; } + /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO + /// \param pDevice - Pointer to the device. + /// \param GraphicsPipelineCI - Graphics pipeline create information. + /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and + /// must not keep a strong reference to the device. + PipelineStateBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const GraphicsPipelineStateCreateInfo& GraphicsPipelineCI, + bool bIsDeviceInternal = false) : + PipelineStateBase{pRefCounters, pDevice, GraphicsPipelineCI.PSODesc, bIsDeviceInternal} + { + ValidateGraphicsPipelineCreateInfo(GraphicsPipelineCI); + } + + /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO + /// \param pDevice - Pointer to the device. + /// \param ComputePipelineCI - Compute pipeline create information. + /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and + /// must not keep a strong reference to the device. + PipelineStateBase(IReferenceCounters* pRefCounters, + RenderDeviceImplType* pDevice, + const ComputePipelineStateCreateInfo& ComputePipelineCI, + bool bIsDeviceInternal = false) : + PipelineStateBase{pRefCounters, pDevice, ComputePipelineCI.PSODesc, bIsDeviceInternal} + { + ValidateComputePipelineCreateInfo(ComputePipelineCI); + } + + ~PipelineStateBase() { /* @@ -125,25 +159,7 @@ public: return *m_pGraphicsPipelineDesc; } - -protected: - size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout - - Uint32* m_pStrides = nullptr; - Uint8 m_BufferSlotsUsed = 0; - - Uint8 m_NumShaderStages = 0; ///< Number of shader stages in this PSO - - /// Array of shader types for every shader stage used by this PSO - std::array m_ShaderStageTypes = {}; - - RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object - - GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr; - protected: -#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(this->m_Desc.PipelineType), " PSO '", this->m_Desc.Name, "' is invalid: ", ##__VA_ARGS__) - Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array& ResourceLayoutIndex) const { if (!IsConsistentShaderType(ShaderType, this->m_Desc.PipelineType)) @@ -204,239 +220,31 @@ protected: return LayoutInd; } -private: - void CheckRasterizerStateDesc(GraphicsPipelineDesc& GraphicsPipeline) const - { - const auto& RSDesc = GraphicsPipeline.RasterizerDesc; - if (RSDesc.FillMode == FILL_MODE_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED"); - if (RSDesc.CullMode == CULL_MODE_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED"); - } - - void CheckAndCorrectDepthStencilDesc(GraphicsPipelineDesc& GraphicsPipeline) const - { - auto& DSSDesc = GraphicsPipeline.DepthStencilDesc; - if (DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN) - { - if (DSSDesc.DepthEnable) - LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled"); - else - DSSDesc.DepthFunc = DepthStencilStateDesc{}.DepthFunc; - } - - auto CheckAndCorrectStencilOpDesc = [&](StencilOpDesc& OpDesc, const char* FaceName) // - { - if (DSSDesc.StencilEnable) - { - if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); - if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); - if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); - if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN) - LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled"); - } - else - { - if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED) - OpDesc.StencilFailOp = StencilOpDesc{}.StencilFailOp; - if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED) - OpDesc.StencilDepthFailOp = StencilOpDesc{}.StencilDepthFailOp; - if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED) - OpDesc.StencilPassOp = StencilOpDesc{}.StencilPassOp; - if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN) - OpDesc.StencilFunc = StencilOpDesc{}.StencilFunc; - } - }; - CheckAndCorrectStencilOpDesc(DSSDesc.FrontFace, "FrontFace"); - CheckAndCorrectStencilOpDesc(DSSDesc.BackFace, "BackFace"); - } - void CheckAndCorrectBlendStateDesc(GraphicsPipelineDesc& GraphicsPipeline) const + void ReserveSpaceForPipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) { - auto& BlendDesc = GraphicsPipeline.BlendDesc; - for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) - { - auto& RTDesc = BlendDesc.RenderTargets[rt]; - // clang-format off - const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0)); - const auto LogicOpEnable = RTDesc.LogicOperationEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0)); - // clang-format on - if (BlendEnable) - { - if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED"); - if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED"); - if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED"); - - if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); - if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); - if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED) - LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED"); - } - else - { - if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED) - RTDesc.SrcBlend = RenderTargetBlendDesc{}.SrcBlend; - if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED) - RTDesc.DestBlend = RenderTargetBlendDesc{}.DestBlend; - if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED) - RTDesc.BlendOp = RenderTargetBlendDesc{}.BlendOp; - - if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED) - RTDesc.SrcBlendAlpha = RenderTargetBlendDesc{}.SrcBlendAlpha; - if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED) - RTDesc.DestBlendAlpha = RenderTargetBlendDesc{}.DestBlendAlpha; - if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED) - RTDesc.BlendOpAlpha = RenderTargetBlendDesc{}.BlendOpAlpha; - } - - if (!LogicOpEnable) - RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp; - } - } + MemPool.AddSpace(); + ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); - void ValidateResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) const - { - if (SrcLayout.Variables != nullptr) - { - MemPool.AddRequiredSize(SrcLayout.NumVariables); - for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) - { - VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); - MemPool.AddRequiredSize(strlen(SrcLayout.Variables[i].Name) + 1); - } - } - - if (SrcLayout.StaticSamplers != nullptr) - { - MemPool.AddRequiredSize(SrcLayout.NumStaticSamplers); - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) - { - VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); - MemPool.AddRequiredSize(strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1); - } - } - } - - void ValidateGraphicsPipeline(const GraphicsPipelineDesc& GraphicsPipeline, LinearAllocator& MemPool) const - { - if (GraphicsPipeline.pRenderPass != nullptr) - { - if (GraphicsPipeline.NumRenderTargets != 0) - LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used"); - if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN) - LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); - - for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) - { - if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN) - LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); - } - - const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc(); - if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount) - LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'"); - } - else - { - if (GraphicsPipeline.SubpassIndex != 0) - LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used"); - } - - const auto& InputLayout = GraphicsPipeline.InputLayout; - Uint32 BufferSlotsUsed = 0; - MemPool.AddRequiredSize(InputLayout.NumElements); + const auto& InputLayout = CreateInfo.GraphicsPipeline.InputLayout; + MemPool.AddSpace(InputLayout.NumElements); for (Uint32 i = 0; i < InputLayout.NumElements; ++i) { auto& LayoutElem = InputLayout.LayoutElements[i]; - MemPool.AddRequiredSize(strlen(LayoutElem.HLSLSemantic) + 1); - BufferSlotsUsed = std::max(BufferSlotsUsed, LayoutElem.BufferSlot + 1); - } - - MemPool.AddRequiredSize(BufferSlotsUsed); - } - - void InitResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) const - { - if (SrcLayout.Variables != nullptr) - { - auto* Variables = MemPool.Allocate(SrcLayout.NumVariables); - DstLayout.Variables = Variables; - for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) - { - Variables[i] = SrcLayout.Variables[i]; - Variables[i].Name = MemPool.CopyString(SrcLayout.Variables[i].Name); - } - } - - if (SrcLayout.StaticSamplers != nullptr) - { - auto* StaticSamplers = MemPool.Allocate(SrcLayout.NumStaticSamplers); - DstLayout.StaticSamplers = StaticSamplers; - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) - { -#ifdef DILIGENT_DEVELOPMENT - { - const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor; - if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) || - (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) || - (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1))) - { - LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcLayout.StaticSamplers[i].SamplerOrTextureName, "\" specifies border color (", - BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3], - "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors"); - } - } -#endif - - StaticSamplers[i] = SrcLayout.StaticSamplers[i]; - StaticSamplers[i].SamplerOrTextureName = MemPool.CopyString(SrcLayout.StaticSamplers[i].SamplerOrTextureName); - } + MemPool.AddSpaceForString(LayoutElem.HLSLSemantic); + m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, static_cast(LayoutElem.BufferSlot + 1)); } - } -protected: -#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \ - if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \ - { \ - LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ + MemPool.AddSpace(m_BufferSlotsUsed); } - void ValidateAndReserveSpace(const GraphicsPipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) const + void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) const { - VALIDATE_SHADER_TYPE(CreateInfo.pVS, SHADER_TYPE_VERTEX, "vertex") - VALIDATE_SHADER_TYPE(CreateInfo.pPS, SHADER_TYPE_PIXEL, "pixel") - VALIDATE_SHADER_TYPE(CreateInfo.pGS, SHADER_TYPE_GEOMETRY, "geometry") - VALIDATE_SHADER_TYPE(CreateInfo.pHS, SHADER_TYPE_HULL, "hull") - VALIDATE_SHADER_TYPE(CreateInfo.pDS, SHADER_TYPE_DOMAIN, "domain") - VALIDATE_SHADER_TYPE(CreateInfo.pAS, SHADER_TYPE_AMPLIFICATION, "amplification") - VALIDATE_SHADER_TYPE(CreateInfo.pMS, SHADER_TYPE_MESH, "mesh") - - MemPool.AddRequiredSize(1); - ValidateResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); - - ValidateGraphicsPipeline(CreateInfo.GraphicsPipeline, MemPool); + ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); } - void ValidateAndReserveSpace(const ComputePipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) const - { - if (CreateInfo.pCS == nullptr) - { - LOG_ERROR_AND_THROW("Compute shader is not provided"); - } - VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute"); - - ValidateResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); - } template void ExtractShaders(const GraphicsPipelineStateCreateInfo& CreateInfo, @@ -450,6 +258,7 @@ protected: { auto ShaderType = pShader->GetDesc().ShaderType; ShaderStages.emplace_back(ShaderType, ValidatedCast(pShader)); + VERIFY(m_ShaderStageTypes[m_NumShaderStages] == SHADER_TYPE_UNKNOWN, "This shader stage is already initialized."); m_ShaderStageTypes[m_NumShaderStages++] = ShaderType; } }; @@ -463,6 +272,7 @@ protected: AddShaderStage(CreateInfo.pDS); AddShaderStage(CreateInfo.pGS); AddShaderStage(CreateInfo.pPS); + VERIFY(CreateInfo.pVS != nullptr, "Vertex shader must not be null"); break; } @@ -471,6 +281,7 @@ protected: AddShaderStage(CreateInfo.pAS); AddShaderStage(CreateInfo.pMS); AddShaderStage(CreateInfo.pPS); + VERIFY(CreateInfo.pMS != nullptr, "Mesh shader must not be null"); break; } @@ -488,63 +299,29 @@ protected: VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once."); ShaderStages.clear(); - auto AddShaderStage = [&](IShader* pShader) { - if (pShader != nullptr) - { - auto ShaderType = pShader->GetDesc().ShaderType; - ShaderStages.emplace_back(ShaderType, ValidatedCast(pShader)); - m_ShaderStageTypes[m_NumShaderStages++] = ShaderType; - } - }; - AddShaderStage(CreateInfo.pCS); + VERIFY_EXPR(CreateInfo.PSODesc.PipelineType == PIPELINE_TYPE_COMPUTE); + VERIFY_EXPR(CreateInfo.pCS != nullptr); + VERIFY_EXPR(CreateInfo.pCS->GetDesc().ShaderType == SHADER_TYPE_COMPUTE); + + ShaderStages.emplace_back(SHADER_TYPE_COMPUTE, ValidatedCast(CreateInfo.pCS)); + m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_COMPUTE; VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages); } - void InitGraphicsPipeline(const GraphicsPipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) + void InitializePipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) { - this->m_pGraphicsPipelineDesc = MemPool.CopyArray(&CreateInfo.GraphicsPipeline, 1); + this->m_pGraphicsPipelineDesc = MemPool.Copy(CreateInfo.GraphicsPipeline); - InitResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + auto& GraphicsPipeline = *this->m_pGraphicsPipelineDesc; + CorrectGraphicsPipelineDesc(GraphicsPipeline); - auto& GraphicsPipeline = *this->m_pGraphicsPipelineDesc; - const auto& PSODesc = this->m_Desc; - - CheckAndCorrectBlendStateDesc(GraphicsPipeline); - CheckRasterizerStateDesc(GraphicsPipeline); - CheckAndCorrectDepthStencilDesc(GraphicsPipeline); - - if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) - { - DEV_CHECK_ERR(CreateInfo.pVS, "Vertex shader must be defined"); - DEV_CHECK_ERR(!CreateInfo.pAS && !CreateInfo.pMS, "Mesh shaders are not supported in graphics pipeline"); - } - else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH) - { - DEV_CHECK_ERR(CreateInfo.pMS, "Mesh shader must be defined"); - DEV_CHECK_ERR(!CreateInfo.pVS && !CreateInfo.pGS && !CreateInfo.pDS && !CreateInfo.pHS, - "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline"); - DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout ignored in mesh shader"); - DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || - GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED, - "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)"); - } + CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); m_pRenderPass = GraphicsPipeline.pRenderPass; - - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) - { - auto RTVFmt = GraphicsPipeline.RTVFormats[rt]; - if (RTVFmt != TEX_FORMAT_UNKNOWN) - { - LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt, - " must be set to TEX_FORMAT_UNKNOWN"); - } - } - if (m_pRenderPass) { const auto& RPDesc = m_pRenderPass->GetDesc(); @@ -577,8 +354,10 @@ protected: LayoutElement* pLayoutElements = MemPool.Allocate(InputLayout.NumElements); for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem) { - pLayoutElements[Elem] = InputLayout.LayoutElements[Elem]; - pLayoutElements[Elem].HLSLSemantic = MemPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic); + const auto& SrcElem = InputLayout.LayoutElements[Elem]; + pLayoutElements[Elem] = SrcElem; + VERIFY_EXPR(SrcElem.HLSLSemantic != nullptr); + pLayoutElements[Elem].HLSLSemantic = MemPool.CopyString(SrcElem.HLSLSemantic); } GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements; @@ -599,10 +378,10 @@ protected: auto BuffSlot = LayoutElem.BufferSlot; if (BuffSlot >= Strides.size()) { - UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")"); + UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds the maximum allowed value (", Strides.size() - 1, ")"); continue; } - m_BufferSlotsUsed = static_cast(std::max(m_BufferSlotsUsed, BuffSlot + 1)); + VERIFY_EXPR(BuffSlot < m_BufferSlotsUsed); auto& CurrAutoStride = TightStrides[BuffSlot]; // If offset is not explicitly specified, use current auto stride value @@ -662,14 +441,91 @@ protected: } } - void InitComputePipeline(const ComputePipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) + void InitializePipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, + LinearAllocator& MemPool) { - InitResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); + CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool); } -#undef VALIDATE_SHADER_TYPE -#undef LOG_PSO_ERROR_AND_THROW +private: + void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) const + { + if (SrcLayout.Variables != nullptr) + { + MemPool.AddSpace(SrcLayout.NumVariables); + for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) + { + VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null"); + MemPool.AddSpaceForString(SrcLayout.Variables[i].Name); + } + } + + if (SrcLayout.StaticSamplers != nullptr) + { + MemPool.AddSpace(SrcLayout.NumStaticSamplers); + for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + { + VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); + MemPool.AddSpaceForString(SrcLayout.StaticSamplers[i].SamplerOrTextureName); + } + } + } + + void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) const + { + if (SrcLayout.Variables != nullptr) + { + auto* Variables = MemPool.Allocate(SrcLayout.NumVariables); + DstLayout.Variables = Variables; + for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i) + { + const auto& SrcVar = SrcLayout.Variables[i]; + Variables[i] = SrcVar; + Variables[i].Name = MemPool.CopyString(SrcVar.Name); + } + } + + if (SrcLayout.StaticSamplers != nullptr) + { + auto* StaticSamplers = MemPool.Allocate(SrcLayout.NumStaticSamplers); + DstLayout.StaticSamplers = StaticSamplers; + for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + { + const auto& SrcSmplr = SrcLayout.StaticSamplers[i]; +#ifdef DILIGENT_DEVELOPMENT + { + const auto& BorderColor = SrcSmplr.Desc.BorderColor; + if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) || + (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) || + (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1))) + { + LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcSmplr.SamplerOrTextureName, "\" specifies border color (", + BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3], + "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors"); + } + } +#endif + + StaticSamplers[i] = SrcSmplr; + StaticSamplers[i].SamplerOrTextureName = MemPool.CopyString(SrcSmplr.SamplerOrTextureName); + } + } + } + +protected: + size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout + + Uint32* m_pStrides = nullptr; + Uint8 m_BufferSlotsUsed = 0; + + Uint8 m_NumShaderStages = 0; ///< Number of shader stages in this PSO + + /// Array of shader types for every shader stage used by this PSO + std::array m_ShaderStageTypes = {}; + + RefCntAutoPtr m_pRenderPass; ///< Strong reference to the render pass object + + GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index a7596e3f..10cf096e 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240074 +#define DILIGENT_API_VERSION 240075 #include "../../../Primitives/interface/BasicTypes.h" @@ -39,64 +39,65 @@ DILIGENT_BEGIN_NAMESPACE(Diligent) /// Diligent API Info. This tructure can be used to verify API compatibility. struct APIInfo { - size_t StructSize DEFAULT_INITIALIZER(0); - int APIVersion DEFAULT_INITIALIZER(0); - size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0); - size_t BlendStateDescSize DEFAULT_INITIALIZER(0); - size_t BufferDescSize DEFAULT_INITIALIZER(0); - size_t BufferDataSize DEFAULT_INITIALIZER(0); - size_t BufferFormatSize DEFAULT_INITIALIZER(0); - size_t BufferViewDescSize DEFAULT_INITIALIZER(0); - size_t StencilOpDescSize DEFAULT_INITIALIZER(0); - size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0); - size_t SamplerCapsSize DEFAULT_INITIALIZER(0); - size_t TextureCapsSize DEFAULT_INITIALIZER(0); - size_t DeviceCapsSize DEFAULT_INITIALIZER(0); - size_t DrawAttribsSize DEFAULT_INITIALIZER(0); - size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0); - size_t ViewportSize DEFAULT_INITIALIZER(0); - size_t RectSize DEFAULT_INITIALIZER(0); - size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0); - size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0); - size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0); - size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0); - size_t SwapChainDescSize DEFAULT_INITIALIZER(0); - size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0); - size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0); - size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0); - size_t BoxSize DEFAULT_INITIALIZER(0); - size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0); - size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0); - size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0); - size_t StateTransitionDescSize DEFAULT_INITIALIZER(0); - size_t LayoutElementSize DEFAULT_INITIALIZER(0); - size_t InputLayoutDescSize DEFAULT_INITIALIZER(0); - size_t SampleDescSize DEFAULT_INITIALIZER(0); - size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0); - size_t StaticSamplerDescSize DEFAULT_INITIALIZER(0); - size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0); - size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0); - size_t ComputePipelineDescSize DEFAULT_INITIALIZER(0); - size_t PipelineStateDescSize DEFAULT_INITIALIZER(0); - size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0); - size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0); - size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0); - size_t SamplerDescSize DEFAULT_INITIALIZER(0); - size_t ShaderDescSize DEFAULT_INITIALIZER(0); - size_t ShaderMacroSize DEFAULT_INITIALIZER(0); - size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0); - size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0); - size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0); - size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0); - size_t TextureDescSize DEFAULT_INITIALIZER(0); - size_t TextureSubResDataSize DEFAULT_INITIALIZER(0); - size_t TextureDataSize DEFAULT_INITIALIZER(0); - size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0); - size_t TextureViewDescSize DEFAULT_INITIALIZER(0); + size_t StructSize DEFAULT_INITIALIZER(0); + int APIVersion DEFAULT_INITIALIZER(0); + size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0); + size_t BlendStateDescSize DEFAULT_INITIALIZER(0); + size_t BufferDescSize DEFAULT_INITIALIZER(0); + size_t BufferDataSize DEFAULT_INITIALIZER(0); + size_t BufferFormatSize DEFAULT_INITIALIZER(0); + size_t BufferViewDescSize DEFAULT_INITIALIZER(0); + size_t StencilOpDescSize DEFAULT_INITIALIZER(0); + size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0); + size_t SamplerCapsSize DEFAULT_INITIALIZER(0); + size_t TextureCapsSize DEFAULT_INITIALIZER(0); + size_t DeviceCapsSize DEFAULT_INITIALIZER(0); + size_t DrawAttribsSize DEFAULT_INITIALIZER(0); + size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0); + size_t ViewportSize DEFAULT_INITIALIZER(0); + size_t RectSize DEFAULT_INITIALIZER(0); + size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0); + size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0); + size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0); + size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0); + size_t SwapChainDescSize DEFAULT_INITIALIZER(0); + size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0); + size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0); + size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0); + size_t BoxSize DEFAULT_INITIALIZER(0); + size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0); + size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0); + size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0); + size_t StateTransitionDescSize DEFAULT_INITIALIZER(0); + size_t LayoutElementSize DEFAULT_INITIALIZER(0); + size_t InputLayoutDescSize DEFAULT_INITIALIZER(0); + size_t SampleDescSize DEFAULT_INITIALIZER(0); + size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0); + size_t StaticSamplerDescSize DEFAULT_INITIALIZER(0); + size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0); + size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0); + size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t ComputePipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); + size_t PipelineStateDescSize DEFAULT_INITIALIZER(0); + size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0); + size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0); + size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0); + size_t SamplerDescSize DEFAULT_INITIALIZER(0); + size_t ShaderDescSize DEFAULT_INITIALIZER(0); + size_t ShaderMacroSize DEFAULT_INITIALIZER(0); + size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0); + size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0); + size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0); + size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0); + size_t TextureDescSize DEFAULT_INITIALIZER(0); + size_t TextureSubResDataSize DEFAULT_INITIALIZER(0); + size_t TextureDataSize DEFAULT_INITIALIZER(0); + size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0); + size_t TextureViewDescSize DEFAULT_INITIALIZER(0); }; typedef struct APIInfo APIInfo; diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index e5682e58..cef07c66 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -324,6 +324,13 @@ struct ComputePipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo) /// Compute shader to be used with the pipeline IShader* pCS DEFAULT_INITIALIZER(nullptr); + +#if DILIGENT_CPP_INTERFACE + ComputePipelineStateCreateInfo() noexcept + { + PSODesc.PipelineType = PIPELINE_TYPE_COMPUTE; + } +#endif }; typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo; @@ -349,7 +356,8 @@ DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject) virtual const PipelineStateDesc& METHOD(GetDesc)() const override = 0; #endif - /// Returns the graphics pipeline description used to create the object + /// Returns the graphics pipeline description used to create the object. + /// This method must only be called for a graphics or mesh pipeline. VIRTUAL const GraphicsPipelineDesc REF METHOD(GetGraphicsPipelineDesc)(THIS) CONST PURE; /// Binds resources for all shaders in the pipeline state diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index ea4e05af..5c72c81a 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -155,7 +155,7 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) /// Creates a new graphics pipeline state object - /// \param [in] PSOCreateInfo - Pipeline state create info, see Diligent::GraphicsPipelineStateCreateInfo for details. + /// \param [in] PSOCreateInfo - Graphics pipeline state create info, see Diligent::GraphicsPipelineStateCreateInfo for details. /// \param [out] ppPipelineState - Address of the memory location where the pointer to the /// pipeline state interface will be stored. /// The function calls AddRef(), so that the new object will contain @@ -166,7 +166,7 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) /// Creates a new compute pipeline state object - /// \param [in] PSOCreateInfo - Pipeline state create info, see Diligent::ComputePipelineStateCreateInfo for details. + /// \param [in] PSOCreateInfo - Compute pipeline state create info, see Diligent::ComputePipelineStateCreateInfo for details. /// \param [out] ppPipelineState - Address of the memory location where the pointer to the /// pipeline state interface will be stored. /// The function calls AddRef(), so that the new object will contain diff --git a/Graphics/GraphicsEngine/src/APIInfo.cpp b/Graphics/GraphicsEngine/src/APIInfo.cpp index 05aef568..aa2fb3d9 100644 --- a/Graphics/GraphicsEngine/src/APIInfo.cpp +++ b/Graphics/GraphicsEngine/src/APIInfo.cpp @@ -90,6 +90,8 @@ static APIInfo InitAPIInfo() INIT_STRUCTURE_SIZE(StaticSamplerDesc); INIT_STRUCTURE_SIZE(PipelineResourceLayoutDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineDesc); + INIT_STRUCTURE_SIZE(GraphicsPipelineStateCreateInfo); + INIT_STRUCTURE_SIZE(ComputePipelineStateCreateInfo); INIT_STRUCTURE_SIZE(PipelineStateDesc); INIT_STRUCTURE_SIZE(RasterizerStateDesc); INIT_STRUCTURE_SIZE(ResourceMappingEntry); diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp new file mode 100644 index 00000000..fedc332d --- /dev/null +++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp @@ -0,0 +1,260 @@ +/* + * Copyright 2019-2020 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 "PipelineStateBase.hpp" + +namespace Diligent +{ + +#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(PSODesc.PipelineType), " PSO '", PSODesc.Name, "' is invalid: ", ##__VA_ARGS__) + +namespace +{ + +void ValidateRasterizerStateDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false) +{ + const auto& RSDesc = GraphicsPipeline.RasterizerDesc; + if (RSDesc.FillMode == FILL_MODE_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED"); + if (RSDesc.CullMode == CULL_MODE_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED"); +} + +void ValidateDepthStencilDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false) +{ + const auto& DSSDesc = GraphicsPipeline.DepthStencilDesc; + if (DSSDesc.DepthEnable && DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled"); + + auto CheckStencilOpDesc = [&](const StencilOpDesc& OpDesc, const char* FaceName) // + { + if (DSSDesc.StencilEnable) + { + if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); + if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); + if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled"); + if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled"); + } + }; + CheckStencilOpDesc(DSSDesc.FrontFace, "FrontFace"); + CheckStencilOpDesc(DSSDesc.BackFace, "BackFace"); +} + +void CorrectDepthStencilDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept +{ + auto& DSSDesc = GraphicsPipeline.DepthStencilDesc; + if (!DSSDesc.DepthEnable && DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN) + DSSDesc.DepthFunc = DepthStencilStateDesc{}.DepthFunc; + + auto CorrectStencilOpDesc = [&](StencilOpDesc& OpDesc) // + { + if (!DSSDesc.StencilEnable) + { + if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED) + OpDesc.StencilFailOp = StencilOpDesc{}.StencilFailOp; + if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED) + OpDesc.StencilDepthFailOp = StencilOpDesc{}.StencilDepthFailOp; + if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED) + OpDesc.StencilPassOp = StencilOpDesc{}.StencilPassOp; + if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN) + OpDesc.StencilFunc = StencilOpDesc{}.StencilFunc; + } + }; + CorrectStencilOpDesc(DSSDesc.FrontFace); + CorrectStencilOpDesc(DSSDesc.BackFace); +} + +void ValidateBlendStateDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false) +{ + const auto& BlendDesc = GraphicsPipeline.BlendDesc; + for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) + { + auto& RTDesc = BlendDesc.RenderTargets[rt]; + + const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0)); + if (BlendEnable) + { + if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED"); + if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED"); + if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED"); + + if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); + if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED"); + if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED) + LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED"); + } + } +} + +void CorrectBlendStateDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept +{ + auto& BlendDesc = GraphicsPipeline.BlendDesc; + for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) + { + auto& RTDesc = BlendDesc.RenderTargets[rt]; + // clang-format off + const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0)); + const auto LogicOpEnable = RTDesc.LogicOperationEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0)); + // clang-format on + if (!BlendEnable) + { + if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED) + RTDesc.SrcBlend = RenderTargetBlendDesc{}.SrcBlend; + if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED) + RTDesc.DestBlend = RenderTargetBlendDesc{}.DestBlend; + if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED) + RTDesc.BlendOp = RenderTargetBlendDesc{}.BlendOp; + + if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED) + RTDesc.SrcBlendAlpha = RenderTargetBlendDesc{}.SrcBlendAlpha; + if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED) + RTDesc.DestBlendAlpha = RenderTargetBlendDesc{}.DestBlendAlpha; + if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED) + RTDesc.BlendOpAlpha = RenderTargetBlendDesc{}.BlendOpAlpha; + } + + if (!LogicOpEnable) + RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp; + } +} + +} // namespace + +#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \ + if (Shader != nullptr && Shader->GetDesc().ShaderType != ExpectedType) \ + { \ + LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \ + } + +void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false) +{ + const auto& PSODesc = CreateInfo.PSODesc; + if (PSODesc.PipelineType != PIPELINE_TYPE_GRAPHICS && PSODesc.PipelineType != PIPELINE_TYPE_MESH) + LOG_PSO_ERROR_AND_THROW("Pipeline type must be GRAPHICS or MESH"); + + const auto& GraphicsPipeline = CreateInfo.GraphicsPipeline; + + ValidateBlendStateDesc(PSODesc, GraphicsPipeline); + ValidateRasterizerStateDesc(PSODesc, GraphicsPipeline); + ValidateDepthStencilDesc(PSODesc, GraphicsPipeline); + + + if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS) + { + if (CreateInfo.pVS == nullptr) + LOG_ERROR_AND_THROW("Vertex shader must not be null"); + + DEV_CHECK_ERR(CreateInfo.pAS == nullptr && CreateInfo.pMS == nullptr, "Mesh shaders are not supported in graphics pipeline"); + } + else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH) + { + if (CreateInfo.pMS == nullptr) + LOG_ERROR_AND_THROW("Mesh shader must not be null"); + + DEV_CHECK_ERR(CreateInfo.pVS == nullptr && CreateInfo.pGS == nullptr && CreateInfo.pDS == nullptr && CreateInfo.pHS == nullptr, + "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline"); + DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout is ignored in a mesh pipeline"); + DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST || + GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED, + "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)"); + } + + + VALIDATE_SHADER_TYPE(CreateInfo.pVS, SHADER_TYPE_VERTEX, "vertex") + VALIDATE_SHADER_TYPE(CreateInfo.pPS, SHADER_TYPE_PIXEL, "pixel") + VALIDATE_SHADER_TYPE(CreateInfo.pGS, SHADER_TYPE_GEOMETRY, "geometry") + VALIDATE_SHADER_TYPE(CreateInfo.pHS, SHADER_TYPE_HULL, "hull") + VALIDATE_SHADER_TYPE(CreateInfo.pDS, SHADER_TYPE_DOMAIN, "domain") + VALIDATE_SHADER_TYPE(CreateInfo.pAS, SHADER_TYPE_AMPLIFICATION, "amplification") + VALIDATE_SHADER_TYPE(CreateInfo.pMS, SHADER_TYPE_MESH, "mesh") + + + if (GraphicsPipeline.pRenderPass != nullptr) + { + if (GraphicsPipeline.NumRenderTargets != 0) + LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used"); + if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); + + for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt) + { + if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN) + LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used"); + } + + const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc(); + if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount) + LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'"); + } + else + { + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt) + { + auto RTVFmt = GraphicsPipeline.RTVFormats[rt]; + if (RTVFmt != TEX_FORMAT_UNKNOWN) + { + LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt, + " must be set to TEX_FORMAT_UNKNOWN"); + } + } + + if (GraphicsPipeline.SubpassIndex != 0) + LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used"); + } +} + +void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false) +{ + const auto& PSODesc = CreateInfo.PSODesc; + if (PSODesc.PipelineType != PIPELINE_TYPE_COMPUTE) + LOG_PSO_ERROR_AND_THROW("Pipeline type must be COMPUTE"); + + if (CreateInfo.pCS == nullptr) + LOG_ERROR_AND_THROW("Compute shader must not be null"); + + VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute"); +} +#undef VALIDATE_SHADER_TYPE +#undef LOG_PSO_ERROR_AND_THROW + +void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept +{ + CorrectBlendStateDesc(GraphicsPipeline); + CorrectDepthStencilDesc(GraphicsPipeline); +} + +} // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 99062706..eb184710 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -137,8 +137,10 @@ public: void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; private: - void InitResourceLayouts(RenderDeviceD3D11Impl* pRenderDeviceD3D11, - const PipelineStateCreateInfo& CreateInfo, + template + LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo); + + void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, const std::vector>& ShaderStages); CComPtr m_pd3d11BlendState; diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp index 1a1e01af..c2a1285c 100644 --- a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp @@ -124,6 +124,9 @@ public: Uint64 GetCommandQueueMask() const { return Uint64{1}; } private: + template + void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState); + virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; EngineD3D11CreateInfo m_EngineAttribs; diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp index 39560453..7ee1ccec 100755 --- a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp @@ -106,7 +106,7 @@ void DeviceContextD3D11Impl::SetPipelineState(IPipelineState* pPipelineState) COMMIT_SHADER(DS, DomainShader); #undef COMMIT_SHADER - auto& GraphicsPipeline = pPipelineStateD3D11->GetGraphicsPipelineDesc(); + const auto& GraphicsPipeline = pPipelineStateD3D11->GetGraphicsPipelineDesc(); m_pd3d11DeviceContext->OMSetBlendState(pPipelineStateD3D11->GetD3D11BlendState(), m_BlendFactors, GraphicsPipeline.SampleMask); m_pd3d11DeviceContext->RSSetState(pPipelineStateD3D11->GetD3D11RasterizerState()); @@ -673,7 +673,7 @@ void DeviceContextD3D11Impl::SetBlendFactors(const float* pBlendFactors) { Uint32 SampleMask = 0xFFFFFFFF; ID3D11BlendState* pd3d11BS = nullptr; - if (m_pPipelineState) + if (m_pPipelineState && m_pPipelineState->GetDesc().IsAnyGraphicsPipeline()) { SampleMask = m_pPipelineState->GetGraphicsPipelineDesc().SampleMask; pd3d11BS = m_pPipelineState->GetD3D11BlendState(); diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index d20e0c32..292a9323 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -35,42 +35,49 @@ namespace Diligent { -PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D11Impl* pRenderDeviceD3D11, - const GraphicsPipelineStateCreateInfo& CreateInfo) : - // clang-format off - TPipelineStateBase - { - pRefCounters, - pRenderDeviceD3D11, - CreateInfo.PSODesc - }, - m_SRBMemAllocator{GetRawAllocator()}, - m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")) -// clang-format on +template +LinearAllocator PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo) { m_ResourceLayoutIndex.fill(-1); - // We do not really need ShaderStages, but ExtractShaders() also initializes - // shader stage types and shader stage counter. std::vector> ShaderStages; ExtractShaders(CreateInfo, ShaderStages); // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddSpace(GetNumShaderStages()); + MemPool.AddSpace(GetNumShaderStages()); - ValidateAndReserveSpace(CreateInfo, MemPool); + ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); m_pStaticResourceLayouts = MemPool.Allocate(GetNumShaderStages()); m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); - InitGraphicsPipeline(CreateInfo, MemPool); - InitResourceLayouts(pRenderDeviceD3D11, CreateInfo, ShaderStages); + InitializePipelineDesc(CreateInfo, MemPool); + InitResourceLayouts(CreateInfo, ShaderStages); + + return MemPool; +} + + +PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D11Impl* pRenderDeviceD3D11, + const GraphicsPipelineStateCreateInfo& CreateInfo) : + // clang-format off + TPipelineStateBase + { + pRefCounters, + pRenderDeviceD3D11, + CreateInfo + }, + m_SRBMemAllocator{GetRawAllocator()}, + m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")) +// clang-format on +{ + auto MemPool = InitInternalObjects(CreateInfo); auto& GraphicsPipeline = GetGraphicsPipelineDesc(); @@ -131,7 +138,7 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* "Failed to create the Direct3D11 input layout"); } - void* Ptr = MemPool.Release(); + auto* Ptr = MemPool.Release(); VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); } @@ -143,49 +150,27 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* { pRefCounters, pRenderDeviceD3D11, - CreateInfo.PSODesc + CreateInfo }, m_SRBMemAllocator{GetRawAllocator()}, m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")) // clang-format on { - m_ResourceLayoutIndex.fill(-1); - - // We do not really need ShaderStages, but ExtractShaders() also initializes - // shader stage types and shader stage counter. - std::vector> ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); - - // Memory must be released if an exception is thrown. - LinearAllocator MemPool{GetRawAllocator()}; - - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); - - ValidateAndReserveSpace(CreateInfo, MemPool); - - MemPool.Reserve(); - - m_pStaticResourceLayouts = MemPool.Allocate(GetNumShaderStages()); - m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); - - InitComputePipeline(CreateInfo, MemPool); - InitResourceLayouts(pRenderDeviceD3D11, CreateInfo, ShaderStages); + auto MemPool = InitInternalObjects(CreateInfo); - auto* pCS = ValidatedCast(CreateInfo.pCS); - m_pCS = pCS; + m_pCS = ValidatedCast(CreateInfo.pCS); if (m_pCS == nullptr) { LOG_ERROR_AND_THROW("Compute shader is null"); } - if (m_pCS && m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE) + 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 = pCS->GetD3D11Resources()->GetHash(); + m_ShaderResourceLayoutHash = m_pCS->GetD3D11Resources()->GetHash(); - void* Ptr = MemPool.Release(); + auto* Ptr = MemPool.Release(); VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); } @@ -209,8 +194,7 @@ PipelineStateD3D11Impl::~PipelineStateD3D11Impl() IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase) -void PipelineStateD3D11Impl::InitResourceLayouts(RenderDeviceD3D11Impl* pRenderDeviceD3D11, - const PipelineStateCreateInfo& CreateInfo, +void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, const std::vector>& ShaderStages) { const auto& ResourceLayout = m_Desc.ResourceLayout; @@ -269,7 +253,7 @@ void PipelineStateD3D11Impl::InitResourceLayouts(RenderDeviceD3D11Impl* { const auto& SrcStaticSamplerInfo = ResourceLayout.StaticSamplers[SrcStaticSamplerInd]; RefCntAutoPtr pStaticSampler; - pRenderDeviceD3D11->CreateSampler(SrcStaticSamplerInfo.Desc, &pStaticSampler); + GetDevice()->CreateSampler(SrcStaticSamplerInfo.Desc, &pStaticSampler); StaticSamplers.emplace_back(SamplerAttribs, std::move(pStaticSampler)); } } @@ -328,9 +312,8 @@ ID3D11InputLayout* PipelineStateD3D11Impl::GetD3D11InputLayout() void PipelineStateD3D11Impl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources) { - auto* pRenderDeviceD3D11 = ValidatedCast(GetDevice()); - auto& SRBAllocator = pRenderDeviceD3D11->GetSRBAllocator(); - auto pShaderResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingD3D11Impl instance", ShaderResourceBindingD3D11Impl)(this, false); + 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))); diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index 537d9db2..94847a51 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -254,7 +254,7 @@ void RenderDeviceD3D11Impl::CreateBufferFromD3DResource(ID3D11Buffer* pd3d11Buff CreateDeviceObject("buffer", BuffDesc, ppBuffer, [&]() // { - BufferD3D11Impl* pBufferD3D11(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d11Buffer)); + 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); @@ -266,7 +266,7 @@ void RenderDeviceD3D11Impl::CreateBuffer(const BufferDesc& BuffDesc, const Buffe CreateDeviceObject("buffer", BuffDesc, ppBuffer, [&]() // { - BufferD3D11Impl* pBufferD3D11(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData)); + 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); @@ -278,7 +278,7 @@ void RenderDeviceD3D11Impl::CreateShader(const ShaderCreateInfo& ShaderCI, IShad CreateDeviceObject("shader", ShaderCI.Desc, ppShader, [&]() // { - ShaderD3D11Impl* pShaderD3D11(NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D11Impl instance", ShaderD3D11Impl)(this, ShaderCI)); + ShaderD3D11Impl* pShaderD3D11{NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D11Impl instance", ShaderD3D11Impl)(this, ShaderCI)}; pShaderD3D11->QueryInterface(IID_Shader, reinterpret_cast(ppShader)); OnCreateDeviceObject(pShaderD3D11); @@ -295,7 +295,7 @@ void RenderDeviceD3D11Impl::CreateTexture1DFromD3DResource(ID3D11Texture1D* pd3d CreateDeviceObject("texture", TexDesc, ppTexture, [&]() // { - TextureBaseD3D11* pTextureD3D11 = NEW_RC_OBJ(m_TexObjAllocator, "Texture1D_D3D11 instance", Texture1D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture); + 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); @@ -312,7 +312,7 @@ void RenderDeviceD3D11Impl::CreateTexture2DFromD3DResource(ID3D11Texture2D* pd3d CreateDeviceObject("texture", TexDesc, ppTexture, [&]() // { - TextureBaseD3D11* pTextureD3D11 = NEW_RC_OBJ(m_TexObjAllocator, "Texture2D_D3D11 instance", Texture2D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture); + 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); @@ -329,7 +329,7 @@ void RenderDeviceD3D11Impl::CreateTexture3DFromD3DResource(ID3D11Texture3D* pd3d CreateDeviceObject("texture", TexDesc, ppTexture, [&]() // { - TextureBaseD3D11* pTextureD3D11 = NEW_RC_OBJ(m_TexObjAllocator, "Texture3D_D3D11 instance", Texture3D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture); + 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); @@ -377,7 +377,7 @@ void RenderDeviceD3D11Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampl m_SamplersRegistry.Find(SamplerDesc, reinterpret_cast(ppSampler)); if (*ppSampler == nullptr) { - SamplerD3D11Impl* pSamplerD3D11(NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D11Impl instance", SamplerD3D11Impl)(this, SamplerDesc)); + 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); @@ -385,26 +385,27 @@ void RenderDeviceD3D11Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampl }); } -void RenderDeviceD3D11Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +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)); + PipelineStateD3D11Impl* pPipelineStateD3D11{NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D11Impl instance", PipelineStateD3D11Impl)(this, PSOCreateInfo)}; pPipelineStateD3D11->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); OnCreateDeviceObject(pPipelineStateD3D11); }); } + +void RenderDeviceD3D11Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreatePipelineState(PSOCreateInfo, ppPipelineState); +} + void RenderDeviceD3D11Impl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& 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); - }); + CreatePipelineState(PSOCreateInfo, ppPipelineState); } void RenderDeviceD3D11Impl::CreateFence(const FenceDesc& Desc, IFence** ppFence) @@ -412,7 +413,7 @@ void RenderDeviceD3D11Impl::CreateFence(const FenceDesc& Desc, IFence** ppFence) CreateDeviceObject("Fence", Desc, ppFence, [&]() // { - FenceD3D11Impl* pFenceD3D11(NEW_RC_OBJ(m_FenceAllocator, "FenceD3D11Impl instance", FenceD3D11Impl)(this, Desc)); + FenceD3D11Impl* pFenceD3D11{NEW_RC_OBJ(m_FenceAllocator, "FenceD3D11Impl instance", FenceD3D11Impl)(this, Desc)}; pFenceD3D11->QueryInterface(IID_Fence, reinterpret_cast(ppFence)); OnCreateDeviceObject(pFenceD3D11); }); @@ -423,7 +424,7 @@ void RenderDeviceD3D11Impl::CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) CreateDeviceObject("Query", Desc, ppQuery, [&]() // { - QueryD3D11Impl* pQueryD3D11(NEW_RC_OBJ(m_QueryAllocator, "QueryD3D11Impl instance", QueryD3D11Impl)(this, Desc)); + QueryD3D11Impl* pQueryD3D11{NEW_RC_OBJ(m_QueryAllocator, "QueryD3D11Impl instance", QueryD3D11Impl)(this, Desc)}; pQueryD3D11->QueryInterface(IID_Query, reinterpret_cast(ppQuery)); OnCreateDeviceObject(pQueryD3D11); }); @@ -434,7 +435,7 @@ void RenderDeviceD3D11Impl::CreateRenderPass(const RenderPassDesc& Desc, IRender CreateDeviceObject("RenderPass", Desc, ppRenderPass, [&]() // { - RenderPassD3D11Impl* pRenderPassD3D11(NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D11Impl instance", RenderPassD3D11Impl)(this, Desc)); + RenderPassD3D11Impl* pRenderPassD3D11{NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D11Impl instance", RenderPassD3D11Impl)(this, Desc)}; pRenderPassD3D11->QueryInterface(IID_RenderPass, reinterpret_cast(ppRenderPass)); OnCreateDeviceObject(pRenderPassD3D11); }); @@ -445,7 +446,7 @@ void RenderDeviceD3D11Impl::CreateFramebuffer(const FramebufferDesc& Desc, IFram CreateDeviceObject("Framebuffer", Desc, ppFramebuffer, [&]() // { - FramebufferD3D11Impl* pFramebufferD3D11(NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D11Impl instance", FramebufferD3D11Impl)(this, Desc)); + FramebufferD3D11Impl* pFramebufferD3D11{NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D11Impl instance", FramebufferD3D11Impl)(this, Desc)}; pFramebufferD3D11->QueryInterface(IID_Framebuffer, reinterpret_cast(ppFramebuffer)); OnCreateDeviceObject(pFramebufferD3D11); }); diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index 821ff951..31d95179 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -131,8 +131,11 @@ private: pShader{_pShader} {} }; - void InitResourceLayouts(RenderDeviceD3D12Impl* pDeviceD3D12, - const PipelineStateCreateInfo& CreateInfo, + + template + LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& ShaderStages); + + void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, std::vector& ShaderStages); CComPtr m_pd3d12PSO; diff --git a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp index 7083e30d..34a77213 100644 --- a/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp @@ -165,6 +165,9 @@ public: D3D_FEATURE_LEVEL GetD3DFeatureLevel() const; private: + template + void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState); + virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; void FreeCommandContext(PooledCommandContext&& Ctx); diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp index f1bc35eb..938c9468 100644 --- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp @@ -254,11 +254,13 @@ void DeviceContextD3D12Impl::SetPipelineState(IPipelineState* pPipelineState) } break; } + case PIPELINE_TYPE_COMPUTE: { CmdCtx.AsComputeContext().SetPipelineState(pd3d12PSO); break; } + default: UNEXPECTED("unknown pipeline type"); } diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index 0d26db2a..f04a309e 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -98,38 +98,49 @@ private: std::array m_Map; }; -PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, - RenderDeviceD3D12Impl* pDeviceD3D12, - const GraphicsPipelineStateCreateInfo& CreateInfo) : - TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, - m_SRBMemAllocator{GetRawAllocator()} +template +LinearAllocator PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& ShaderStages) { m_ResourceLayoutIndex.fill(-1); - std::vector ShaderStages; ExtractShaders(CreateInfo, ShaderStages); // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddRequiredSize(GetNumShaderStages() * 2); - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddSpace(GetNumShaderStages() * 2); + MemPool.AddSpace(GetNumShaderStages()); + MemPool.AddSpace(GetNumShaderStages()); - ValidateAndReserveSpace(CreateInfo, MemPool); + ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); - m_RootSig.AllocateStaticSamplers(m_Desc.ResourceLayout); + m_RootSig.AllocateStaticSamplers(CreateInfo.PSODesc.ResourceLayout); m_pShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); m_pStaticVarManagers = MemPool.Allocate(GetNumShaderStages()); - InitGraphicsPipeline(CreateInfo, MemPool); - InitResourceLayouts(pDeviceD3D12, CreateInfo, ShaderStages); + InitializePipelineDesc(CreateInfo, MemPool); + InitResourceLayouts(CreateInfo, ShaderStages); + + return MemPool; +} + + +PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, + RenderDeviceD3D12Impl* pDeviceD3D12, + const GraphicsPipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + std::vector ShaderStages; + + auto MemPool = InitInternalObjects(CreateInfo, ShaderStages); + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) { const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); @@ -324,31 +335,11 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - m_ResourceLayoutIndex.fill(-1); - std::vector ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); - - // Memory must be released if an exception is thrown. - LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddRequiredSize(GetNumShaderStages() * 2); - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); - - ValidateAndReserveSpace(CreateInfo, MemPool); - - MemPool.Reserve(); + auto MemPool = InitInternalObjects(CreateInfo, ShaderStages); auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); - m_RootSig.AllocateStaticSamplers(m_Desc.ResourceLayout); - - m_pShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); - m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); - m_pStaticVarManagers = MemPool.Allocate(GetNumShaderStages()); - - InitComputePipeline(CreateInfo, MemPool); - InitResourceLayouts(pDeviceD3D12, CreateInfo, ShaderStages); D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; @@ -410,11 +401,10 @@ PipelineStateD3D12Impl::~PipelineStateD3D12Impl() IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase) -void PipelineStateD3D12Impl::InitResourceLayouts(RenderDeviceD3D12Impl* pDeviceD3D12, - const PipelineStateCreateInfo& CreateInfo, +void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, std::vector& ShaderStages) { - auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + auto pd3d12Device = GetDevice()->GetD3D12Device(); const auto& ResourceLayout = m_Desc.ResourceLayout; #ifdef DILIGENT_DEVELOPMENT @@ -443,7 +433,7 @@ void PipelineStateD3D12Impl::InitResourceLayouts(RenderDeviceD3D12Impl* ShaderResourceLayoutD3D12 // { *this, - pDeviceD3D12->GetD3D12Device(), + pd3d12Device, m_Desc.PipelineType, ResourceLayout, pShaderD3D12->GetShaderResources(), @@ -461,7 +451,7 @@ void PipelineStateD3D12Impl::InitResourceLayouts(RenderDeviceD3D12Impl* ShaderResourceLayoutD3D12 // { *this, - pDeviceD3D12->GetD3D12Device(), + pd3d12Device, m_Desc.PipelineType, ResourceLayout, pShaderD3D12->GetShaderResources(), diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index 97069bd2..ba91f7bc 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -534,26 +534,27 @@ void RenderDeviceD3D12Impl::TestTextureFormat(TEXTURE_FORMAT TexFormat) IMPLEMENT_QUERY_INTERFACE(RenderDeviceD3D12Impl, IID_RenderDeviceD3D12, TRenderDeviceBase) -void RenderDeviceD3D12Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +template +void RenderDeviceD3D12Impl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState) { CreateDeviceObject("Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, [&]() // { - PipelineStateD3D12Impl* pPipelineStateD3D12(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D12Impl instance", PipelineStateD3D12Impl)(this, PSOCreateInfo)); + PipelineStateD3D12Impl* pPipelineStateD3D12{NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D12Impl instance", PipelineStateD3D12Impl)(this, PSOCreateInfo)}; pPipelineStateD3D12->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); OnCreateDeviceObject(pPipelineStateD3D12); }); } + +void RenderDeviceD3D12Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreatePipelineState(PSOCreateInfo, ppPipelineState); +} + void RenderDeviceD3D12Impl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) { - CreateDeviceObject("Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, - [&]() // - { - PipelineStateD3D12Impl* pPipelineStateD3D12(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D12Impl instance", PipelineStateD3D12Impl)(this, PSOCreateInfo)); - pPipelineStateD3D12->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); - OnCreateDeviceObject(pPipelineStateD3D12); - }); + CreatePipelineState(PSOCreateInfo, ppPipelineState); } void RenderDeviceD3D12Impl::CreateBufferFromD3DResource(ID3D12Resource* pd3d12Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer) @@ -561,7 +562,7 @@ void RenderDeviceD3D12Impl::CreateBufferFromD3DResource(ID3D12Resource* pd3d12Bu CreateDeviceObject("buffer", BuffDesc, ppBuffer, [&]() // { - BufferD3D12Impl* pBufferD3D12(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d12Buffer)); + BufferD3D12Impl* pBufferD3D12{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d12Buffer)}; pBufferD3D12->QueryInterface(IID_Buffer, reinterpret_cast(ppBuffer)); pBufferD3D12->CreateDefaultViews(); OnCreateDeviceObject(pBufferD3D12); @@ -573,7 +574,7 @@ void RenderDeviceD3D12Impl::CreateBuffer(const BufferDesc& BuffDesc, const Buffe CreateDeviceObject("buffer", BuffDesc, ppBuffer, [&]() // { - BufferD3D12Impl* pBufferD3D12(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData)); + BufferD3D12Impl* pBufferD3D12{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData)}; pBufferD3D12->QueryInterface(IID_Buffer, reinterpret_cast(ppBuffer)); pBufferD3D12->CreateDefaultViews(); OnCreateDeviceObject(pBufferD3D12); @@ -586,7 +587,7 @@ void RenderDeviceD3D12Impl::CreateShader(const ShaderCreateInfo& ShaderCI, IShad CreateDeviceObject("shader", ShaderCI.Desc, ppShader, [&]() // { - ShaderD3D12Impl* pShaderD3D12(NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D12Impl instance", ShaderD3D12Impl)(this, ShaderCI)); + ShaderD3D12Impl* pShaderD3D12{NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D12Impl instance", ShaderD3D12Impl)(this, ShaderCI)}; pShaderD3D12->QueryInterface(IID_Shader, reinterpret_cast(ppShader)); OnCreateDeviceObject(pShaderD3D12); @@ -600,7 +601,7 @@ void RenderDeviceD3D12Impl::CreateTextureFromD3DResource(ID3D12Resource* pd3d12T CreateDeviceObject("texture", TexDesc, ppTexture, [&]() // { - TextureD3D12Impl* pTextureD3D12 = NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture); + TextureD3D12Impl* pTextureD3D12{NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture)}; pTextureD3D12->QueryInterface(IID_Texture, reinterpret_cast(ppTexture)); pTextureD3D12->CreateDefaultViews(); @@ -613,7 +614,7 @@ void RenderDeviceD3D12Impl::CreateTexture(const TextureDesc& TexDesc, ID3D12Reso CreateDeviceObject("texture", TexDesc, ppTexture, [&]() // { - TextureD3D12Impl* pTextureD3D12 = NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture); + TextureD3D12Impl* pTextureD3D12{NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture)}; pTextureD3D12->QueryInterface(IID_TextureD3D12, reinterpret_cast(ppTexture)); }); } @@ -623,7 +624,7 @@ void RenderDeviceD3D12Impl::CreateTexture(const TextureDesc& TexDesc, const Text CreateDeviceObject("texture", TexDesc, ppTexture, [&]() // { - TextureD3D12Impl* pTextureD3D12 = NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, pData); + TextureD3D12Impl* pTextureD3D12{NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, pData)}; pTextureD3D12->QueryInterface(IID_Texture, reinterpret_cast(ppTexture)); pTextureD3D12->CreateDefaultViews(); @@ -639,7 +640,7 @@ void RenderDeviceD3D12Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampl m_SamplersRegistry.Find(SamplerDesc, reinterpret_cast(ppSampler)); if (*ppSampler == nullptr) { - SamplerD3D12Impl* pSamplerD3D12(NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D12Impl instance", SamplerD3D12Impl)(this, SamplerDesc)); + SamplerD3D12Impl* pSamplerD3D12{NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D12Impl instance", SamplerD3D12Impl)(this, SamplerDesc)}; pSamplerD3D12->QueryInterface(IID_Sampler, reinterpret_cast(ppSampler)); OnCreateDeviceObject(pSamplerD3D12); m_SamplersRegistry.Add(SamplerDesc, *ppSampler); @@ -652,7 +653,7 @@ void RenderDeviceD3D12Impl::CreateFence(const FenceDesc& Desc, IFence** ppFence) CreateDeviceObject("Fence", Desc, ppFence, [&]() // { - FenceD3D12Impl* pFenceD3D12(NEW_RC_OBJ(m_FenceAllocator, "FenceD3D12Impl instance", FenceD3D12Impl)(this, Desc)); + FenceD3D12Impl* pFenceD3D12{NEW_RC_OBJ(m_FenceAllocator, "FenceD3D12Impl instance", FenceD3D12Impl)(this, Desc)}; pFenceD3D12->QueryInterface(IID_Fence, reinterpret_cast(ppFence)); OnCreateDeviceObject(pFenceD3D12); }); @@ -663,7 +664,7 @@ void RenderDeviceD3D12Impl::CreateQuery(const QueryDesc& Desc, IQuery** ppQuery) CreateDeviceObject("Query", Desc, ppQuery, [&]() // { - QueryD3D12Impl* pQueryD3D12(NEW_RC_OBJ(m_QueryAllocator, "QueryD3D12Impl instance", QueryD3D12Impl)(this, Desc)); + QueryD3D12Impl* pQueryD3D12{NEW_RC_OBJ(m_QueryAllocator, "QueryD3D12Impl instance", QueryD3D12Impl)(this, Desc)}; pQueryD3D12->QueryInterface(IID_Query, reinterpret_cast(ppQuery)); OnCreateDeviceObject(pQueryD3D12); }); @@ -674,7 +675,7 @@ void RenderDeviceD3D12Impl::CreateRenderPass(const RenderPassDesc& Desc, IRender CreateDeviceObject("RenderPass", Desc, ppRenderPass, [&]() // { - RenderPassD3D12Impl* pRenderPassD3D12(NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D12Impl instance", RenderPassD3D12Impl)(this, Desc)); + RenderPassD3D12Impl* pRenderPassD3D12{NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D12Impl instance", RenderPassD3D12Impl)(this, Desc)}; pRenderPassD3D12->QueryInterface(IID_RenderPass, reinterpret_cast(ppRenderPass)); OnCreateDeviceObject(pRenderPassD3D12); }); @@ -685,7 +686,7 @@ void RenderDeviceD3D12Impl::CreateFramebuffer(const FramebufferDesc& Desc, IFram CreateDeviceObject("Framebuffer", Desc, ppFramebuffer, [&]() // { - FramebufferD3D12Impl* pFramebufferD3D12(NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D12Impl instance", FramebufferD3D12Impl)(this, Desc)); + FramebufferD3D12Impl* pFramebufferD3D12{NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D12Impl instance", FramebufferD3D12Impl)(this, Desc)}; pFramebufferD3D12->QueryInterface(IID_Framebuffer, reinterpret_cast(ppFramebuffer)); OnCreateDeviceObject(pFramebufferD3D12); }); diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp index 55c53c25..83f8bdad 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp @@ -107,8 +107,11 @@ private: pShader{_pShader} {} }; - void InitResourceLayouts(RenderDeviceGLImpl* pDeviceVk, - const std::vector& ShaderStages, + + template + void Initialize(const PSOCreateInfoType& CreateInfo, const std::vector& ShaderStages); + + void InitResourceLayouts(const std::vector& ShaderStages, LinearAllocator& MemPool); // Linked GL programs for every shader stage. Every pipeline needs to have its own programs diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp index 5c8037c3..6b76feb9 100644 --- a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp @@ -175,6 +175,9 @@ protected: std::unique_ptr m_pTexRegionRender; private: + template + void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal); + virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; bool CheckExtension(const Char* ExtensionString); void FlagSupportedTexFormats(); diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 4ac36396..7b7d4e21 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -36,6 +36,28 @@ namespace Diligent { + +template +void PipelineStateGLImpl::Initialize(const PSOCreateInfoType& CreateInfo, const std::vector& ShaderStages) +{ + // Memory must be released if an exception is thrown. + LinearAllocator MemPool{GetRawAllocator()}; + + MemPool.AddSpace(GetNumShaderStages()); + MemPool.AddSpace(GetNumShaderStages()); + MemPool.AddSpace(m_Desc.ResourceLayout.NumStaticSamplers); + + ReserveSpaceForPipelineDesc(CreateInfo, MemPool); + + MemPool.Reserve(); + + InitResourceLayouts(ShaderStages, MemPool); + InitializePipelineDesc(CreateInfo, MemPool); + + void* Ptr = MemPool.Release(); + VERIFY_EXPR(Ptr == m_GLPrograms); +} + PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, RenderDeviceGLImpl* pDeviceGL, const GraphicsPipelineStateCreateInfo& CreateInfo, @@ -71,22 +93,7 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_PIXEL; } - // Memory must be released if an exception is thrown. - LinearAllocator MemPool{GetRawAllocator()}; - - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(m_Desc.ResourceLayout.NumStaticSamplers); - - ValidateAndReserveSpace(CreateInfo, MemPool); - - MemPool.Reserve(); - - InitResourceLayouts(pDeviceGL, ShaderStages, MemPool); - InitGraphicsPipeline(CreateInfo, MemPool); - - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_GLPrograms); + Initialize(CreateInfo, ShaderStages); } PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, @@ -108,22 +115,7 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* p std::vector ShaderStages; ExtractShaders(CreateInfo, ShaderStages); - // Memory must be released if an exception is thrown. - LinearAllocator MemPool{GetRawAllocator()}; - - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(m_Desc.ResourceLayout.NumStaticSamplers); - - ValidateAndReserveSpace(CreateInfo, MemPool); - - MemPool.Reserve(); - - InitResourceLayouts(pDeviceGL, ShaderStages, MemPool); - InitComputePipeline(CreateInfo, MemPool); - - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_GLPrograms); + Initialize(CreateInfo, ShaderStages); } PipelineStateGLImpl::~PipelineStateGLImpl() @@ -149,11 +141,11 @@ PipelineStateGLImpl::~PipelineStateGLImpl() IMPLEMENT_QUERY_INTERFACE(PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase) -void PipelineStateGLImpl::InitResourceLayouts(RenderDeviceGLImpl* pDeviceGL, - const std::vector& ShaderStages, +void PipelineStateGLImpl::InitResourceLayouts(const std::vector& ShaderStages, LinearAllocator& MemPool) { - auto& DeviceCaps = pDeviceGL->GetDeviceCaps(); + auto* const pDeviceGL = GetDevice(); + const auto& DeviceCaps = pDeviceGL->GetDeviceCaps(); VERIFY(DeviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized"); auto pImmediateCtx = m_pDevice->GetImmediateContext(); diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index 59b4bdfd..7911fa47 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -696,7 +696,8 @@ void RenderDeviceGLImpl::CreateSampler(const SamplerDesc& SamplerDesc, ISampler* CreateSampler(SamplerDesc, ppSampler, false); } -void RenderDeviceGLImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal) +template +void RenderDeviceGLImpl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal) { CreateDeviceObject( "Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState, @@ -709,17 +710,14 @@ void RenderDeviceGLImpl::CreateGraphicsPipelineState(const GraphicsPipelineState ); } +void RenderDeviceGLImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal) +{ + CreatePipelineState(PSOCreateInfo, ppPipelineState, bIsDeviceInternal); +} + void RenderDeviceGLImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal) { - CreateDeviceObject( - "Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState, - [&]() // - { - PipelineStateGLImpl* pPipelineStateOGL(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateGLImpl instance", PipelineStateGLImpl)(this, PSOCreateInfo, bIsDeviceInternal)); - pPipelineStateOGL->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); - OnCreateDeviceObject(pPipelineStateOGL); - } // - ); + CreatePipelineState(PSOCreateInfo, ppPipelineState, bIsDeviceInternal); } void RenderDeviceGLImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) diff --git a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp index 1a9c99c0..5861005e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp @@ -151,13 +151,15 @@ TexRegionRender::TexRegionRender(class RenderDeviceGLImpl* pDeviceGL) pDeviceGL->CreateShader(ShaderAttrs, &FragmetShader, IsInternalDeviceObject); PSOCreateInfo.pPS = FragmetShader; - PSOCreateInfo.PSODesc.ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; + auto& ResourceLayout = PSOCreateInfo.PSODesc.ResourceLayout; + + ResourceLayout.DefaultVariableType = SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC; ShaderResourceVariableDesc Vars[] = { {SHADER_TYPE_PIXEL, "cbConstants", SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE} // }; - PSOCreateInfo.PSODesc.ResourceLayout.NumVariables = _countof(Vars); - PSOCreateInfo.PSODesc.ResourceLayout.Variables = Vars; + ResourceLayout.NumVariables = _countof(Vars); + ResourceLayout.Variables = Vars; pDeviceGL->CreateGraphicsPipelineState(PSOCreateInfo, &m_pPSO[Dim * 3 + Fmt], IsInternalDeviceObject); } diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index 1773e743..96b34008 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -127,8 +127,13 @@ public: private: using TShaderStages = ShaderResourceLayoutVk::TShaderStages; - void InitResourceLayouts(RenderDeviceVkImpl* pDeviceVk, - const PipelineStateCreateInfo& CreateInfo, + + template + LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& vkShaderStages, + std::vector& ShaderModules); + + void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages); const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp index 24f3345c..469e8119 100644 --- a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp @@ -183,6 +183,9 @@ public: IDXCompiler* GetDxCompiler() const { return m_pDxCompiler.get(); } private: + template + void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState); + virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final; // Submits command buffer for execution to the command queue diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 3e4154be..dfa270cc 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -401,10 +401,10 @@ static void CreateGraphicsPipeline(RenderDeviceVkImpl* Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name); } -void PipelineStateVkImpl::InitResourceLayouts(RenderDeviceVkImpl* pDeviceVk, - const PipelineStateCreateInfo& CreateInfo, +void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages) { + auto* const pDeviceVk = GetDevice(); const auto& LogicalDevice = pDeviceVk->GetLogicalDevice(); for (size_t s = 0; s < ShaderStages.size(); ++s) @@ -463,26 +463,24 @@ void PipelineStateVkImpl::InitResourceLayouts(RenderDeviceVkImpl* pDe m_ShaderResourceLayoutHash = m_PipelineLayout.GetHash(); } - -PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, - RenderDeviceVkImpl* pDeviceVk, - const GraphicsPipelineStateCreateInfo& CreateInfo) : - TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, - m_SRBMemAllocator{GetRawAllocator()} +template +LinearAllocator PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& vkShaderStages, + std::vector& ShaderModules) { m_ResourceLayoutIndex.fill(-1); - ShaderResourceLayoutVk::TShaderStages ShaderStages; + TShaderStages ShaderStages; ExtractShaders(CreateInfo, ShaderStages); // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddRequiredSize(GetNumShaderStages() * 2); - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); + MemPool.AddSpace(GetNumShaderStages() * 2); + MemPool.AddSpace(GetNumShaderStages()); + MemPool.AddSpace(GetNumShaderStages()); - ValidateAndReserveSpace(CreateInfo, MemPool); + ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); @@ -490,15 +488,27 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* m_StaticResCaches = MemPool.Allocate(GetNumShaderStages()); m_StaticVarsMgrs = MemPool.Allocate(GetNumShaderStages()); - InitGraphicsPipeline(CreateInfo, MemPool); - InitResourceLayouts(pDeviceVk, CreateInfo, ShaderStages); + InitializePipelineDesc(CreateInfo, MemPool); + InitResourceLayouts(CreateInfo, ShaderStages); // Create shader modules and initialize shader stages - std::vector VkShaderStages; + InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); + + return MemPool; +} + +PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, + RenderDeviceVkImpl* pDeviceVk, + const GraphicsPipelineStateCreateInfo& CreateInfo) : + TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, + m_SRBMemAllocator{GetRawAllocator()} +{ + std::vector vkShaderStages; std::vector ShaderModules; - InitPipelineShaderStages(pDeviceVk->GetLogicalDevice(), ShaderStages, ShaderModules, VkShaderStages); - CreateGraphicsPipeline(pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); + auto MemPool = InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + + CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); void* Ptr = MemPool.Release(); VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); @@ -511,35 +521,12 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - m_ResourceLayoutIndex.fill(-1); - - ShaderResourceLayoutVk::TShaderStages ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); - - // Memory must be released if an exception is thrown. - LinearAllocator MemPool{GetRawAllocator()}; - - MemPool.AddRequiredSize(GetNumShaderStages() * 2); - MemPool.AddRequiredSize(GetNumShaderStages()); - MemPool.AddRequiredSize(GetNumShaderStages()); - - ValidateAndReserveSpace(CreateInfo, MemPool); - - MemPool.Reserve(); - - m_ShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); - m_StaticResCaches = MemPool.Allocate(GetNumShaderStages()); - m_StaticVarsMgrs = MemPool.Allocate(GetNumShaderStages()); - - InitComputePipeline(CreateInfo, MemPool); - InitResourceLayouts(pDeviceVk, CreateInfo, ShaderStages); - - // Create shader modules and initialize shader stages - std::vector VkShaderStages; + std::vector vkShaderStages; std::vector ShaderModules; - InitPipelineShaderStages(pDeviceVk->GetLogicalDevice(), ShaderStages, ShaderModules, VkShaderStages); - CreateComputePipeline(pDeviceVk, VkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); + auto MemPool = InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + + CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); void* Ptr = MemPool.Release(); VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index ca729479..1441569e 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -541,7 +541,8 @@ void RenderDeviceVkImpl::TestTextureFormat(TEXTURE_FORMAT TexFormat) IMPLEMENT_QUERY_INTERFACE(RenderDeviceVkImpl, IID_RenderDeviceVk, TRenderDeviceBase) -void RenderDeviceVkImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +template +void RenderDeviceVkImpl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState) { CreateDeviceObject( "Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, @@ -554,18 +555,15 @@ void RenderDeviceVkImpl::CreateGraphicsPipelineState(const GraphicsPipelineState ); } +void RenderDeviceVkImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) +{ + CreatePipelineState(PSOCreateInfo, ppPipelineState); +} + void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState) { - CreateDeviceObject( - "Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState, - [&]() // - { - PipelineStateVkImpl* pPipelineStateVk(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateVkImpl instance", PipelineStateVkImpl)(this, PSOCreateInfo)); - pPipelineStateVk->QueryInterface(IID_PipelineState, reinterpret_cast(ppPipelineState)); - OnCreateDeviceObject(pPipelineStateVk); - } // - ); + CreatePipelineState(PSOCreateInfo, ppPipelineState); } -- cgit v1.2.3 From ff88c0507d8e8d4571b00adb421557bca1f4ed48 Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 18 Oct 2020 17:25:39 -0700 Subject: Updated third-party modules; fixed compiler warnings --- Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp | 4 ++-- Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp index 914a09bb..04a08af1 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp @@ -311,7 +311,7 @@ void GLPipelineResourceLayout::SamplerBindInfo::BindResource(IDeviceObject* pVie { const auto& ViewDesc = pViewGL->GetDesc(); const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc(); - if (!(BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED || BuffDesc.Mode == BUFFER_MODE_RAW)) + if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW)) { LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", m_Attribs.Name, ": formatted buffer view is expected."); @@ -361,7 +361,7 @@ void GLPipelineResourceLayout::ImageBindInfo::BindResource(IDeviceObject* pView, { const auto& ViewDesc = pViewGL->GetDesc(); const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc(); - if (!(BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED || BuffDesc.Mode == BUFFER_MODE_RAW)) + if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW)) { LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", m_Attribs.Name, ": formatted buffer view is expected."); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 7f726e69..33e0aa82 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -762,7 +762,7 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject* { const auto& ViewDesc = pBufferViewVk->GetDesc(); const auto& BuffDesc = pBufferViewVk->GetBuffer()->GetDesc(); - if (!(BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED || BuffDesc.Mode == BUFFER_MODE_RAW)) + if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW)) { LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '", SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected."); -- cgit v1.2.3 From a520bf4f9748d20e432bcf7994be3148d0b75d54 Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 19 Oct 2020 10:21:30 -0700 Subject: Renamed static sampler to immutable sampler (API240076) --- .../GraphicsEngine/include/PipelineStateBase.hpp | 26 ++++---- .../include/ShaderResourceVariableBase.hpp | 14 ++--- Graphics/GraphicsEngine/interface/APIInfo.h | 4 +- Graphics/GraphicsEngine/interface/PipelineState.h | 46 +++++++------- Graphics/GraphicsEngine/src/APIInfo.cpp | 2 +- .../include/PipelineStateD3D11Impl.hpp | 12 ++-- .../src/PipelineStateD3D11Impl.cpp | 47 +++++++------- .../src/ShaderResourceBindingD3D11Impl.cpp | 2 +- .../src/ShaderResourceLayoutD3D11.cpp | 42 ++++++------- .../GraphicsEngineD3D12/include/RootSignature.hpp | 22 +++---- .../src/D3D12TypeConversions.cpp | 2 +- .../src/PipelineStateD3D12Impl.cpp | 4 +- Graphics/GraphicsEngineD3D12/src/RootSignature.cpp | 73 +++++++++++----------- .../src/ShaderResourceLayoutD3D12.cpp | 37 ++++++----- .../include/ShaderResources.hpp | 10 +-- .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 62 +++++++++--------- .../include/GLPipelineResourceLayout.hpp | 12 ++-- .../include/GLProgramResourceCache.hpp | 4 +- .../include/PipelineStateGLImpl.hpp | 6 +- .../src/GLPipelineResourceLayout.cpp | 18 +++--- .../src/PipelineStateGLImpl.cpp | 24 +++---- .../include/ShaderResourceLayoutVk.hpp | 4 +- .../src/GenerateMipsVkHelper.cpp | 6 +- .../GraphicsEngineVulkan/src/PipelineLayout.cpp | 2 +- .../src/PipelineStateVkImpl.cpp | 2 +- .../src/ShaderResourceLayoutVk.cpp | 44 ++++++------- 26 files changed, 268 insertions(+), 259 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index cda2247e..c108f663 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -460,13 +460,13 @@ private: } } - if (SrcLayout.StaticSamplers != nullptr) + if (SrcLayout.ImmutableSamplers != nullptr) { - MemPool.AddSpace(SrcLayout.NumStaticSamplers); - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + MemPool.AddSpace(SrcLayout.NumImmutableSamplers); + for (Uint32 i = 0; i < SrcLayout.NumImmutableSamplers; ++i) { - VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null"); - MemPool.AddSpaceForString(SrcLayout.StaticSamplers[i].SamplerOrTextureName); + VERIFY(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName != nullptr, "Immutable sampler or texture name can't be null"); + MemPool.AddSpaceForString(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName); } } } @@ -485,13 +485,13 @@ private: } } - if (SrcLayout.StaticSamplers != nullptr) + if (SrcLayout.ImmutableSamplers != nullptr) { - auto* StaticSamplers = MemPool.Allocate(SrcLayout.NumStaticSamplers); - DstLayout.StaticSamplers = StaticSamplers; - for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i) + auto* ImmutableSamplers = MemPool.Allocate(SrcLayout.NumImmutableSamplers); + DstLayout.ImmutableSamplers = ImmutableSamplers; + for (Uint32 i = 0; i < SrcLayout.NumImmutableSamplers; ++i) { - const auto& SrcSmplr = SrcLayout.StaticSamplers[i]; + const auto& SrcSmplr = SrcLayout.ImmutableSamplers[i]; #ifdef DILIGENT_DEVELOPMENT { const auto& BorderColor = SrcSmplr.Desc.BorderColor; @@ -499,15 +499,15 @@ private: (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) || (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1))) { - LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcSmplr.SamplerOrTextureName, "\" specifies border color (", + LOG_WARNING_MESSAGE("Immutable sampler for variable \"", SrcSmplr.SamplerOrTextureName, "\" specifies border color (", BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3], "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors"); } } #endif - StaticSamplers[i] = SrcSmplr; - StaticSamplers[i].SamplerOrTextureName = MemPool.CopyString(SrcSmplr.SamplerOrTextureName); + ImmutableSamplers[i] = SrcSmplr; + ImmutableSamplers[i].SamplerOrTextureName = MemPool.CopyString(SrcSmplr.SamplerOrTextureName); } } } diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp index 78c1832d..1130fbff 100644 --- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp +++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp @@ -115,15 +115,15 @@ inline Uint32 GetAllowedTypeBits(const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVar return AllowedTypeBits; } -inline Int32 FindStaticSampler(const StaticSamplerDesc* StaticSamplers, - Uint32 NumStaticSamplers, - SHADER_TYPE ShaderType, - const char* ResourceName, - const char* SamplerSuffix) +inline Int32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers, + Uint32 NumImtblSamplers, + SHADER_TYPE ShaderType, + const char* ResourceName, + const char* SamplerSuffix) { - for (Uint32 s = 0; s < NumStaticSamplers; ++s) + for (Uint32 s = 0; s < NumImtblSamplers; ++s) { - const auto& StSam = StaticSamplers[s]; + const auto& StSam = ImtblSamplers[s]; if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(ResourceName, StSam.SamplerOrTextureName, SamplerSuffix)) return s; } diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 10cf096e..a32511d2 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240075 +#define DILIGENT_API_VERSION 240076 #include "../../../Primitives/interface/BasicTypes.h" @@ -77,7 +77,7 @@ struct APIInfo size_t InputLayoutDescSize DEFAULT_INITIALIZER(0); size_t SampleDescSize DEFAULT_INITIALIZER(0); size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0); - size_t StaticSamplerDescSize DEFAULT_INITIALIZER(0); + size_t ImmutableSamplerDescSize DEFAULT_INITIALIZER(0); size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0); size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0); size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0); diff --git a/Graphics/GraphicsEngine/interface/PipelineState.h b/Graphics/GraphicsEngine/interface/PipelineState.h index cef07c66..2d889c61 100644 --- a/Graphics/GraphicsEngine/interface/PipelineState.h +++ b/Graphics/GraphicsEngine/interface/PipelineState.h @@ -96,32 +96,36 @@ struct ShaderResourceVariableDesc typedef struct ShaderResourceVariableDesc ShaderResourceVariableDesc; -/// Static sampler description -struct StaticSamplerDesc +/// Immutable sampler description. + +/// An immutable sampler is compiled into the pipeline state and can't be changed. +/// It is generally more efficient than a regular sampler and should be used +/// whenever possible. +struct ImmutableSamplerDesc { - /// Shader stages that this static sampler applies to. More than one shader stage can be specified. + /// Shader stages that this immutable sampler applies to. More than one shader stage can be specified. SHADER_TYPE ShaderStages DEFAULT_INITIALIZER(SHADER_TYPE_UNKNOWN); /// The name of the sampler itself or the name of the texture variable that - /// this static sampler is assigned to if combined texture samplers are used. + /// this immutable sampler is assigned to if combined texture samplers are used. const Char* SamplerOrTextureName DEFAULT_INITIALIZER(nullptr); /// Sampler description struct SamplerDesc Desc; #if DILIGENT_CPP_INTERFACE - StaticSamplerDesc()noexcept{} + ImmutableSamplerDesc()noexcept{} - StaticSamplerDesc(SHADER_TYPE _ShaderStages, - const Char* _SamplerOrTextureName, - const SamplerDesc& _Desc)noexcept : + ImmutableSamplerDesc(SHADER_TYPE _ShaderStages, + const Char* _SamplerOrTextureName, + const SamplerDesc& _Desc)noexcept : ShaderStages {_ShaderStages }, SamplerOrTextureName{_SamplerOrTextureName}, Desc {_Desc } {} #endif }; -typedef struct StaticSamplerDesc StaticSamplerDesc; +typedef struct ImmutableSamplerDesc ImmutableSamplerDesc; /// Pipeline layout description struct PipelineResourceLayoutDesc @@ -129,19 +133,19 @@ struct PipelineResourceLayoutDesc /// Default shader resource variable type. This type will be used if shader /// variable description is not found in the Variables array /// or if Variables == nullptr - SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType DEFAULT_INITIALIZER(SHADER_RESOURCE_VARIABLE_TYPE_STATIC); + SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType DEFAULT_INITIALIZER(SHADER_RESOURCE_VARIABLE_TYPE_STATIC); /// Number of elements in Variables array - Uint32 NumVariables DEFAULT_INITIALIZER(0); + Uint32 NumVariables DEFAULT_INITIALIZER(0); /// Array of shader resource variable descriptions - const ShaderResourceVariableDesc* Variables DEFAULT_INITIALIZER(nullptr); + const ShaderResourceVariableDesc* Variables DEFAULT_INITIALIZER(nullptr); - /// Number of static samplers in StaticSamplers array - Uint32 NumStaticSamplers DEFAULT_INITIALIZER(0); + /// Number of immutable samplers in ImmutableSamplers array + Uint32 NumImmutableSamplers DEFAULT_INITIALIZER(0); - /// Array of static sampler descriptions - const StaticSamplerDesc* StaticSamplers DEFAULT_INITIALIZER(nullptr); + /// Array of immutable sampler descriptions + const ImmutableSamplerDesc* ImmutableSamplers DEFAULT_INITIALIZER(nullptr); }; typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc; @@ -256,7 +260,7 @@ typedef struct PipelineStateDesc PipelineStateDesc; DILIGENT_TYPED_ENUM(PSO_CREATE_FLAGS, Uint32) { /// Null flag. - PSO_CREATE_FLAG_NONE = 0x00, + PSO_CREATE_FLAG_NONE = 0x00, /// Ignore missing variables. @@ -264,15 +268,15 @@ DILIGENT_TYPED_ENUM(PSO_CREATE_FLAGS, Uint32) /// provided as part of the pipeline resource layout description /// that is not found in any of the designated shader stages. /// Use this flag to silence these warnings. - PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES = 0x01, + PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES = 0x01, - /// Ignore missing static samplers. + /// Ignore missing immutable samplers. - /// By default, the engine outputs a warning for every static sampler + /// By default, the engine outputs a warning for every immutable sampler /// provided as part of the pipeline resource layout description /// that is not found in any of the designated shader stages. /// Use this flag to silence these warnings. - PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS = 0x02, + PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS = 0x02, }; DEFINE_FLAG_ENUM_OPERATORS(PSO_CREATE_FLAGS); diff --git a/Graphics/GraphicsEngine/src/APIInfo.cpp b/Graphics/GraphicsEngine/src/APIInfo.cpp index aa2fb3d9..e4111327 100644 --- a/Graphics/GraphicsEngine/src/APIInfo.cpp +++ b/Graphics/GraphicsEngine/src/APIInfo.cpp @@ -87,7 +87,7 @@ static APIInfo InitAPIInfo() INIT_STRUCTURE_SIZE(InputLayoutDesc); INIT_STRUCTURE_SIZE(SampleDesc); INIT_STRUCTURE_SIZE(ShaderResourceVariableDesc); - INIT_STRUCTURE_SIZE(StaticSamplerDesc); + INIT_STRUCTURE_SIZE(ImmutableSamplerDesc); INIT_STRUCTURE_SIZE(PipelineResourceLayoutDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineDesc); INIT_STRUCTURE_SIZE(GraphicsPipelineStateCreateInfo); diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index eb184710..0fa62606 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -134,7 +134,7 @@ public: const ShaderD3D11Impl* GetShaderByType(SHADER_TYPE ShaderType) const; const ShaderD3D11Impl* GetShader(Uint32 Index) const; - void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; + void SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const; private: template @@ -166,20 +166,20 @@ private: // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex) std::array m_ResourceLayoutIndex = {-1, -1, -1, -1, -1}; - std::array m_StaticSamplerOffsets = {}; - struct StaticSamplerInfo + std::array m_ImmutableSamplerOffsets = {}; + struct ImmutableSamplerInfo { const D3DShaderResourceAttribs& Attribs; RefCntAutoPtr pSampler; - StaticSamplerInfo(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_StaticSamplers; + std::vector> m_ImmutableSamplers; }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 292a9323..722318f2 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -74,7 +74,7 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* CreateInfo }, m_SRBMemAllocator{GetRawAllocator()}, - m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")) + m_ImmutableSamplers (STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) // clang-format on { auto MemPool = InitInternalObjects(CreateInfo); @@ -153,7 +153,7 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* CreateInfo }, m_SRBMemAllocator{GetRawAllocator()}, - m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")) + m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) // clang-format on { auto MemPool = InitInternalObjects(CreateInfo); @@ -209,11 +209,11 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& } ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(), (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, - (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); + (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0); } #endif - decltype(m_StaticSamplers) StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector")); + decltype(m_ImmutableSamplers) ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")); std::array ShaderResLayoutDataSizes = {}; std::array ShaderResCacheDataSizes = {}; for (Uint32 s = 0; s < ShaderStages.size(); ++s) @@ -243,21 +243,22 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& }; // clang-format on - // Initialize static samplers + // Initialize immutable samplers for (Uint32 sam = 0; sam < ShaderResources.GetNumSamplers(); ++sam) { - const auto& SamplerAttribs = ShaderResources.GetSampler(sam); - constexpr bool LogStaticSamplerArrayError = true; - auto SrcStaticSamplerInd = ShaderResources.FindStaticSampler(SamplerAttribs, ResourceLayout, LogStaticSamplerArrayError); - if (SrcStaticSamplerInd >= 0) + const auto& SamplerAttribs = ShaderResources.GetSampler(sam); + constexpr bool LogImtblSamplerArrayError = true; + auto SrcImtblSamplerInd = ShaderResources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); + if (SrcImtblSamplerInd >= 0) { - const auto& SrcStaticSamplerInfo = ResourceLayout.StaticSamplers[SrcStaticSamplerInd]; - RefCntAutoPtr pStaticSampler; - GetDevice()->CreateSampler(SrcStaticSamplerInfo.Desc, &pStaticSampler); - StaticSamplers.emplace_back(SamplerAttribs, std::move(pStaticSampler)); + const auto& SrcImtblSamplerInfo = ResourceLayout.ImmutableSamplers[SrcImtblSamplerInd]; + + RefCntAutoPtr pImbtlSampler; + GetDevice()->CreateSampler(SrcImtblSamplerInfo.Desc, &pImbtlSampler); + ImmutableSamplers.emplace_back(SamplerAttribs, std::move(pImbtlSampler)); } } - m_StaticSamplerOffsets[s + 1] = static_cast(StaticSamplers.size()); + m_ImmutableSamplerOffsets[s + 1] = static_cast(ImmutableSamplers.size()); if (m_Desc.SRBAllocationGranularity > 1) { @@ -279,14 +280,14 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderResLayoutDataSizes.data(), GetNumShaderStages(), ShaderResCacheDataSizes.data()); } - m_StaticSamplers.reserve(StaticSamplers.size()); - for (auto& Sam : StaticSamplers) - m_StaticSamplers.emplace_back(std::move(Sam)); + m_ImmutableSamplers.reserve(ImmutableSamplers.size()); + for (auto& ImtblSam : ImmutableSamplers) + m_ImmutableSamplers.emplace_back(std::move(ImtblSam)); for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { - // Initialize static samplers in the static resource cache to avoid warning messages - SetStaticSamplers(m_pStaticResourceCaches[s], s); + // Initialize immutable samplers in the static resource cache to avoid warning messages + SetImmutableSamplers(m_pStaticResourceCaches[s], s); } } @@ -431,15 +432,15 @@ IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByIndex(SHADER return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Index); } -void PipelineStateD3D11Impl::SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const +void PipelineStateD3D11Impl::SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const { auto NumCachedSamplers = ResourceCache.GetSamplerCount(); - for (Uint32 s = m_StaticSamplerOffsets[ShaderInd]; s < m_StaticSamplerOffsets[ShaderInd + 1]; ++s) + for (Uint32 s = m_ImmutableSamplerOffsets[ShaderInd]; s < m_ImmutableSamplerOffsets[ShaderInd + 1]; ++s) { - auto& SamplerInfo = m_StaticSamplers[s]; + auto& SamplerInfo = m_ImmutableSamplers[s]; const auto& SamAttribs = SamplerInfo.Attribs; auto* pSamplerD3D11Impl = SamplerInfo.pSampler.RawPtr(); - // Limiting EndBindPoint is required when initializing static samplers in a Shader's static cache + // 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); diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 88c7b77f..5e95db97 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -177,7 +177,7 @@ void ShaderResourceBindingD3D11Impl::InitializeStaticResources(const IPipelineSt } #endif StaticResLayout.CopyResources(m_pBoundResourceCaches[shader]); - pPSOD3D11->SetStaticSamplers(m_pBoundResourceCaches[shader], shader); + pPSOD3D11->SetImmutableSamplers(m_pBoundResourceCaches[shader], shader); } m_bIsStaticResourcesBound = true; diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index 723e190a..c1e6e65a 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -86,9 +86,9 @@ size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes) { - // Skip static samplers as they are initialized directly in the resource cache by the PSO - constexpr bool CountStaticSamplers = false; - auto ResCounters = SrcResources.CountResources(ResourceLayout, AllowedVarTypes, NumAllowedTypes, CountStaticSamplers); + // 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) + @@ -120,9 +120,9 @@ ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& const auto AllowedTypeBits = GetAllowedTypeBits(VarTypes, NumVarTypes); // Count total number of resources of allowed types - // Skip static samplers as they are initialized directly in the resource cache by the PSO - constexpr bool CountStaticSamplers = false; - auto ResCounters = m_pResources->CountResources(ResourceLayout, VarTypes, NumVarTypes, CountStaticSamplers); + // 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; @@ -192,12 +192,12 @@ ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& auto VarType = m_pResources->FindVariableType(Sampler, ResourceLayout); if (IsAllowedType(VarType, AllowedTypeBits)) { - // Constructor of PipelineStateD3D11Impl initializes static samplers and will log the error, if any - constexpr bool LogStaticSamplerArrayError = false; - auto StaticSamplerInd = m_pResources->FindStaticSampler(Sampler, ResourceLayout, LogStaticSamplerArrayError); - if (StaticSamplerInd >= 0) + // 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 static samplers as they are initialized directly in the resource cache by the PSO + // Skip immutble samplers as they are initialized directly in the resource cache by the PSO return; } // Initialize current sampler in place, increment sampler counter @@ -241,10 +241,10 @@ ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& AssignedSamplerIndex = TexSRVBindInfo::InvalidSamplerIndex; #ifdef DILIGENT_DEBUG // Shader error will be logged by the PipelineStateD3D11Impl - constexpr bool LogStaticSamplerArrayError = false; - if (m_pResources->FindStaticSampler(AssignedSamplerAttribs, ResourceLayout, LogStaticSamplerArrayError) < 0) + constexpr bool LogImtblSamplerArrayError = false; + if (m_pResources->FindImmutableSampler(AssignedSamplerAttribs, ResourceLayout, LogImtblSamplerArrayError) < 0) { - UNEXPECTED("Unable to find non-static sampler assigned to texture SRV '", TexSRV.Name, "'."); + UNEXPECTED("Unable to find non-immutable sampler assigned to texture SRV '", TexSRV.Name, "'."); } #endif } @@ -252,10 +252,10 @@ ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& { #ifdef DILIGENT_DEBUG // Shader error will be logged by the PipelineStateD3D11Impl - constexpr bool LogStaticSamplerArrayError = false; - if (m_pResources->FindStaticSampler(AssignedSamplerAttribs, ResourceLayout, LogStaticSamplerArrayError) >= 0) + constexpr bool LogImtblSamplerArrayError = false; + if (m_pResources->FindImmutableSampler(AssignedSamplerAttribs, ResourceLayout, LogImtblSamplerArrayError) >= 0) { - UNEXPECTED("Static sampler '", AssignedSamplerAttribs.Name, "' is assigned to texture SRV '", TexSRV.Name, "'."); + UNEXPECTED("Immutable sampler '", AssignedSamplerAttribs.Name, "' is assigned to texture SRV '", TexSRV.Name, "'."); } #endif } @@ -412,7 +412,7 @@ void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache [&](const SamplerBindInfo& sam) // { - //VERIFY(!sam.IsStaticSampler, "Variables are not created for static samplers"); + //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()); @@ -460,7 +460,7 @@ void ShaderResourceLayoutD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pVie if (ValidSamplerAssigned()) { auto& Sampler = m_ParentResLayout.GetResource(SamplerIndex); - //VERIFY(!Sampler.IsStaticSampler, "Static samplers are not assigned to texture SRVs as they are initialized directly in the shader resource cache"); + //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); @@ -502,7 +502,7 @@ void ShaderResourceLayoutD3D11::SamplerBindInfo::BindResource(IDeviceObject* pSa "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(!IsStaticSampler, "Cannot bind sampler to a static sampler"); + //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 @@ -737,7 +737,7 @@ IShaderResourceVariable* ShaderResourceLayoutD3D11::GetShaderVariable(const Char if (!m_pResources->IsUsingCombinedTextureSamplers()) { - // Static samplers are never created in the resource layout + // Immutable samplers are never created in the resource layout if (auto* pSampler = GetResourceByName(Name)) return pSampler; } diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp index 2bf6d0b3..232bce65 100644 --- a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp +++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp @@ -302,7 +302,7 @@ class RootSignature public: RootSignature(); - void AllocateStaticSamplers(const PipelineResourceLayoutDesc& ResourceLayout); + void AllocateImmutableSamplers(const PipelineResourceLayoutDesc& ResourceLayout); void Finalize(ID3D12Device* pd3d12Device); @@ -312,10 +312,10 @@ public: void InitResourceCache(class RenderDeviceD3D12Impl* pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator& CacheMemAllocator) const; - void InitStaticSampler(SHADER_TYPE ShaderType, - const char* SamplerName, - const char* SamplerSuffix, - const D3DShaderResourceAttribs& ShaderResAttribs); + void InitImmutableSampler(SHADER_TYPE ShaderType, + const char* SamplerName, + const char* SamplerSuffix, + const D3DShaderResourceAttribs& ShaderResAttribs); void AllocateResourceSlot(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineType, @@ -481,22 +481,22 @@ private: RootParamsManager m_RootParams; - struct StaticSamplerAttribs + struct ImmutableSamplerAttribs { - StaticSamplerDesc SamplerDesc; + ImmutableSamplerDesc SamplerDesc; UINT ShaderRegister = static_cast(-1); UINT ArraySize = 0; UINT RegisterSpace = 0; D3D12_SHADER_VISIBILITY ShaderVisibility = static_cast(-1); - StaticSamplerAttribs() noexcept {} - StaticSamplerAttribs(const StaticSamplerDesc& SamDesc, D3D12_SHADER_VISIBILITY Visibility) noexcept : + ImmutableSamplerAttribs() noexcept {} + ImmutableSamplerAttribs(const ImmutableSamplerDesc& SamDesc, D3D12_SHADER_VISIBILITY Visibility) noexcept : SamplerDesc(SamDesc), ShaderVisibility(Visibility) {} }; - // Note: sizeof(m_StaticSamplers) == 56 (MS compiler, release x64) - std::vector> m_StaticSamplers; + // Note: sizeof(m_ImmutableSamplers) == 56 (MS compiler, release x64) + std::vector> m_ImmutableSamplers; IMemoryAllocator& m_MemAllocator; diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp index 23652519..34a98a45 100644 --- a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp +++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp @@ -321,7 +321,7 @@ D3D12_STATIC_BORDER_COLOR BorderColorToD3D12StaticBorderColor(const Float32 Bord StaticBorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE; else { - LOG_ERROR_MESSAGE("Static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors."); + LOG_ERROR_MESSAGE("D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors."); } return StaticBorderColor; } diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index f04a309e..b65ad4fc 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -117,7 +117,7 @@ LinearAllocator PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoT MemPool.Reserve(); - m_RootSig.AllocateStaticSamplers(CreateInfo.PSODesc.ResourceLayout); + m_RootSig.AllocateImmutableSamplers(CreateInfo.PSODesc.ResourceLayout); m_pShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); @@ -417,7 +417,7 @@ void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& } ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(), (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, - (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); + (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0); } #endif diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp index bba639f8..2afb9eb1 100644 --- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp @@ -166,7 +166,7 @@ size_t RootSignature::RootParamsManager::GetHash() const RootSignature::RootSignature() : m_RootParams{GetRawAllocator()}, m_MemAllocator{GetRawAllocator()}, - m_StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerAttribs, GetRawAllocator(), "Allocator for vector")) + m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerAttribs, GetRawAllocator(), "Allocator for vector")) { m_SrvCbvUavRootTablesMap.fill(InvalidRootTableIndex); m_SamplerRootTablesMap.fill(InvalidRootTableIndex); @@ -282,29 +282,30 @@ D3D12_DESCRIPTOR_HEAP_TYPE HeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE Ran } -void RootSignature::InitStaticSampler(SHADER_TYPE ShaderType, - const char* SamplerName, - const char* SamplerSuffix, - const D3DShaderResourceAttribs& SamplerAttribs) +void RootSignature::InitImmutableSampler(SHADER_TYPE ShaderType, + const char* SamplerName, + const char* SamplerSuffix, + const D3DShaderResourceAttribs& SamplerAttribs) { auto ShaderVisibility = GetShaderVisibility(ShaderType); auto SamplerFound = false; - for (auto& StSmplr : m_StaticSamplers) + for (auto& ImtblSmplr : m_ImmutableSamplers) { - if (StSmplr.ShaderVisibility == ShaderVisibility && - StreqSuff(SamplerName, StSmplr.SamplerDesc.SamplerOrTextureName, SamplerSuffix)) + if (ImtblSmplr.ShaderVisibility == ShaderVisibility && + StreqSuff(SamplerName, ImtblSmplr.SamplerDesc.SamplerOrTextureName, SamplerSuffix)) { - StSmplr.ShaderRegister = SamplerAttribs.BindPoint; - StSmplr.ArraySize = SamplerAttribs.BindCount; - StSmplr.RegisterSpace = 0; - SamplerFound = true; + ImtblSmplr.ShaderRegister = SamplerAttribs.BindPoint; + ImtblSmplr.ArraySize = SamplerAttribs.BindCount; + ImtblSmplr.RegisterSpace = 0; + + SamplerFound = true; break; } } if (!SamplerFound) { - LOG_ERROR("Unable to find static sampler \'", SamplerName, '\''); + LOG_ERROR("Unable to find immutable sampler \'", SamplerName, '\''); } } @@ -446,19 +447,19 @@ void RootSignature::dbgVerifyRootParameters() const } #endif -void RootSignature::AllocateStaticSamplers(const PipelineResourceLayoutDesc& ResourceLayout) +void RootSignature::AllocateImmutableSamplers(const PipelineResourceLayoutDesc& ResourceLayout) { - if (ResourceLayout.NumStaticSamplers > 0) + if (ResourceLayout.NumImmutableSamplers > 0) { - m_StaticSamplers.reserve(ResourceLayout.NumStaticSamplers); - for (Uint32 sam = 0; sam < ResourceLayout.NumStaticSamplers; ++sam) + m_ImmutableSamplers.reserve(ResourceLayout.NumImmutableSamplers); + for (Uint32 sam = 0; sam < ResourceLayout.NumImmutableSamplers; ++sam) { - const auto& StSamDesc = ResourceLayout.StaticSamplers[sam]; - Uint32 ShaderStages = StSamDesc.ShaderStages; + const auto& ImtblSamDesc = ResourceLayout.ImmutableSamplers[sam]; + Uint32 ShaderStages = ImtblSamDesc.ShaderStages; while (ShaderStages != 0) { auto Stage = ShaderStages & ~(ShaderStages - 1); - m_StaticSamplers.emplace_back(StSamDesc, GetShaderVisibility(static_cast(Stage))); + m_ImmutableSamplers.emplace_back(ImtblSamDesc, GetShaderVisibility(static_cast(Stage))); ShaderStages &= ~Stage; } } @@ -516,19 +517,19 @@ void RootSignature::Finalize(ID3D12Device* pd3d12Device) rootSignatureDesc.pParameters = D3D12Parameters.size() ? D3D12Parameters.data() : nullptr; UINT TotalD3D12StaticSamplers = 0; - for (const auto& StSam : m_StaticSamplers) - TotalD3D12StaticSamplers += StSam.ArraySize; + for (const auto& ImtblSam : m_ImmutableSamplers) + TotalD3D12StaticSamplers += ImtblSam.ArraySize; rootSignatureDesc.NumStaticSamplers = TotalD3D12StaticSamplers; rootSignatureDesc.pStaticSamplers = nullptr; std::vector> D3D12StaticSamplers(STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector")); D3D12StaticSamplers.reserve(TotalD3D12StaticSamplers); - if (!m_StaticSamplers.empty()) + if (!m_ImmutableSamplers.empty()) { - for (size_t s = 0; s < m_StaticSamplers.size(); ++s) + for (size_t s = 0; s < m_ImmutableSamplers.size(); ++s) { - const auto& StSmplrDesc = m_StaticSamplers[s]; - const auto& SamDesc = StSmplrDesc.SamplerDesc.Desc; - for (UINT ArrInd = 0; ArrInd < StSmplrDesc.ArraySize; ++ArrInd) + const auto& ImtblSmplrDesc = m_ImmutableSamplers[s]; + const auto& SamDesc = ImtblSmplrDesc.SamplerDesc.Desc; + for (UINT ArrInd = 0; ArrInd < ImtblSmplrDesc.ArraySize; ++ArrInd) { D3D12StaticSamplers.emplace_back( D3D12_STATIC_SAMPLER_DESC // @@ -543,18 +544,18 @@ void RootSignature::Finalize(ID3D12Device* pd3d12Device) BorderColorToD3D12StaticBorderColor(SamDesc.BorderColor), SamDesc.MinLOD, SamDesc.MaxLOD, - StSmplrDesc.ShaderRegister + ArrInd, - StSmplrDesc.RegisterSpace, - StSmplrDesc.ShaderVisibility // - } // + ImtblSmplrDesc.ShaderRegister + ArrInd, + ImtblSmplrDesc.RegisterSpace, + ImtblSmplrDesc.ShaderVisibility // + } // ); } } rootSignatureDesc.pStaticSamplers = D3D12StaticSamplers.data(); - // Release static samplers array, we no longer need it - std::vector> EmptySamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerAttribs, GetRawAllocator(), "Allocator for vector")); - m_StaticSamplers.swap(EmptySamplers); + // Release immutable samplers array, we no longer need it + std::vector> EmptySamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerAttribs, GetRawAllocator(), "Allocator for vector")); + m_ImmutableSamplers.swap(EmptySamplers); VERIFY_EXPR(D3D12StaticSamplers.size() == TotalD3D12StaticSamplers); } @@ -640,7 +641,7 @@ void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl DEV_CHECK_ERR(!SamplerHeapSpace.IsNull(), "Failed to allocate ", TotalSamplerDescriptors, " GPU-visible Sampler descriptor", (TotalSamplerDescriptors > 1 ? "s" : ""), - ". Consider using static samplers in the Pipeline State Object or " + ". Consider using immutable samplers in the Pipeline State Object or " "increasing GPUDescriptorHeapSize[1] in EngineD3D12CreateInfo."); } VERIFY_EXPR(TotalSamplerDescriptors == 0 && SamplerHeapSpace.IsNull() || SamplerHeapSpace.GetNumHandles() == TotalSamplerDescriptors); @@ -965,7 +966,7 @@ void RootSignature::CommitDescriptorHandlesInternal_SMD(RenderDeviceD3D12Impl* DEV_CHECK_ERR(DynamicSamplerDescriptors.GetDescriptorHeap() != nullptr, "Failed to allocate ", NumDynamicSamplerDescriptors, " dynamic GPU-visible Sampler descriptor", (NumDynamicSamplerDescriptors > 1 ? "s" : ""), - ". Consider using static samplers in the Pipeline State Object, increasing GPUDescriptorHeapDynamicSize[1] in " + ". Consider using immutable samplers in the Pipeline State Object, increasing GPUDescriptorHeapDynamicSize[1] in " "EngineD3D12CreateInfo, or optimizing dynamic resource utilization by using static or mutable shader resource variables instead."); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index c0029da5..06e902fb 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -149,10 +149,11 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& auto VarType = m_pResources->FindVariableType(Sam, ResourceLayout); if (IsAllowedType(VarType, AllowedTypeBits)) { - constexpr bool LogStaticSamplerArrayError = true; - auto StaticSamplerInd = m_pResources->FindStaticSampler(Sam, ResourceLayout, LogStaticSamplerArrayError); - // Skip static samplers - if (StaticSamplerInd < 0) + constexpr bool LogImtblSamplerArrayError = true; + + auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError); + // Skip immutable samplers + if (ImtblSamplerInd < 0) ++SamplerCount[VarType]; } }, @@ -237,7 +238,7 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& VERIFY(RootIndex != D3D12Resource::InvalidRootIndex, "Root index must be valid"); VERIFY(Offset != D3D12Resource::InvalidOffset, "Offset must be valid"); - // Static samplers are never copied, and SamplerId == InvalidSamplerId + // Immutable samplers are never copied, and SamplerId == InvalidSamplerId auto& NewResource = (ResType == CachedResourceType::Sampler) ? GetSampler(VarType, CurrSampler[VarType]++) : GetSrvCbvUav(VarType, CurrCbvSrvUav[VarType]++); @@ -258,12 +259,13 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& if (IsAllowedType(VarType, AllowedTypeBits)) { // The error (if any) have already been logged when counting the resources - constexpr bool LogStaticSamplerArrayError = false; - auto StaticSamplerInd = m_pResources->FindStaticSampler(Sam, ResourceLayout, LogStaticSamplerArrayError); - if (StaticSamplerInd >= 0) + constexpr bool LogImtblSamplerArrayError = false; + + auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError); + if (ImtblSamplerInd >= 0) { if (pRootSig != nullptr) - pRootSig->InitStaticSampler(m_pResources->GetShaderType(), Sam.Name, m_pResources->GetCombinedSamplerSuffix(), Sam); + pRootSig->InitImmutableSampler(m_pResources->GetShaderType(), Sam.Name, m_pResources->GetCombinedSamplerSuffix(), Sam); } else { @@ -290,18 +292,19 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& ") of the sampler '", SamplerAttribs.Name, "' that is assigned to it"); // The error (if any) have already been logged when counting the resources - constexpr bool LogStaticSamplerArrayError = false; - auto StaticSamplerInd = m_pResources->FindStaticSampler(SamplerAttribs, ResourceLayout, LogStaticSamplerArrayError); - if (StaticSamplerInd >= 0) + constexpr bool LogImtblSamplerArrayError = false; + + auto ImtblSamplerInd = m_pResources->FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); + if (ImtblSamplerInd >= 0) { - // Static samplers are never copied, and SamplerId == InvalidSamplerId + // Immutable samplers are never copied, and SamplerId == InvalidSamplerId #ifdef DILIGENT_DEBUG auto SamplerCount = GetTotalSamplerCount(); for (Uint32 s = 0; s < SamplerCount; ++s) { const auto& Sampler = GetSampler(s); if (strcmp(Sampler.Attribs.Name, SamplerAttribs.Name) == 0) - LOG_ERROR("Static sampler '", Sampler.Attribs.Name, "' was found among resources. This seems to be a bug"); + LOG_ERROR("Immutable sampler '", Sampler.Attribs.Name, "' was found among resources. This seems to be a bug"); } #endif } @@ -619,7 +622,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject* if (ValidSamplerAssigned()) { auto& Sam = ParentResLayout.GetAssignedSampler(*this); - //VERIFY( !Sam.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" ); + //VERIFY( !Sam.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" ); VERIFY_EXPR(Attribs.BindCount == Sam.Attribs.BindCount || Sam.Attribs.BindCount == 1); auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0; @@ -793,7 +796,7 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR { const auto& SamInfo = DstLayout.GetAssignedSampler(res); - //VERIFY(!SamInfo.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache"); + //VERIFY(!SamInfo.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache"); VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid"); VERIFY_EXPR(SamInfo.Attribs.BindCount == res.Attribs.BindCount || SamInfo.Attribs.BindCount == 1); @@ -920,7 +923,7 @@ bool ShaderResourceLayoutD3D12::dvpVerifyBindings(const ShaderResourceCacheD3D12 { VERIFY(res.GetResType() == CachedResourceType::TexSRV, "Sampler can only be assigned to a texture SRV"); const auto& SamInfo = GetAssignedSampler(res); - //VERIFY(!SamInfo.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" ); + //VERIFY(!SamInfo.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" ); VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid"); for (Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd) diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp index 2843f9f0..f15d2e74 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp @@ -372,20 +372,20 @@ public: SHADER_RESOURCE_VARIABLE_TYPE FindVariableType(const D3DShaderResourceAttribs& ResourceAttribs, const PipelineResourceLayoutDesc& ResourceLayout) const; - Int32 FindStaticSampler(const D3DShaderResourceAttribs& ResourceAttribs, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - bool LogStaticSamplerArrayError) const; + Int32 FindImmutableSampler(const D3DShaderResourceAttribs& ResourceAttribs, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + bool LogImmutableSamplerArrayError) const; D3DShaderResourceCounters CountResources(const PipelineResourceLayoutDesc& ResourceLayout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes, - bool CountStaticSamplers) const noexcept; + bool CountImmutableSamplers) const noexcept; #ifdef DILIGENT_DEVELOPMENT static void DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& ResourceLayout, const ShaderResources* const pShaderResources[], Uint32 NumShaders, bool VerifyVariables, - bool VerifyStaticSamplers); + bool VerifyImmutableSamplers); #endif void GetShaderModel(Uint32& Major, Uint32& Minor) const diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 498e31a2..86a7fc35 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -122,44 +122,44 @@ SHADER_RESOURCE_VARIABLE_TYPE ShaderResources::FindVariableType(const D3DShaderR } } -Int32 ShaderResources::FindStaticSampler(const D3DShaderResourceAttribs& ResourceAttribs, - const PipelineResourceLayoutDesc& ResourceLayoutDesc, - bool LogStaticSamplerArrayError) const +Int32 ShaderResources::FindImmutableSampler(const D3DShaderResourceAttribs& ResourceAttribs, + const PipelineResourceLayoutDesc& ResourceLayoutDesc, + bool LogImmutableSamplerArrayError) const { VERIFY(ResourceAttribs.GetInputType() == D3D_SIT_SAMPLER, "Sampler is expected"); - auto StaticSamplerInd = - Diligent::FindStaticSampler(ResourceLayoutDesc.StaticSamplers, - ResourceLayoutDesc.NumStaticSamplers, - m_ShaderType, - ResourceAttribs.Name, - m_SamplerSuffix); + auto ImtblSamplerInd = + Diligent::FindImmutableSampler(ResourceLayoutDesc.ImmutableSamplers, + ResourceLayoutDesc.NumImmutableSamplers, + m_ShaderType, + ResourceAttribs.Name, + m_SamplerSuffix); - if (StaticSamplerInd >= 0 && ResourceAttribs.BindCount > 1) + if (ImtblSamplerInd >= 0 && ResourceAttribs.BindCount > 1) { Uint32 ShaderMajorVersion = 0; Uint32 ShaderMinorVersion = 0; GetShaderModel(ShaderMajorVersion, ShaderMinorVersion); if (ShaderMajorVersion >= 6 || ShaderMajorVersion >= 5 && ShaderMinorVersion >= 1) { - if (LogStaticSamplerArrayError) + if (LogImmutableSamplerArrayError) { - LOG_ERROR_MESSAGE("Static sampler '", ResourceAttribs.Name, '[', ResourceAttribs.BindCount, + LOG_ERROR_MESSAGE("Immutable sampler '", ResourceAttribs.Name, '[', ResourceAttribs.BindCount, "]' will be ignored because static sampler arrays are not allowed in shader model 5.1 and above. " "Compile the shader using shader model 5.0 or use non-array sampler variable."); } - StaticSamplerInd = -1; + ImtblSamplerInd = -1; } } - return StaticSamplerInd; + return ImtblSamplerInd; } D3DShaderResourceCounters ShaderResources::CountResources(const PipelineResourceLayoutDesc& ResourceLayout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, Uint32 NumAllowedTypes, - bool CountStaticSamplers) const noexcept + bool CountImmutableSamplers) const noexcept { auto AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); @@ -176,11 +176,11 @@ D3DShaderResourceCounters ShaderResources::CountResources(const PipelineResource auto VarType = FindVariableType(Sam, ResourceLayout); if (IsAllowedType(VarType, AllowedTypeBits)) { - if (!CountStaticSamplers) + if (!CountImmutableSamplers) { - constexpr bool LogStaticSamplerArrayError = false; - if (FindStaticSampler(Sam, ResourceLayout, LogStaticSamplerArrayError) >= 0) - return; // Skip static sampler if requested + constexpr bool LogImtblSamplerArrayError = false; + if (FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError) >= 0) + return; // Skip immutable sampler if requested } ++Counters.NumSamplers; } @@ -219,7 +219,7 @@ void ShaderResources::DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& const ShaderResources* const pShaderResources[], Uint32 NumShaders, bool VerifyVariables, - bool VerifyStaticSamplers) + bool VerifyImmutableSamplers) { auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) // { @@ -300,40 +300,40 @@ void ShaderResources::DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& } } - if (VerifyStaticSamplers) + if (VerifyImmutableSamplers) { - for (Uint32 sam = 0; sam < ResourceLayout.NumStaticSamplers; ++sam) + for (Uint32 sam = 0; sam < ResourceLayout.NumImmutableSamplers; ++sam) { - const auto& StSamDesc = ResourceLayout.StaticSamplers[sam]; + const auto& StSamDesc = ResourceLayout.ImmutableSamplers[sam]; if (StSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN) { - LOG_WARNING_MESSAGE("No allowed shader stages are specified for static sampler '", StSamDesc.SamplerOrTextureName, "'."); + LOG_WARNING_MESSAGE("No allowed shader stages are specified for immutable sampler '", StSamDesc.SamplerOrTextureName, "'."); continue; } const auto* TexOrSamName = StSamDesc.SamplerOrTextureName; - bool StaticSamplerFound = false; - for (Uint32 s = 0; s < NumShaders && !StaticSamplerFound; ++s) + bool ImtblSamplerFound = false; + for (Uint32 s = 0; s < NumShaders && !ImtblSamplerFound; ++s) { const auto& Resources = *pShaderResources[s]; if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0) continue; - // Look for static sampler. + // Look for immutable sampler. // In case HLSL-style combined image samplers are used, the condition is Sampler.Name == "g_Texture" + "_sampler". // Otherwise the condition is Sampler.Name == "g_Texture_sampler" + "". const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); - for (Uint32 n = 0; n < Resources.GetNumSamplers() && !StaticSamplerFound; ++n) + for (Uint32 n = 0; n < Resources.GetNumSamplers() && !ImtblSamplerFound; ++n) { const auto& Sampler = Resources.GetSampler(n); - StaticSamplerFound = StreqSuff(Sampler.Name, TexOrSamName, CombinedSamplerSuffix); + ImtblSamplerFound = StreqSuff(Sampler.Name, TexOrSamName, CombinedSamplerSuffix); } } - if (!StaticSamplerFound) + if (!ImtblSamplerFound) { - LOG_WARNING_MESSAGE("Static sampler '", TexOrSamName, "' is not found in any of the designated shader stages: ", + LOG_WARNING_MESSAGE("Immutable sampler '", TexOrSamName, "' is not found in any of the designated shader stages: ", GetAllowedShadersString(StSamDesc.ShaderStages)); } } diff --git a/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp b/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp index 80f622c9..24e88004 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp @@ -118,15 +118,15 @@ public: GLVariableBase(const GLProgramResources::GLResourceAttribs& ResourceAttribs, GLPipelineResourceLayout& ParentLayout, SHADER_RESOURCE_VARIABLE_TYPE VariableType, - Int32 StaticSamplerIdx) : + Int32 ImtblSamplerIdx) : // clang-format off TBase {ParentLayout}, m_Attribs {ResourceAttribs }, m_VariableType {VariableType }, - m_StaticSamplerIdx{StaticSamplerIdx} + m_ImtblSamplerIdx {ImtblSamplerIdx} // clang-format on { - VERIFY_EXPR(StaticSamplerIdx < 0 || ResourceAttribs.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV); + VERIFY_EXPR(ImtblSamplerIdx < 0 || ResourceAttribs.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV); } virtual SHADER_RESOURCE_VARIABLE_TYPE DILIGENT_CALL_TYPE GetType() const override final @@ -146,7 +146,7 @@ public: const GLProgramResources::GLResourceAttribs& m_Attribs; const SHADER_RESOURCE_VARIABLE_TYPE m_VariableType; - const Int32 m_StaticSamplerIdx; + const Int32 m_ImtblSamplerIdx; }; @@ -188,8 +188,8 @@ public: SamplerBindInfo(const GLProgramResources::GLResourceAttribs& ResourceAttribs, GLPipelineResourceLayout& ParentResLayout, SHADER_RESOURCE_VARIABLE_TYPE VariableType, - Int32 StaticSamplerIdx) : - GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, StaticSamplerIdx} + Int32 ImtblSamplerIdx) : + GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, ImtblSamplerIdx} {} // Non-virtual function diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp index 3fbc550e..eab96f6a 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp @@ -128,9 +128,9 @@ public: GetSampler(Binding).Set(std::move(pTexView), SetSampler); } - void SetStaticSampler(Uint32 Binding, ISampler* pStaticSampler) + void SetImmutableSampler(Uint32 Binding, ISampler* pImtblSampler) { - GetSampler(Binding).pSampler = ValidatedCast(pStaticSampler); + GetSampler(Binding).pSampler = ValidatedCast(pImtblSampler); } void CopySampler(Uint32 Binding, const CachedResourceView& SrcSam) diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp index 83f8bdad..0c5692d0 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp @@ -95,7 +95,7 @@ public: private: GLObjectWrappers::GLPipelineObj& GetGLProgramPipeline(GLContext::NativeGLContextType Context); - void InitStaticSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const; + void InitImmutableSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const; struct GLPipelineShaderStageInfo { @@ -143,8 +143,8 @@ private: Uint32 m_TotalImageBindings = 0; Uint32 m_TotalStorageBufferBindings = 0; - using SamplerPtr = RefCntAutoPtr; - SamplerPtr* m_StaticSamplers = nullptr; // [m_Desc.ResourceLayout.NumStaticSamplers] + using SamplerPtr = RefCntAutoPtr; + SamplerPtr* m_ImmutableSamplers = nullptr; // [m_Desc.ResourceLayout.NumImmutableSamplers] }; } // namespace Diligent diff --git a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp index 04a08af1..d2f9cddc 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp @@ -147,11 +147,11 @@ void GLPipelineResourceLayout::Initialize(GLProgramResources* P { auto VarType = GetShaderVariableType(ShaderStages, Sam.Name, ResourceLayout); VERIFY_EXPR(IsAllowedType(VarType, DbgAllowedTypeBits)); - Int32 StaticSamplerIdx = -1; + Int32 ImtblSamplerIdx = -1; if (Sam.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV) { - StaticSamplerIdx = FindStaticSampler(ResourceLayout.StaticSamplers, ResourceLayout.NumStaticSamplers, ShaderStages, - Sam.Name, nullptr); + ImtblSamplerIdx = FindImmutableSampler(ResourceLayout.ImmutableSamplers, ResourceLayout.NumImmutableSamplers, ShaderStages, + Sam.Name, nullptr); } auto* pSamVar = new (&GetResource(VarCounters.NumSamplers++)) SamplerBindInfo // @@ -159,7 +159,7 @@ void GLPipelineResourceLayout::Initialize(GLProgramResources* P Sam, *this, VarType, - StaticSamplerIdx // + ImtblSamplerIdx // }; SamplerBindingSlots = std::max(SamplerBindingSlots, pSamVar->m_Attribs.Binding + pSamVar->m_Attribs.ArraySize); }, @@ -290,13 +290,13 @@ void GLPipelineResourceLayout::SamplerBindInfo::BindResource(IDeviceObject* pVie { auto& CachedTexSampler = ResourceCache.GetConstSampler(m_Attribs.Binding + ArrayIndex); VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, CachedTexSampler.pView.RawPtr()); - if (m_StaticSamplerIdx >= 0) + if (m_ImtblSamplerIdx >= 0) { - VERIFY(CachedTexSampler.pSampler != nullptr, "Static samplers must be initialized by PipelineStateGLImpl::InitializeSRBResourceCache!"); + VERIFY(CachedTexSampler.pSampler != nullptr, "Immutable samplers must be initialized by PipelineStateGLImpl::InitializeSRBResourceCache!"); } } #endif - ResourceCache.SetTexSampler(m_Attribs.Binding + ArrayIndex, std::move(pViewGL), m_StaticSamplerIdx < 0); + ResourceCache.SetTexSampler(m_Attribs.Binding + ArrayIndex, std::move(pViewGL), m_ImtblSamplerIdx < 0); } else if (m_Attribs.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV) { @@ -794,9 +794,9 @@ bool GLPipelineResourceLayout::dvpVerifyBindings(const GLProgramResourceCache& R else { const auto& CachedSampler = ResourceCache.GetConstSampler(BindPoint); - if (sam.m_StaticSamplerIdx >= 0 && CachedSampler.pSampler == nullptr) + if (sam.m_ImtblSamplerIdx >= 0 && CachedSampler.pSampler == nullptr) { - LOG_ERROR_MESSAGE("Static sampler is not initialized for texture '", sam.m_Attribs.Name, "'"); + LOG_ERROR_MESSAGE("Immutable sampler is not initialized for texture '", sam.m_Attribs.Name, "'"); BindingsOK = false; } } diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 7b7d4e21..8bc3802e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -45,7 +45,7 @@ void PipelineStateGLImpl::Initialize(const PSOCreateInfoType& CreateInfo, const MemPool.AddSpace(GetNumShaderStages()); MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(m_Desc.ResourceLayout.NumStaticSamplers); + MemPool.AddSpace(m_Desc.ResourceLayout.NumImmutableSamplers); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); @@ -129,9 +129,9 @@ PipelineStateGLImpl::~PipelineStateGLImpl() m_GLPrograms[i].~GLProgramObj(); m_ProgramResources[i].~GLProgramResources(); } - for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumStaticSamplers; ++i) + for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumImmutableSamplers; ++i) { - m_StaticSamplers[i].~SamplerPtr(); + m_ImmutableSamplers[i].~SamplerPtr(); } void* pRawMem = m_GLPrograms; @@ -207,17 +207,17 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr); } - m_StaticSamplers = MemPool.ConstructArray(m_Desc.ResourceLayout.NumStaticSamplers); - for (Uint32 s = 0; s < m_Desc.ResourceLayout.NumStaticSamplers; ++s) + m_ImmutableSamplers = MemPool.ConstructArray(m_Desc.ResourceLayout.NumImmutableSamplers); + for (Uint32 s = 0; s < m_Desc.ResourceLayout.NumImmutableSamplers; ++s) { - pDeviceGL->CreateSampler(m_Desc.ResourceLayout.StaticSamplers[s].Desc, &m_StaticSamplers[s]); + pDeviceGL->CreateSampler(m_Desc.ResourceLayout.ImmutableSamplers[s].Desc, &m_ImmutableSamplers[s]); } { // Clone only static variables into static resource layout, assign and initialize static resource cache const SHADER_RESOURCE_VARIABLE_TYPE StaticVars[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; m_StaticResourceLayout.Initialize(m_ProgramResources, static_cast(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache); - InitStaticSamplersInResourceCache(m_StaticResourceLayout, m_StaticResourceCache); + InitImmutableSamplersInResourceCache(m_StaticResourceLayout, m_StaticResourceCache); } } @@ -303,19 +303,19 @@ GLObjectWrappers::GLPipelineObj& PipelineStateGLImpl::GetGLProgramPipeline(GLCon void PipelineStateGLImpl::InitializeSRBResourceCache(GLProgramResourceCache& ResourceCache) const { ResourceCache.Initialize(m_TotalUniformBufferBindings, m_TotalSamplerBindings, m_TotalImageBindings, m_TotalStorageBufferBindings, GetRawAllocator()); - InitStaticSamplersInResourceCache(m_ResourceLayout, ResourceCache); + InitImmutableSamplersInResourceCache(m_ResourceLayout, ResourceCache); } -void PipelineStateGLImpl::InitStaticSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const +void PipelineStateGLImpl::InitImmutableSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const { for (Uint32 s = 0; s < ResourceLayout.GetNumResources(); ++s) { const auto& Sam = ResourceLayout.GetConstResource(s); - if (Sam.m_StaticSamplerIdx >= 0) + if (Sam.m_ImtblSamplerIdx >= 0) { - ISampler* pSampler = m_StaticSamplers[Sam.m_StaticSamplerIdx].RawPtr(); + ISampler* pSampler = m_ImmutableSamplers[Sam.m_ImtblSamplerIdx].RawPtr(); for (Uint32 binding = Sam.m_Attribs.Binding; binding < Sam.m_Attribs.Binding + Sam.m_Attribs.ArraySize; ++binding) - Cache.SetStaticSampler(binding, pSampler); + Cache.SetImmutableSampler(binding, pSampler); } } } diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 62ff38b5..0013fe23 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -158,7 +158,7 @@ public: const PipelineResourceLayoutDesc& ResourceLayoutDesc, class PipelineLayout& PipelineLayout, bool VerifyVariables, - bool VerifyStaticSamplers); + bool VerifyImmutableSamplers); // sizeof(VkResource) == 24 (x64) struct VkResource @@ -293,7 +293,7 @@ public: static void dvpVerifyResourceLayoutDesc(const TShaderStages& ShaderStages, const PipelineResourceLayoutDesc& ResourceLayoutDesc, bool VerifyVariables, - bool VerifyStaticSamplers); + bool VerifyImmutableSamplers); #endif Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp index d6f4b0be..e7ab95b1 100644 --- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp +++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp @@ -166,9 +166,9 @@ std::array, 4> GenerateMipsVkHelper::CreatePSOs(TE PSODesc.ResourceLayout.Variables = &VarDesc; PSODesc.ResourceLayout.NumVariables = 1; - const StaticSamplerDesc StaticSampler(SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp); - PSODesc.ResourceLayout.StaticSamplers = &StaticSampler; - PSODesc.ResourceLayout.NumStaticSamplers = 1; + const ImmutableSamplerDesc ImtblSampler{SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp}; + PSODesc.ResourceLayout.ImmutableSamplers = &ImtblSampler; + PSODesc.ResourceLayout.NumImmutableSamplers = 1; m_DeviceVkImpl.CreateComputePipelineState(PSOCreateInfo, &PSOs[NonPowOfTwo]); PSOs[NonPowOfTwo]->GetStaticVariableByName(SHADER_TYPE_COMPUTE, "CB")->Set(m_ConstantsCB); diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp index 6ed84171..b221659a 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp @@ -213,7 +213,7 @@ bool PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::operator== if ((B0.pImmutableSamplers != nullptr && B1.pImmutableSamplers == nullptr) || (B0.pImmutableSamplers == nullptr && B1.pImmutableSamplers != nullptr)) return false; - // Static samplers themselves should not affect compatibility + // Immutable samplers themselves should not affect compatibility // clang-format on } return true; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index dfa270cc..6cbe5da9 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -426,7 +426,7 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(), m_Desc.ResourceLayout, m_PipelineLayout, (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0, - (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0); + (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0); m_PipelineLayout.Finalize(LogicalDevice); if (m_Desc.SRBAllocationGranularity > 1) diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp index 33e0aa82..e73ee9aa 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp @@ -63,10 +63,10 @@ static Int32 FindImmutableSampler(SHADER_TYPE ShaderType, return -1; } - for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s) + for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s) { - const auto& StSam = ResourceLayoutDesc.StaticSamplers[s]; - if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, StSam.SamplerOrTextureName, SamplerSuffix)) + const auto& ImtblSam = ResourceLayoutDesc.ImmutableSamplers[s]; + if (((ImtblSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, ImtblSam.SamplerOrTextureName, SamplerSuffix)) return s; } @@ -154,10 +154,10 @@ void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* m_NumImmutableSamplers = 0; if (AllocateImmutableSamplers) { - for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s) + for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s) { - const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[s]; - if ((StSamDesc.ShaderStages & ShaderType) != 0) + const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[s]; + if ((ImtblSamDesc.ShaderStages & ShaderType) != 0) ++m_NumImmutableSamplers; } } @@ -286,7 +286,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const ShaderVkImpl* void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& ShaderStages, const PipelineResourceLayoutDesc& ResourceLayoutDesc, bool VerifyVariables, - bool VerifyStaticSamplers) + bool VerifyImmutableSamplers) { auto GetAllowedShadersString = [&](SHADER_TYPE Stages) // { @@ -359,14 +359,14 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& } } - if (VerifyStaticSamplers) + if (VerifyImmutableSamplers) { - for (Uint32 sam = 0; sam < ResourceLayoutDesc.NumStaticSamplers; ++sam) + for (Uint32 sam = 0; sam < ResourceLayoutDesc.NumImmutableSamplers; ++sam) { - const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[sam]; - if (StSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN) + const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[sam]; + if (ImtblSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN) { - LOG_WARNING_MESSAGE("No allowed shader stages are specified for static sampler '", StSamDesc.SamplerOrTextureName, "'."); + LOG_WARNING_MESSAGE("No allowed shader stages are specified for immutable sampler '", ImtblSamDesc.SamplerOrTextureName, "'."); continue; } @@ -374,36 +374,36 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s) { const auto& Resources = *ShaderStages[s].pShader->GetShaderResources(); - if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0) + if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0) continue; // Irrespective of whether HLSL-style combined image samplers are used, - // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex) + // an immutable sampler can be assigned to a GLSL sampled image (i.e. sampler2D g_tex) for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i) { const auto& SmplImg = Resources.GetSmpldImg(i); - SamplerFound = (strcmp(SmplImg.Name, StSamDesc.SamplerOrTextureName) == 0); + SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0); } if (!SamplerFound) { - // Check if static sampler is assigned to a separate sampler. + // Check if an immutable sampler is assigned to a separate sampler. // In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler". // Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "". const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix(); for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i) { const auto& SepSmpl = Resources.GetSepSmplr(i); - SamplerFound = StreqSuff(SepSmpl.Name, StSamDesc.SamplerOrTextureName, CombinedSamplerSuffix); + SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix); } } } if (!SamplerFound) { - LOG_WARNING_MESSAGE("Static sampler '", StSamDesc.SamplerOrTextureName, + LOG_WARNING_MESSAGE("Immutable sampler '", ImtblSamDesc.SamplerOrTextureName, "' is not found in any of the designated shader stages: ", - GetAllowedShadersString(StSamDesc.ShaderStages)); + GetAllowedShadersString(ImtblSamDesc.ShaderStages)); } } } @@ -417,10 +417,10 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende const PipelineResourceLayoutDesc& ResourceLayoutDesc, class PipelineLayout& PipelineLayout, bool VerifyVariables, - bool VerifyStaticSamplers) + bool VerifyImmutableSamplers) { #ifdef DILIGENT_DEVELOPMENT - dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyStaticSamplers); + dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyImmutableSamplers); #endif const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr; @@ -473,7 +473,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRende { auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++); VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!"); - const auto& ImmutableSamplerDesc = ResourceLayoutDesc.StaticSamplers[SrcImmutableSamplerInd].Desc; + const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc; pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler); vkImmutableSampler = ImmutableSampler.RawPtr()->GetVkSampler(); } -- cgit v1.2.3 From e5f36378de4a7258fcc9d6ca7a349df1136b7444 Mon Sep 17 00:00:00 2001 From: assiduous Date: Mon, 19 Oct 2020 12:08:40 -0700 Subject: Renamed USAGE_STATIC to USAGE_IMMUTABLE (API240077) --- Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp | 12 ++++++------ Graphics/GraphicsEngine/interface/APIInfo.h | 2 +- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 4 ++-- Graphics/GraphicsEngine/interface/RenderDevice.h | 4 ++-- Graphics/GraphicsEngine/src/BufferBase.cpp | 6 +++--- .../GraphicsEngineD3D11/include/D3D11TypeConversions.hpp | 4 ++-- Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp | 4 ++-- Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp | 4 ++-- Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp | 4 ++-- Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp | 6 +++--- Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp | 2 +- Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp | 4 ++-- Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp | 4 ++-- Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp | 6 +++--- Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp | 6 +++--- 15 files changed, 36 insertions(+), 36 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp index 7cc46ea1..fc6939e9 100644 --- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp +++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp @@ -765,16 +765,16 @@ const Char* GetUsageString(USAGE Usage) { // clang-format off #define INIT_USGAGE_STR(Usage)UsageStrings[Usage] = #Usage - INIT_USGAGE_STR( USAGE_STATIC ); - INIT_USGAGE_STR( USAGE_DEFAULT ); - INIT_USGAGE_STR( USAGE_DYNAMIC ); - INIT_USGAGE_STR( USAGE_STAGING ); - INIT_USGAGE_STR( USAGE_UNIFIED ); + INIT_USGAGE_STR(USAGE_IMMUTABLE); + INIT_USGAGE_STR(USAGE_DEFAULT); + INIT_USGAGE_STR(USAGE_DYNAMIC); + INIT_USGAGE_STR(USAGE_STAGING); + INIT_USGAGE_STR(USAGE_UNIFIED); #undef INIT_USGAGE_STR // clang-format on bUsageStringsInit = true; } - if (Usage >= USAGE_STATIC && Usage < USAGE_NUM_USAGES) + if (Usage >= USAGE_IMMUTABLE && Usage < USAGE_NUM_USAGES) return UsageStrings[Usage]; else { diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index a32511d2..327f54c7 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240076 +#define DILIGENT_API_VERSION 240077 #include "../../../Primitives/interface/BasicTypes.h" diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 74e16535..0f6b4b82 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -103,7 +103,7 @@ DILIGENT_TYPED_ENUM(USAGE, Uint8) /// when it is created, since it cannot be changed after creation. \n /// D3D11 Counterpart: D3D11_USAGE_IMMUTABLE. OpenGL counterpart: GL_STATIC_DRAW /// \remarks Static buffers do not allow CPU access and must use CPU_ACCESS_NONE flag. - USAGE_STATIC = 0, + USAGE_IMMUTABLE = 0, /// A resource that requires read and write access by the GPU and can also be occasionally /// written by the CPU. \n @@ -1706,7 +1706,7 @@ struct GraphicsAdapterInfo /// The amount of local video memory that is inaccessible by CPU, in bytes. - /// \note Device-local memory is where USAGE_DEFAULT and USAGE_STATIC resources + /// \note Device-local memory is where USAGE_DEFAULT and USAGE_IMMUTABLE resources /// are typically allocated. /// /// On some devices it may not be possible to query the memory size, diff --git a/Graphics/GraphicsEngine/interface/RenderDevice.h b/Graphics/GraphicsEngine/interface/RenderDevice.h index 5c72c81a..252daf1a 100644 --- a/Graphics/GraphicsEngine/interface/RenderDevice.h +++ b/Graphics/GraphicsEngine/interface/RenderDevice.h @@ -75,7 +75,7 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) /// \param [in] BuffDesc - Buffer description, see Diligent::BufferDesc for details. /// \param [in] pBuffData - Pointer to Diligent::BufferData structure that describes /// initial buffer data or nullptr if no data is provided. - /// Static buffers (USAGE_STATIC) must be initialized at creation time. + /// Immutable buffers (USAGE_IMMUTABLE) must be initialized at creation time. /// \param [out] ppBuffer - Address of the memory location where the pointer to the /// buffer interface will be stored. The function calls AddRef(), /// so that the new buffer will contain one reference and must be @@ -106,7 +106,7 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject) /// \param [in] TexDesc - Texture description, see Diligent::TextureDesc for details. /// \param [in] pData - Pointer to Diligent::TextureData structure that describes /// initial texture data or nullptr if no data is provided. - /// Static textures (USAGE_STATIC) must be initialized at creation time. + /// Immutable textures (USAGE_IMMUTABLE) must be initialized at creation time. /// /// \param [out] ppTexture - Address of the memory location where the pointer to the /// texture interface will be stored. diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp index 4aff91a0..0239ed92 100644 --- a/Graphics/GraphicsEngine/src/BufferBase.cpp +++ b/Graphics/GraphicsEngine/src/BufferBase.cpp @@ -71,7 +71,7 @@ void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) switch (Desc.Usage) { - case USAGE_STATIC: + case USAGE_IMMUTABLE: case USAGE_DEFAULT: VERIFY_BUFFER(Desc.CPUAccessFlags == CPU_ACCESS_NONE, "static and default buffers can't have any CPU access flags set."); break; @@ -114,8 +114,8 @@ void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps) void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData) { - if (Desc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr)) - LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as static buffers must be initialized at creation time."); + if (Desc.Usage == USAGE_IMMUTABLE && (pBuffData == nullptr || pBuffData->pData == nullptr)) + LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as immutable buffers must be initialized at creation time."); if (Desc.Usage == USAGE_DYNAMIC && pBuffData != nullptr && pBuffData->pData != nullptr) LOG_BUFFER_ERROR_AND_THROW("initial data must be null for dynamic buffers."); diff --git a/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp b/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp index 5a87cfd7..96de94f9 100644 --- a/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp +++ b/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp @@ -79,7 +79,7 @@ inline D3D11_USAGE UsageToD3D11Usage(USAGE Usage) switch (Usage) { // clang-format off - case USAGE_STATIC: return D3D11_USAGE_IMMUTABLE; + case USAGE_IMMUTABLE: return D3D11_USAGE_IMMUTABLE; case USAGE_DEFAULT: return D3D11_USAGE_DEFAULT; case USAGE_DYNAMIC: return D3D11_USAGE_DYNAMIC; case USAGE_STAGING: return D3D11_USAGE_STAGING; @@ -93,7 +93,7 @@ inline USAGE D3D11UsageToUsage(D3D11_USAGE D3D11Usage) switch (D3D11Usage) { // clang-format off - case D3D11_USAGE_IMMUTABLE: return USAGE_STATIC; + case D3D11_USAGE_IMMUTABLE: return USAGE_IMMUTABLE; case D3D11_USAGE_DEFAULT: return USAGE_DEFAULT; case D3D11_USAGE_DYNAMIC: return USAGE_DYNAMIC; case D3D11_USAGE_STAGING: return USAGE_STAGING; diff --git a/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp index de7c843d..16e77806 100644 --- a/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp @@ -62,8 +62,8 @@ BufferD3D11Impl::BufferD3D11Impl(IReferenceCounters* pRefCounters, LOG_ERROR_AND_THROW("Unified resources are not supported in Direct3D11"); } - if (m_Desc.Usage == USAGE_STATIC) - VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers"); + if (m_Desc.Usage == USAGE_IMMUTABLE) + VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers"); if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER) { diff --git a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp index 7a744b57..0e9b217b 100644 --- a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp @@ -51,8 +51,8 @@ TextureBaseD3D11::TextureBaseD3D11(IReferenceCounters* pRefCounters, } // clang-format on { - if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr)) - LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null"); + if (m_Desc.Usage == USAGE_IMMUTABLE && (pInitData == nullptr || pInitData->pSubResources == nullptr)) + LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time: pInitData can't be null"); SetState(RESOURCE_STATE_UNDEFINED); } diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp index c89a7423..d7cd54b6 100644 --- a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp @@ -68,8 +68,8 @@ BufferD3D12Impl::BufferD3D12Impl(IReferenceCounters* pRefCounters, LOG_ERROR_AND_THROW("Unified resources are not supported in Direct3D12"); } - if (m_Desc.Usage == USAGE_STATIC) - VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers"); + if (m_Desc.Usage == USAGE_IMMUTABLE) + VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers"); if (m_Desc.Usage == USAGE_DYNAMIC) VERIFY(pBuffData == nullptr || pBuffData->pData == nullptr, "Initial data must be null for dynamic buffers"); diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp index a4033f51..22829770 100644 --- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp @@ -135,8 +135,8 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, const TextureData* pInitData /*= nullptr*/) : TTextureBase{pRefCounters, TexViewObjAllocator, pRenderDeviceD3D12, TexDesc} { - if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr)) - LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null"); + if (m_Desc.Usage == USAGE_IMMUTABLE && (pInitData == nullptr || pInitData->pSubResources == nullptr)) + LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time: pInitData can't be null"); if ((m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0) { @@ -149,7 +149,7 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters, D3D12_RESOURCE_DESC Desc = GetD3D12TextureDesc(); auto* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device(); - if (m_Desc.Usage == USAGE_STATIC || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC) + if (m_Desc.Usage == USAGE_IMMUTABLE || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC) { D3D12_CLEAR_VALUE ClearValue = {}; D3D12_CLEAR_VALUE* pClearValue = nullptr; diff --git a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp index a93528ec..4c57652f 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp @@ -82,7 +82,7 @@ inline GLenum UsageToGLUsage(const BufferDesc& Desc) // DYNAMIC: The data store contents will be modified repeatedly and used many times. // clang-format off - case USAGE_STATIC: return GL_STATIC_DRAW; + case USAGE_IMMUTABLE: return GL_STATIC_DRAW; case USAGE_DEFAULT: return GL_STATIC_DRAW; case USAGE_UNIFIED: return GL_STATIC_DRAW; case USAGE_DYNAMIC: return GL_DYNAMIC_DRAW; diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp index 4bba7d46..ac99cfa0 100644 --- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp @@ -96,8 +96,8 @@ BufferGLImpl::BufferGLImpl(IReferenceCounters* pRefCounters, LOG_ERROR_AND_THROW("Unified resources are not supported in OpenGL/GLES"); } - if (m_Desc.Usage == USAGE_STATIC) - VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers"); + if (m_Desc.Usage == USAGE_IMMUTABLE) + VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers"); // TODO: find out if it affects performance if the buffer is originally bound to one target // and then bound to another (such as first to GL_ARRAY_BUFFER and then to GL_UNIFORM_BUFFER) diff --git a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp index 564d16cb..243ab1c9 100644 --- a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp @@ -63,8 +63,8 @@ TextureBaseGL::TextureBaseGL(IReferenceCounters* pRefCounters, // clang-format on { VERIFY(m_GLTexFormat != 0, "Unsupported texture format"); - if (TexDesc.Usage == USAGE_STATIC && pInitData == nullptr) - LOG_ERROR_AND_THROW("Static Texture must be initialized with data at creation time"); + if (TexDesc.Usage == USAGE_IMMUTABLE && pInitData == nullptr) + LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time"); if (TexDesc.Usage == USAGE_STAGING) { diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp index 8edb3472..3e61a756 100644 --- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp @@ -59,8 +59,8 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters, { ValidateBufferInitData(BuffDesc, pBuffData); - if (m_Desc.Usage == USAGE_STATIC) - VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers"); + if (m_Desc.Usage == USAGE_IMMUTABLE) + VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers"); if (m_Desc.Usage == USAGE_DYNAMIC) VERIFY(pBuffData == nullptr || pBuffData->pData == nullptr, "Initial data must be null for dynamic buffers"); @@ -186,7 +186,7 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters, VkMemoryPropertyFlags vkMemoryFlags = 0; switch (m_Desc.Usage) { - case USAGE_STATIC: + case USAGE_IMMUTABLE: case USAGE_DEFAULT: case USAGE_DYNAMIC: // Dynamic buffer with SRV or UAV bind flag vkMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp index 313de089..488e4bf6 100644 --- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp @@ -54,13 +54,13 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters, } // clang-format on { - if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr)) - LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null"); + if (m_Desc.Usage == USAGE_IMMUTABLE && (pInitData == nullptr || pInitData->pSubResources == nullptr)) + LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time: pInitData can't be null"); const auto& FmtAttribs = GetTextureFormatAttribs(m_Desc.Format); const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice(); - if (m_Desc.Usage == USAGE_STATIC || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC) + if (m_Desc.Usage == USAGE_IMMUTABLE || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC) { VkImageCreateInfo ImageCI = {}; -- cgit v1.2.3 From 13b0b54987db2684e46e337d2e5be5b81366083b Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 20 Oct 2020 13:26:21 -0700 Subject: Improved exception safety of pipeline state object construction --- .../GraphicsEngine/include/PipelineStateBase.hpp | 8 +- .../include/PipelineStateD3D11Impl.hpp | 4 +- .../include/ShaderResourceCacheD3D11.hpp | 2 +- .../include/ShaderResourceLayoutD3D11.hpp | 23 +- .../src/PipelineStateD3D11Impl.cpp | 210 +++++---- .../src/ShaderResourceBindingD3D11Impl.cpp | 23 +- .../src/ShaderResourceCacheD3D11.cpp | 93 ++-- .../src/ShaderResourceLayoutD3D11.cpp | 23 +- .../include/PipelineStateD3D12Impl.hpp | 4 +- .../include/ShaderResourceCacheD3D12.hpp | 2 +- .../include/ShaderResourceLayoutD3D12.hpp | 25 +- .../include/ShaderVariableD3D12.hpp | 18 +- .../src/PipelineStateD3D12Impl.cpp | 501 +++++++++++---------- .../src/ShaderResourceBindingD3D12Impl.cpp | 17 +- .../src/ShaderResourceLayoutD3D12.cpp | 27 +- .../src/ShaderVariableD3D12.cpp | 23 +- .../include/ShaderResources.hpp | 2 +- .../GraphicsEngineD3DBase/src/ShaderResources.cpp | 2 +- .../include/GLProgramResourceCache.hpp | 2 +- .../include/PipelineStateGLImpl.hpp | 2 + .../src/GLProgramResourceCache.cpp | 4 +- .../src/PipelineStateGLImpl.cpp | 130 ++++-- .../include/PipelineStateVkImpl.hpp | 10 +- .../include/ShaderResourceCacheVk.hpp | 2 +- .../include/ShaderResourceLayoutVk.hpp | 2 +- .../include/ShaderVariableVk.hpp | 24 +- .../src/PipelineStateVkImpl.cpp | 123 +++-- .../src/ShaderResourceBindingVkImpl.cpp | 3 +- .../GraphicsEngineVulkan/src/ShaderVariableVk.cpp | 29 +- 29 files changed, 738 insertions(+), 600 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp index c108f663..1effd32f 100644 --- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp +++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp @@ -222,7 +222,7 @@ protected: void ReserveSpaceForPipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) + LinearAllocator& MemPool) noexcept { MemPool.AddSpace(); ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); @@ -240,7 +240,7 @@ protected: } void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo, - LinearAllocator& MemPool) const + LinearAllocator& MemPool) const noexcept { ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool); } @@ -448,7 +448,7 @@ protected: } private: - void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) const + static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) noexcept { if (SrcLayout.Variables != nullptr) { @@ -471,7 +471,7 @@ private: } } - void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) const + static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool) { if (SrcLayout.Variables != nullptr) { diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp index 0fa62606..520e9bb0 100644 --- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp @@ -138,11 +138,13 @@ public: private: template - LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo); + void InitInternalObjects(const PSOCreateInfoType& CreateInfo); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, const std::vector>& ShaderStages); + void Destruct(); + CComPtr m_pd3d11BlendState; CComPtr m_pd3d11RasterizerState; CComPtr m_pd3d11DepthStencilState; diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp index dc70eec1..7aa7126d 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp @@ -51,7 +51,7 @@ namespace Diligent class ShaderResourceCacheD3D11 { public: - ShaderResourceCacheD3D11() + ShaderResourceCacheD3D11() noexcept {} ~ShaderResourceCacheD3D11(); diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp index 4b4d13b2..9b2c2d9b 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp @@ -47,14 +47,19 @@ namespace Diligent class ShaderResourceLayoutD3D11 { public: - ShaderResourceLayoutD3D11(IObject& Owner, - std::shared_ptr pSrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, - Uint32 NumVarTypes, - ShaderResourceCacheD3D11& ResourceCache, - IMemoryAllocator& ResCacheDataAllocator, - IMemoryAllocator& ResLayoutDataAllocator); + 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 @@ -68,7 +73,7 @@ public: static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, const PipelineResourceLayoutDesc& ResourceLayout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes); + Uint32 NumAllowedTypes) noexcept; void CopyResources(ShaderResourceCacheD3D11& DstCache) const; diff --git a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp index 722318f2..108f149c 100644 --- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp @@ -36,30 +36,42 @@ namespace Diligent { template -LinearAllocator PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo) +void PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo) { m_ResourceLayoutIndex.fill(-1); std::vector> ShaderStages; ExtractShaders(CreateInfo, ShaderStages); - // Memory must be released if an exception is thrown. + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - m_pStaticResourceLayouts = MemPool.Allocate(GetNumShaderStages()); - m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); + 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); - InitResourceLayouts(CreateInfo, ShaderStages); - return 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, ShaderStages); } @@ -77,9 +89,11 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* m_ImmutableSamplers (STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) // clang-format on { - auto MemPool = InitInternalObjects(CreateInfo); + try + { + InitInternalObjects(CreateInfo); - auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + auto& GraphicsPipeline = GetGraphicsPipelineDesc(); #define INIT_SHADER(ShortName, ExpectedType) \ do \ @@ -94,52 +108,55 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* 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); + 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 - if (m_pVS == nullptr) - { - LOG_ERROR_AND_THROW("Vertex shader is null"); - } + if (m_pVS == nullptr) + { + LOG_ERROR_AND_THROW("Vertex shader is null"); + } - auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); + auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device(); - D3D11_BLEND_DESC D3D11BSDesc = {}; - BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateBlendState(&D3D11BSDesc, &m_pd3d11BlendState), - "Failed to create D3D11 blend state object"); + D3D11_BLEND_DESC D3D11BSDesc = {}; + BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateBlendState(&D3D11BSDesc, &m_pd3d11BlendState), + "Failed to create D3D11 blend state object"); - D3D11_RASTERIZER_DESC D3D11RSDesc = {}; - RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, D3D11RSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateRasterizerState(&D3D11RSDesc, &m_pd3d11RasterizerState), - "Failed to create D3D11 rasterizer state"); + D3D11_RASTERIZER_DESC D3D11RSDesc = {}; + RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, D3D11RSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateRasterizerState(&D3D11RSDesc, &m_pd3d11RasterizerState), + "Failed to create D3D11 rasterizer state"); - D3D11_DEPTH_STENCIL_DESC D3D11DSSDesc = {}; - DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc); - CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateDepthStencilState(&D3D11DSSDesc, &m_pd3d11DepthStencilState), - "Failed to create D3D11 depth stencil state"); + D3D11_DEPTH_STENCIL_DESC D3D11DSSDesc = {}; + DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc); + CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateDepthStencilState(&D3D11DSSDesc, &m_pd3d11DepthStencilState), + "Failed to create D3D11 depth stencil state"); - // Create input layout - const auto& InputLayout = GraphicsPipeline.InputLayout; - if (InputLayout.NumElements > 0) - { - std::vector> d311InputElements(STD_ALLOCATOR_RAW_MEM(D3D11_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); - LayoutElements_To_D3D11_INPUT_ELEMENT_DESCs(InputLayout, d311InputElements); + // Create input layout + const auto& InputLayout = GraphicsPipeline.InputLayout; + if (InputLayout.NumElements > 0) + { + 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 = m_pVS.RawPtr()->GetBytecode(); + if (!pVSByteCode) + LOG_ERROR_AND_THROW("Vertex Shader byte code does not exist"); - 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"); + 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"); + } + } + catch (...) + { + Destruct(); + throw; } - - auto* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); } PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters, @@ -156,38 +173,55 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")) // clang-format on { - auto MemPool = InitInternalObjects(CreateInfo); - - m_pCS = ValidatedCast(CreateInfo.pCS); - if (m_pCS == nullptr) + try { - LOG_ERROR_AND_THROW("Compute shader is null"); - } + InitInternalObjects(CreateInfo); - if (m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE) + 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(); + } + catch (...) { - LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(SHADER_TYPE_COMPUTE), " shader is expeceted while ", GetShaderTypeLiteralName(m_pCS->GetDesc().ShaderType), " provided"); + Destruct(); + throw; } - m_ShaderResourceLayoutHash = m_pCS->GetD3D11Resources()->GetHash(); - - auto* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pStaticResourceLayouts); } PipelineStateD3D11Impl::~PipelineStateD3D11Impl() { - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + Destruct(); +} + +void PipelineStateD3D11Impl::Destruct() +{ + if (m_pStaticResourceLayouts != nullptr) { - m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); - m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); + for (Uint32 l = 0; l < GetNumShaderStages(); ++l) + { + m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); + } } - for (Uint32 l = 0; l < GetNumShaderStages(); ++l) + if (m_pStaticResourceCaches != nullptr) { - m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11(); + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + { + m_pStaticResourceCaches[s].Destroy(GetRawAllocator()); + m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11(); + } } - // m_pStaticResourceLayouts and m_pStaticResourceCaches are allocated in contiguous chunks of memory. - if (auto* pRawMem = m_pStaticResourceLayouts) + + // All subobjects are allocated in contiguous chunks of memory. + if (auto* pRawMem = m_pStaticResourceCaches) GetRawAllocator().Free(pRawMem); } @@ -213,42 +247,36 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& } #endif - decltype(m_ImmutableSamplers) ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")); + decltype(m_ImmutableSamplers) ImmutableSamplers{STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector")}; + std::array ShaderResLayoutDataSizes = {}; std::array ShaderResCacheDataSizes = {}; for (Uint32 s = 0; s < ShaderStages.size(); ++s) { - const auto* pShader = ShaderStages[s].second; - const auto& ShaderDesc = pShader->GetDesc(); - const auto& ShaderResources = *pShader->GetD3D11Resources(); - VERIFY_EXPR(ShaderDesc.ShaderType == ShaderResources.GetShaderType()); + const auto* pShader = ShaderStages[s].second; + const auto& ShaderDesc = pShader->GetDesc(); + const auto& Resources = *pShader->GetD3D11Resources(); + VERIFY_EXPR(ShaderDesc.ShaderType == Resources.GetShaderType()); - new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D11; - // Do not initialize the cache as this will be performed by the resource layout + // 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}; - // clang-format off - new (m_pStaticResourceLayouts + s) - ShaderResourceLayoutD3D11 - { - *this, - pShader->GetD3D11Resources(), - m_Desc.ResourceLayout, - StaticVarTypes, - _countof(StaticVarTypes), - m_pStaticResourceCaches[s], - GetRawAllocator(), - GetRawAllocator() - }; - // clang-format on + m_pStaticResourceLayouts[s].Initialize( + pShader->GetD3D11Resources(), + m_Desc.ResourceLayout, + StaticVarTypes, + _countof(StaticVarTypes), + GetRawAllocator(), + GetRawAllocator() // + ); // Initialize immutable samplers - for (Uint32 sam = 0; sam < ShaderResources.GetNumSamplers(); ++sam) + for (Uint32 sam = 0; sam < Resources.GetNumSamplers(); ++sam) { - const auto& SamplerAttribs = ShaderResources.GetSampler(sam); + const auto& SamplerAttribs = Resources.GetSampler(sam); constexpr bool LogImtblSamplerArrayError = true; - auto SrcImtblSamplerInd = ShaderResources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); + auto SrcImtblSamplerInd = Resources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError); if (SrcImtblSamplerInd >= 0) { const auto& SrcImtblSamplerInfo = ResourceLayout.ImmutableSamplers[SrcImtblSamplerInd]; @@ -267,8 +295,8 @@ void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC // }; - ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(ShaderResources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes)); - ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(ShaderResources); + ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(Resources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes)); + ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(Resources); } auto ShaderInd = GetShaderTypePipelineIndex(ShaderDesc.ShaderType, m_Desc.PipelineType); diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index 5e95db97..f7ce059b 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -77,20 +77,15 @@ ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounter // 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}; - // clang-format off - new (m_pResourceLayouts + s) - ShaderResourceLayoutD3D11 - { - *this, - pShaderD3D11->GetD3D11Resources(), - PSODesc.ResourceLayout, - VarTypes, - _countof(VarTypes), - m_pBoundResourceCaches[s], - ResCacheDataAllocator, - ResLayoutDataAllocator - }; - // clang-format on + new (m_pResourceLayouts + s) ShaderResourceLayoutD3D11{*this, m_pBoundResourceCaches[s]}; + 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); diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp index 28086285..3aaf82b7 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp @@ -148,61 +148,60 @@ void ShaderResourceCacheD3D11::Initialize(Uint32 CBCount, Uint32 SRVCount, Uint3 void ShaderResourceCacheD3D11::Destroy(IMemoryAllocator& MemAllocator) { - VERIFY(IsInitialized(), "Resource cache is not initialized"); + if (!IsInitialized()) + return; + VERIFY(m_pdbgMemoryAllocator == &MemAllocator, "The allocator does not match the one used to create resources"); - if (IsInitialized()) + // Explicitly destory all objects + auto CBCount = GetCBCount(); + if (CBCount != 0) { - // Explicitly destory all objects - auto CBCount = GetCBCount(); - if (CBCount != 0) - { - CachedCB* CBs = nullptr; - ID3D11Buffer** d3d11CBs = nullptr; - GetCBArrays(CBs, d3d11CBs); - for (size_t cb = 0; cb < CBCount; ++cb) - CBs[cb].~CachedCB(); - } + CachedCB* CBs = nullptr; + ID3D11Buffer** d3d11CBs = nullptr; + GetCBArrays(CBs, d3d11CBs); + 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; + GetSRVArrays(SRVResources, d3d11SRVs); + 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; + GetSamplerArrays(Samplers, d3d11Samplers); + 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; + GetUAVArrays(UAVResources, d3d11UAVs); + 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_MemoryEndOffset = InvalidResourceOffset; - if (m_pResourceData != nullptr) - MemAllocator.Free(m_pResourceData); - m_pResourceData = nullptr; - } + if (m_pResourceData != nullptr) + MemAllocator.Free(m_pResourceData); + m_pResourceData = nullptr; } ShaderResourceCacheD3D11::~ShaderResourceCacheD3D11() diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp index c1e6e65a..f7c1958d 100755 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp @@ -84,7 +84,7 @@ ShaderResourceLayoutD3D11::~ShaderResourceLayoutD3D11() size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources, const PipelineResourceLayoutDesc& ResourceLayout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes) + Uint32 NumAllowedTypes) noexcept { // Skip immutable samplers as they are initialized directly in the resource cache by the PSO constexpr bool CountImtblSamplers = false; @@ -101,20 +101,15 @@ size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D } -ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& Owner, - std::shared_ptr pSrcResources, - const PipelineResourceLayoutDesc& ResourceLayout, - const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes, - Uint32 NumVarTypes, - ShaderResourceCacheD3D11& ResourceCache, - IMemoryAllocator& ResCacheDataAllocator, - IMemoryAllocator& ResLayoutDataAllocator) : - // clang-format off - m_Owner {Owner}, - m_pResources {std::move(pSrcResources)}, - m_ResourceCache {ResourceCache} -// clang-format on +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); diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp index 31d95179..fa761fc7 100644 --- a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp @@ -133,11 +133,13 @@ private: }; template - LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& ShaderStages); + void InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector& ShaderStages); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, std::vector& ShaderStages); + void Destruct(); + CComPtr m_pd3d12PSO; RootSignature m_RootSig; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp index 1a0362ab..8a8f7b25 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp @@ -110,7 +110,7 @@ public: SRBResources }; - ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) + ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) noexcept // clang-format off #ifdef DILIGENT_DEBUG : m_DbgContentType diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp index 5426d98b..719345fc 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp @@ -112,21 +112,24 @@ namespace Diligent class ShaderResourceLayoutD3D12 final { public: - // There are two modes a layout can be constructed: + explicit ShaderResourceLayoutD3D12(IObject& Owner) noexcept : + m_Owner{Owner} + {} + + // There are two modes a layout can be initialized: // - initialize static resource layout and initialize shader resource cache to hold static resources // - initialize reference layouts that address all types of resources (static, mutable, dynamic). // Root indices and descriptor table offsets are assigned during the initialization; // no shader resource cache is provided - ShaderResourceLayoutD3D12(IObject& Owner, - ID3D12Device* pd3d12Device, - PIPELINE_TYPE PipelineType, - const PipelineResourceLayoutDesc& ResourceLayout, - std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - class RootSignature* pRootSig); + void Initialize(ID3D12Device* pd3d12Device, + PIPELINE_TYPE PipelineType, + const PipelineResourceLayoutDesc& ResourceLayout, + std::shared_ptr pSrcResources, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + class RootSignature* pRootSig); // clang-format off ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete; diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp index 213748d9..c30d8296 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp @@ -76,12 +76,16 @@ class ShaderVariableD3D12Impl; class ShaderVariableManagerD3D12 { public: - ShaderVariableManagerD3D12(IObject& Owner, - const ShaderResourceLayoutD3D12& Layout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12& ResourceCache); + ShaderVariableManagerD3D12(IObject& Owner, + ShaderResourceCacheD3D12& ResourceCache) noexcept : + m_Owner{Owner}, + m_ResourceCache{ResourceCache} + {} + + void Initialize(const ShaderResourceLayoutD3D12& Layout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes); ~ShaderVariableManagerD3D12(); void Destroy(IMemoryAllocator& Allocator); @@ -120,7 +124,7 @@ private: Uint32 m_NumVariables = 0; #ifdef DILIGENT_DEBUG - IMemoryAllocator& m_DbgAllocator; + IMemoryAllocator* m_pDbgAllocator = nullptr; #endif // clang-format on }; diff --git a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp index b65ad4fc..2d31e70d 100644 --- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp @@ -99,34 +99,47 @@ private: }; template -LinearAllocator PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, - std::vector& ShaderStages) +void PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& ShaderStages) { m_ResourceLayoutIndex.fill(-1); ExtractShaders(CreateInfo, ShaderStages); - // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddSpace(GetNumShaderStages() * 2); - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages * 2); + MemPool.AddSpace(NumShaderStages); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - m_RootSig.AllocateImmutableSamplers(CreateInfo.PSODesc.ResourceLayout); + m_pStaticResourceCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources); + + // The memory is now owned by PipelineStateD3D12Impl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_pStaticResourceCaches); + (void)Ptr; - m_pShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); - m_pStaticResourceCaches = MemPool.Allocate(GetNumShaderStages()); - m_pStaticVarManagers = MemPool.Allocate(GetNumShaderStages()); + m_pShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, std::ref(*this)); + + m_pStaticVarManagers = MemPool.Allocate(NumShaderStages); + for (Uint32 s = 0; s < NumShaderStages; ++s) + new (m_pStaticVarManagers + s) ShaderVariableManagerD3D12{*this, GetStaticShaderResCache(s)}; InitializePipelineDesc(CreateInfo, MemPool); - InitResourceLayouts(CreateInfo, ShaderStages); - return MemPool; + m_RootSig.AllocateImmutableSamplers(CreateInfo.PSODesc.ResourceLayout); + + // 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, ShaderStages); } @@ -136,197 +149,202 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector ShaderStages; - - auto MemPool = InitInternalObjects(CreateInfo, ShaderStages); - - auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); - if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) + try { - const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + std::vector ShaderStages; - D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; + InitInternalObjects(CreateInfo, ShaderStages); - for (const auto& Stage : ShaderStages) + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS) { - auto* pShaderD3D12 = Stage.pShader; - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; - VERIFY_EXPR(ShaderType == Stage.Type); + const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); + + D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {}; - D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; - switch (ShaderType) + for (const auto& Stage : ShaderStages) { - // clang-format off + auto* pShaderD3D12 = Stage.pShader; + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off case SHADER_TYPE_VERTEX: pd3d12ShaderBytecode = &d3d12PSODesc.VS; break; case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; case SHADER_TYPE_GEOMETRY: pd3d12ShaderBytecode = &d3d12PSODesc.GS; break; case SHADER_TYPE_HULL: pd3d12ShaderBytecode = &d3d12PSODesc.HS; break; case SHADER_TYPE_DOMAIN: pd3d12ShaderBytecode = &d3d12PSODesc.DS; break; - // clang-format on - default: UNEXPECTED("Unexpected shader type"); - } - auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); - pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); - pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); - } + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); + } - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); + memset(&d3d12PSODesc.StreamOutput, 0, sizeof(d3d12PSODesc.StreamOutput)); - BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); - // The sample mask for the blend state. - d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, d3d12PSODesc.BlendState); + // The sample mask for the blend state. + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; - RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); - DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, d3d12PSODesc.DepthStencilState); - std::vector> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); + std::vector> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector")); - const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout; - if (InputLayout.NumElements > 0) - { - LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); - d3d12PSODesc.InputLayout.NumElements = static_cast(d312InputElements.size()); - d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); - } - else - { - d3d12PSODesc.InputLayout.NumElements = 0; - d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; - } + const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout; + if (InputLayout.NumElements > 0) + { + LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements); + d3d12PSODesc.InputLayout.NumElements = static_cast(d312InputElements.size()); + d3d12PSODesc.InputLayout.pInputElementDescs = d312InputElements.data(); + } + else + { + d3d12PSODesc.InputLayout.NumElements = 0; + d3d12PSODesc.InputLayout.pInputElementDescs = nullptr; + } - d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; - static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; - d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; + d3d12PSODesc.IBStripCutValue = D3D12_INDEX_BUFFER_STRIP_CUT_VALUE_DISABLED; + static const PrimitiveTopology_To_D3D12_PRIMITIVE_TOPOLOGY_TYPE PrimTopologyToD3D12TopologyType; + d3d12PSODesc.PrimitiveTopologyType = PrimTopologyToD3D12TopologyType[GraphicsPipeline.PrimitiveTopology]; - d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; - for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) - d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormats); ++rt) - d3d12PSODesc.RTVFormats[rt] = DXGI_FORMAT_UNKNOWN; - d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + d3d12PSODesc.NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormats); ++rt) + d3d12PSODesc.RTVFormats[rt] = DXGI_FORMAT_UNKNOWN; + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); - d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; - d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; + d3d12PSODesc.SampleDesc.Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc.Quality = GraphicsPipeline.SmplDesc.Quality; - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); - } + HRESULT hr = pd3d12Device->CreateGraphicsPipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); + } #ifdef D3D12_H_HAS_MESH_SHADER - else if (m_Desc.PipelineType == PIPELINE_TYPE_MESH) - { - const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); - - struct MESH_SHADER_PIPELINE_STATE_DESC + else if (m_Desc.PipelineType == PIPELINE_TYPE_MESH) { - PSS_SubObject Flags; - PSS_SubObject NodeMask; - PSS_SubObject pRootSignature; - PSS_SubObject PS; - PSS_SubObject AS; - PSS_SubObject MS; - PSS_SubObject BlendState; - PSS_SubObject DepthStencilState; - PSS_SubObject RasterizerState; - PSS_SubObject SampleDesc; - PSS_SubObject SampleMask; - PSS_SubObject DSVFormat; - PSS_SubObject RTVFormatArray; - PSS_SubObject CachedPSO; - }; - MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; - - for (const auto& Stage : ShaderStages) - { - auto* pShaderD3D12 = Stage.pShader; - auto ShaderType = pShaderD3D12->GetDesc().ShaderType; - VERIFY_EXPR(ShaderType == Stage.Type); + const auto& GraphicsPipeline = GetGraphicsPipelineDesc(); - D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; - switch (ShaderType) + struct MESH_SHADER_PIPELINE_STATE_DESC { - // clang-format off + PSS_SubObject Flags; + PSS_SubObject NodeMask; + PSS_SubObject pRootSignature; + PSS_SubObject PS; + PSS_SubObject AS; + PSS_SubObject MS; + PSS_SubObject BlendState; + PSS_SubObject DepthStencilState; + PSS_SubObject RasterizerState; + PSS_SubObject SampleDesc; + PSS_SubObject SampleMask; + PSS_SubObject DSVFormat; + PSS_SubObject RTVFormatArray; + PSS_SubObject CachedPSO; + }; + MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {}; + + for (const auto& Stage : ShaderStages) + { + auto* pShaderD3D12 = Stage.pShader; + auto ShaderType = pShaderD3D12->GetDesc().ShaderType; + VERIFY_EXPR(ShaderType == Stage.Type); + + D3D12_SHADER_BYTECODE* pd3d12ShaderBytecode = nullptr; + switch (ShaderType) + { + // clang-format off case SHADER_TYPE_AMPLIFICATION: pd3d12ShaderBytecode = &d3d12PSODesc.AS; break; case SHADER_TYPE_MESH: pd3d12ShaderBytecode = &d3d12PSODesc.MS; break; case SHADER_TYPE_PIXEL: pd3d12ShaderBytecode = &d3d12PSODesc.PS; break; - // clang-format on - default: UNEXPECTED("Unexpected shader type"); - } - auto* pByteCode = pShaderD3D12->GetShaderByteCode(); + // clang-format on + default: UNEXPECTED("Unexpected shader type"); + } + auto* pByteCode = pShaderD3D12->GetShaderByteCode(); - pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); - pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); - } + pd3d12ShaderBytecode->pShaderBytecode = pByteCode->GetBufferPointer(); + pd3d12ShaderBytecode->BytecodeLength = pByteCode->GetBufferSize(); + } - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, *d3d12PSODesc.BlendState); - d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; + BlendStateDesc_To_D3D12_BLEND_DESC(GraphicsPipeline.BlendDesc, *d3d12PSODesc.BlendState); + d3d12PSODesc.SampleMask = GraphicsPipeline.SampleMask; - RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, *d3d12PSODesc.RasterizerState); - DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, *d3d12PSODesc.DepthStencilState); + RasterizerStateDesc_To_D3D12_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, *d3d12PSODesc.RasterizerState); + DepthStencilStateDesc_To_D3D12_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, *d3d12PSODesc.DepthStencilState); - d3d12PSODesc.RTVFormatArray->NumRenderTargets = GraphicsPipeline.NumRenderTargets; - for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) - d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); - for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormatArray->RTFormats); ++rt) - d3d12PSODesc.RTVFormatArray->RTFormats[rt] = DXGI_FORMAT_UNKNOWN; - d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); + d3d12PSODesc.RTVFormatArray->NumRenderTargets = GraphicsPipeline.NumRenderTargets; + for (Uint32 rt = 0; rt < GraphicsPipeline.NumRenderTargets; ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = TexFormatToDXGI_Format(GraphicsPipeline.RTVFormats[rt]); + for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(d3d12PSODesc.RTVFormatArray->RTFormats); ++rt) + d3d12PSODesc.RTVFormatArray->RTFormats[rt] = DXGI_FORMAT_UNKNOWN; + d3d12PSODesc.DSVFormat = TexFormatToDXGI_Format(GraphicsPipeline.DSVFormat); - d3d12PSODesc.SampleDesc->Count = GraphicsPipeline.SmplDesc.Count; - d3d12PSODesc.SampleDesc->Quality = GraphicsPipeline.SmplDesc.Quality; + d3d12PSODesc.SampleDesc->Count = GraphicsPipeline.SmplDesc.Count; + d3d12PSODesc.SampleDesc->Quality = GraphicsPipeline.SmplDesc.Quality; - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - d3d12PSODesc.CachedPSO->pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO->CachedBlobSizeInBytes = 0; + d3d12PSODesc.CachedPSO->pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO->CachedBlobSizeInBytes = 0; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - D3D12_PIPELINE_STATE_STREAM_DESC streamDesc; - streamDesc.SizeInBytes = sizeof(d3d12PSODesc); - streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; + D3D12_PIPELINE_STATE_STREAM_DESC streamDesc; + streamDesc.SizeInBytes = sizeof(d3d12PSODesc); + streamDesc.pPipelineStateSubobjectStream = &d3d12PSODesc; - auto* device2 = pDeviceD3D12->GetD3D12Device2(); + auto* device2 = pDeviceD3D12->GetD3D12Device2(); - CHECK_D3D_RESULT_THROW(device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)), "Failed to create pipeline state"); - } + CHECK_D3D_RESULT_THROW(device2->CreatePipelineState(&streamDesc, IID_PPV_ARGS(&m_pd3d12PSO)), "Failed to create pipeline state"); + } #endif // D3D12_H_HAS_MESH_SHADER - else - { - LOG_ERROR_AND_THROW("Unsupported pipeline type"); - } + else + { + LOG_ERROR_AND_THROW("Unsupported pipeline type"); + } - if (*m_Desc.Name != 0) + if (*m_Desc.Name != 0) + { + m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); + String RootSignatureDesc("Root signature for PSO '"); + RootSignatureDesc.append(m_Desc.Name); + RootSignatureDesc.push_back('\''); + m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + } + } + catch (...) { - m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); - String RootSignatureDesc("Root signature for PSO '"); - RootSignatureDesc.append(m_Desc.Name); - RootSignatureDesc.push_back('\''); - m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + Destruct(); + throw; } - - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pShaderResourceLayouts); } PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters, @@ -335,67 +353,92 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector ShaderStages; + try + { + std::vector ShaderStages; - auto MemPool = InitInternalObjects(CreateInfo, ShaderStages); + InitInternalObjects(CreateInfo, ShaderStages); - auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); + auto pd3d12Device = pDeviceD3D12->GetD3D12Device(); - D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; + D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {}; - VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); - auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); - d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); - d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); + VERIFY_EXPR(ShaderStages[0].Type == SHADER_TYPE_COMPUTE); + auto* pByteCode = ShaderStages[0].pShader->GetShaderByteCode(); + d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer(); + d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize(); - // For single GPU operation, set this to zero. If there are multiple GPU nodes, - // set bits to identify the nodes (the device's physical adapters) for which the - // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. - d3d12PSODesc.NodeMask = 0; + // For single GPU operation, set this to zero. If there are multiple GPU nodes, + // set bits to identify the nodes (the device's physical adapters) for which the + // graphics pipeline state is to apply. Each bit in the mask corresponds to a single node. + d3d12PSODesc.NodeMask = 0; - d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; - d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; + d3d12PSODesc.CachedPSO.pCachedBlob = nullptr; + d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0; - // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. - d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; + // The only valid bit is D3D12_PIPELINE_STATE_FLAG_TOOL_DEBUG, which can only be set on WARP devices. + d3d12PSODesc.Flags = D3D12_PIPELINE_STATE_FLAG_NONE; - d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); + d3d12PSODesc.pRootSignature = m_RootSig.GetD3D12RootSignature(); - HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); - if (FAILED(hr)) - LOG_ERROR_AND_THROW("Failed to create pipeline state"); + HRESULT hr = pd3d12Device->CreateComputePipelineState(&d3d12PSODesc, __uuidof(ID3D12PipelineState), reinterpret_cast(static_cast(&m_pd3d12PSO))); + if (FAILED(hr)) + LOG_ERROR_AND_THROW("Failed to create pipeline state"); - if (*m_Desc.Name != 0) + if (*m_Desc.Name != 0) + { + m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); + String RootSignatureDesc("Root signature for PSO '"); + RootSignatureDesc.append(m_Desc.Name); + RootSignatureDesc.push_back('\''); + m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + } + } + catch (...) { - m_pd3d12PSO->SetName(WidenString(m_Desc.Name).c_str()); - String RootSignatureDesc("Root signature for PSO '"); - RootSignatureDesc.append(m_Desc.Name); - RootSignatureDesc.push_back('\''); - m_RootSig.GetD3D12RootSignature()->SetName(WidenString(RootSignatureDesc).c_str()); + Destruct(); + throw; } - - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_pShaderResourceLayouts); } PipelineStateD3D12Impl::~PipelineStateD3D12Impl() +{ + Destruct(); +} + +void PipelineStateD3D12Impl::Destruct() { auto& ShaderResLayoutAllocator = GetRawAllocator(); for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { - m_pStaticVarManagers[s].Destroy(GetRawAllocator()); - m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); - m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); - m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); - m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12(); + if (m_pStaticVarManagers != nullptr) + { + m_pStaticVarManagers[s].Destroy(GetRawAllocator()); + m_pStaticVarManagers[s].~ShaderVariableManagerD3D12(); + } + + if (m_pShaderResourceLayouts != nullptr) + { + m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12(); + m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12(); + } + + if (m_pStaticResourceCaches != nullptr) + { + m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12(); + } + } + // All internal objects are allocated in contiguous chunks of memory. + if (auto* pRawMem = m_pStaticResourceCaches) + { + ShaderResLayoutAllocator.Free(pRawMem); } - // m_pShaderResourceLayouts, m_pStaticResourceCaches, and m_pShaderResourceLayouts are allocated in - // contiguous chunks of memory. - auto* pRawMem = m_pShaderResourceLayouts; - ShaderResLayoutAllocator.Free(pRawMem); - // D3D12 object can only be destroyed when it is no longer used by the GPU - m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask); + if (m_pd3d12PSO) + { + // D3D12 object can only be destroyed when it is no longer used by the GPU + m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask); + } } IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase) @@ -429,49 +472,37 @@ void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& m_ResourceLayoutIndex[ShaderInd] = static_cast(s); - new (m_pShaderResourceLayouts + s) - ShaderResourceLayoutD3D12 // - { - *this, - pd3d12Device, - m_Desc.PipelineType, - ResourceLayout, - pShaderD3D12->GetShaderResources(), - GetRawAllocator(), - nullptr, - 0, - nullptr, - &m_RootSig // - }; - - new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D12{ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources}; + m_pShaderResourceLayouts[s].Initialize( + pd3d12Device, + m_Desc.PipelineType, + ResourceLayout, + pShaderD3D12->GetShaderResources(), + GetRawAllocator(), + nullptr, + 0, + nullptr, + &m_RootSig // + ); const SHADER_RESOURCE_VARIABLE_TYPE StaticVarType[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC}; - new (m_pShaderResourceLayouts + GetNumShaderStages() + s) - ShaderResourceLayoutD3D12 // - { - *this, - pd3d12Device, - m_Desc.PipelineType, - ResourceLayout, - pShaderD3D12->GetShaderResources(), - GetRawAllocator(), - StaticVarType, - _countof(StaticVarType), - m_pStaticResourceCaches + s, - nullptr // - }; - - new (m_pStaticVarManagers + s) - ShaderVariableManagerD3D12 // - { - *this, - GetStaticShaderResLayout(static_cast(s)), - GetRawAllocator(), - nullptr, - 0, - GetStaticShaderResCache(static_cast(s)) // - }; + m_pShaderResourceLayouts[GetNumShaderStages() + s].Initialize( + pd3d12Device, + m_Desc.PipelineType, + ResourceLayout, + pShaderD3D12->GetShaderResources(), + GetRawAllocator(), + StaticVarType, + _countof(StaticVarType), + m_pStaticResourceCaches + s, + nullptr // + ); + + m_pStaticVarManagers[s].Initialize( + GetStaticShaderResLayout(static_cast(s)), + GetRawAllocator(), + nullptr, + 0 // + ); } m_RootSig.Finalize(pd3d12Device); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 3293283a..1c5ae5f5 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -67,16 +67,13 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; const auto& SrcLayout = pPSO->GetShaderResLayout(s); // Create shader variable manager in place - new (m_pShaderVarMgrs + s) - ShaderVariableManagerD3D12 // - { - *this, - SrcLayout, - VarDataAllocator, - AllowedVarTypes, - _countof(AllowedVarTypes), - m_ShaderResourceCache // - }; + new (m_pShaderVarMgrs + s) ShaderVariableManagerD3D12{*this, m_ShaderResourceCache}; + m_pShaderVarMgrs[s].Initialize( + SrcLayout, + VarDataAllocator, + AllowedVarTypes, + _countof(AllowedVarTypes) // + ); m_ResourceLayoutIndex[ShaderInd] = static_cast(s); } diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp index 06e902fb..c0428e7e 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp @@ -113,22 +113,19 @@ void ShaderResourceLayoutD3D12::AllocateMemory(IMemoryAllocator& // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Shader-Resource-Layouts-and-Root-Signature-in-a-Pipeline-State-Object // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Resource-Layouts-in-a-Pipeline-State -ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& Owner, - ID3D12Device* pd3d12Device, - PIPELINE_TYPE PipelineType, - const PipelineResourceLayoutDesc& ResourceLayout, - std::shared_ptr pSrcResources, - IMemoryAllocator& LayoutDataAllocator, - const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12* pResourceCache, - RootSignature* pRootSig) : - // clang-format off - m_Owner {Owner}, - m_pd3d12Device {pd3d12Device}, - m_pResources {std::move(pSrcResources)} -// clang-format on +void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device, + PIPELINE_TYPE PipelineType, + const PipelineResourceLayoutDesc& ResourceLayout, + std::shared_ptr pSrcResources, + IMemoryAllocator& LayoutDataAllocator, + const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes, + Uint32 NumAllowedTypes, + ShaderResourceCacheD3D12* pResourceCache, + RootSignature* pRootSig) { + m_pd3d12Device = pd3d12Device; + m_pResources = std::move(pSrcResources); + VERIFY_EXPR((pResourceCache != nullptr) ^ (pRootSig != nullptr)); const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp index f7c23096..fd58eacf 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp @@ -54,20 +54,15 @@ size_t ShaderVariableManagerD3D12::GetRequiredMemorySize(const ShaderResourceLay } // Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes -ShaderVariableManagerD3D12::ShaderVariableManagerD3D12(IObject& Owner, - const ShaderResourceLayoutD3D12& SrcLayout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheD3D12& ResourceCache) : - // clang-format off - m_Owner {Owner}, - m_ResourceCache {ResourceCache} +void ShaderVariableManagerD3D12::Initialize(const ShaderResourceLayoutD3D12& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes) +{ #ifdef DILIGENT_DEBUG - , m_DbgAllocator {Allocator} + m_pDbgAllocator = &Allocator; #endif -// clang-format on -{ + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); VERIFY_EXPR(m_NumVariables == 0); auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables); @@ -113,10 +108,10 @@ ShaderVariableManagerD3D12::~ShaderVariableManagerD3D12() void ShaderVariableManagerD3D12::Destroy(IMemoryAllocator& Allocator) { - VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor"); - if (m_pVariables != nullptr) { + VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + for (Uint32 v = 0; v < m_NumVariables; ++v) m_pVariables[v].~ShaderVariableD3D12Impl(); Allocator.Free(m_pVariables); diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp index f15d2e74..efbff703 100644 --- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp @@ -385,7 +385,7 @@ public: const ShaderResources* const pShaderResources[], Uint32 NumShaders, bool VerifyVariables, - bool VerifyImmutableSamplers); + bool VerifyImmutableSamplers) noexcept; #endif void GetShaderModel(Uint32& Major, Uint32& Minor) const diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp index 86a7fc35..b975b506 100644 --- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp +++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp @@ -219,7 +219,7 @@ void ShaderResources::DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& const ShaderResources* const pShaderResources[], Uint32 NumShaders, bool VerifyVariables, - bool VerifyImmutableSamplers) + bool VerifyImmutableSamplers) noexcept { auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) // { diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp index eab96f6a..07c8f39e 100644 --- a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp @@ -45,7 +45,7 @@ namespace Diligent class GLProgramResourceCache { public: - GLProgramResourceCache() + GLProgramResourceCache() noexcept {} ~GLProgramResourceCache(); diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp index 0c5692d0..93180774 100644 --- a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp +++ b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp @@ -114,6 +114,8 @@ private: void InitResourceLayouts(const std::vector& ShaderStages, LinearAllocator& MemPool); + void Destruct(); + // Linked GL programs for every shader stage. Every pipeline needs to have its own programs // because resource bindings assigned by GLProgramResources::LoadUniforms depend on other // shader stages. diff --git a/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp b/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp index 95557557..84cdc46e 100644 --- a/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp @@ -92,7 +92,9 @@ GLProgramResourceCache::~GLProgramResourceCache() void GLProgramResourceCache::Destroy(IMemoryAllocator& MemAllocator) { - VERIFY(IsInitialized(), "Resource cache is not initialized"); + if (!IsInitialized()) + return; + VERIFY(m_pdbgMemoryAllocator == &MemAllocator, "The allocator does not match the one used to create resources"); for (Uint32 cb = 0; cb < GetUBCount(); ++cb) diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp index 8bc3802e..8b429094 100644 --- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp @@ -40,22 +40,37 @@ namespace Diligent template void PipelineStateGLImpl::Initialize(const PSOCreateInfoType& CreateInfo, const std::vector& ShaderStages) { - // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; + VERIFY_EXPR(m_NumShaderStages > 0 && m_NumShaderStages == ShaderStages.size()); + if (!GetDevice()->GetDeviceCaps().Features.SeparablePrograms) + m_NumShaderStages = 1; - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + const auto NumPrograms = GetNumShaderStages(); + + MemPool.AddSpace(NumPrograms); + MemPool.AddSpace(NumPrograms); MemPool.AddSpace(m_Desc.ResourceLayout.NumImmutableSamplers); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - InitResourceLayouts(ShaderStages, MemPool); - InitializePipelineDesc(CreateInfo, MemPool); + m_GLPrograms = MemPool.ConstructArray(NumPrograms, false); - void* Ptr = MemPool.Release(); + // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); VERIFY_EXPR(Ptr == m_GLPrograms); + (void)Ptr; + + m_ProgramResources = MemPool.ConstructArray(NumPrograms); + + m_ImmutableSamplers = MemPool.ConstructArray(m_Desc.ResourceLayout.NumImmutableSamplers); + + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects + + InitResourceLayouts(ShaderStages, MemPool); + InitializePipelineDesc(CreateInfo, MemPool); } PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, @@ -74,26 +89,33 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* m_StaticResourceLayout{*this} // clang-format on { - std::vector ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); + try + { + std::vector ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); + + RefCntAutoPtr pTempPS; + if (CreateInfo.pPS == nullptr) + { + // Some OpenGL implementations fail if fragment shader is not present, so + // create a dummy one. + ShaderCreateInfo ShaderCI; + ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL; + ShaderCI.Source = "void main(){}"; + ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; + ShaderCI.Desc.Name = "Dummy fragment shader"; + pDeviceGL->CreateShader(ShaderCI, reinterpret_cast(static_cast(&pTempPS))); + + ShaderStages.emplace_back(SHADER_TYPE_PIXEL, pTempPS); + m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_PIXEL; + } - RefCntAutoPtr pTempPS; - if (CreateInfo.pPS == nullptr) + Initialize(CreateInfo, ShaderStages); + } + catch (...) { - // Some OpenGL implementations fail if fragment shader is not present, so - // create a dummy one. - ShaderCreateInfo ShaderCI; - ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL; - ShaderCI.Source = "void main(){}"; - ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL; - ShaderCI.Desc.Name = "Dummy fragment shader"; - pDeviceGL->CreateShader(ShaderCI, reinterpret_cast(static_cast(&pTempPS))); - - ShaderStages.emplace_back(SHADER_TYPE_PIXEL, pTempPS); - m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_PIXEL; + Destruct(); } - - Initialize(CreateInfo, ShaderStages); } PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters, @@ -112,30 +134,54 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* p m_StaticResourceLayout{*this} // clang-format on { - std::vector ShaderStages; - ExtractShaders(CreateInfo, ShaderStages); + try + { + std::vector ShaderStages; + ExtractShaders(CreateInfo, ShaderStages); - Initialize(CreateInfo, ShaderStages); + Initialize(CreateInfo, ShaderStages); + } + catch (...) + { + Destruct(); + } } PipelineStateGLImpl::~PipelineStateGLImpl() +{ + Destruct(); +} + +void PipelineStateGLImpl::Destruct() { auto& RawAllocator = GetRawAllocator(); m_StaticResourceCache.Destroy(RawAllocator); GetDevice()->OnDestroyPSO(this); - for (Uint32 i = 0; i < GetNumShaderStages(); ++i) + if (m_ImmutableSamplers != nullptr) { - m_GLPrograms[i].~GLProgramObj(); - m_ProgramResources[i].~GLProgramResources(); + for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumImmutableSamplers; ++i) + { + m_ImmutableSamplers[i].~SamplerPtr(); + } } - for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumImmutableSamplers; ++i) + + for (Uint32 i = 0; i < GetNumShaderStages(); ++i) { - m_ImmutableSamplers[i].~SamplerPtr(); + if (m_GLPrograms != nullptr) + { + m_GLPrograms[i].~GLProgramObj(); + } + if (m_ProgramResources != nullptr) + { + m_ProgramResources[i].~GLProgramResources(); + } } - void* pRawMem = m_GLPrograms; - RawAllocator.Free(pRawMem); + if (void* pRawMem = m_GLPrograms) + { + RawAllocator.Free(pRawMem); + } } IMPLEMENT_QUERY_INTERFACE(PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase) @@ -145,8 +191,8 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vectorGetDeviceCaps(); - VERIFY(DeviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized"); + const auto& deviceCaps = pDeviceGL->GetDeviceCaps(); + VERIFY(deviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized"); auto pImmediateCtx = m_pDevice->GetImmediateContext(); VERIFY_EXPR(pImmediateCtx); @@ -157,18 +203,16 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderStages.size()); - m_ProgramResources = MemPool.ConstructArray(ShaderStages.size()); for (size_t i = 0; i < ShaderStages.size(); ++i) { auto* pShaderGL = ShaderStages[i].pShader; const auto& ShaderDesc = pShaderGL->GetDesc(); - new (m_GLPrograms + i) GLProgramObj{ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)}; + m_GLPrograms[i] = GLProgramObj{ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)}; // Load uniforms and assign bindings m_ProgramResources[i].LoadUniforms(ShaderDesc.ShaderType, m_GLPrograms[i], GLState, m_TotalUniformBufferBindings, @@ -191,8 +235,7 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(ShaderStages.size()), false)); - m_ProgramResources = MemPool.Construct(); + m_GLPrograms[0] = ShaderGLImpl::LinkProgram(Shaders.data(), static_cast(Shaders.size()), false); m_ProgramResources[0].LoadUniforms(ActiveStages, m_GLPrograms[0], GLState, m_TotalUniformBufferBindings, @@ -204,10 +247,9 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr); + m_ResourceLayout.Initialize(m_ProgramResources, GetNumShaderStages(), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr); } - m_ImmutableSamplers = MemPool.ConstructArray(m_Desc.ResourceLayout.NumImmutableSamplers); for (Uint32 s = 0; s < m_Desc.ResourceLayout.NumImmutableSamplers; ++s) { pDeviceGL->CreateSampler(m_Desc.ResourceLayout.ImmutableSamplers[s].Desc, &m_ImmutableSamplers[s]); @@ -216,7 +258,7 @@ void PipelineStateGLImpl::InitResourceLayouts(const std::vector(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache); + m_StaticResourceLayout.Initialize(m_ProgramResources, GetNumShaderStages(), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache); InitImmutableSamplersInResourceCache(m_StaticResourceLayout, m_StaticResourceCache); } } diff --git a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp index 96b34008..d4f2fc36 100644 --- a/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp @@ -129,13 +129,15 @@ private: using TShaderStages = ShaderResourceLayoutVk::TShaderStages; template - LinearAllocator InitInternalObjects(const PSOCreateInfoType& CreateInfo, - std::vector& vkShaderStages, - std::vector& ShaderModules); + void InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& vkShaderStages, + std::vector& ShaderModules); void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo, TShaderStages& ShaderStages); + void Destruct(); + const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const { VERIFY_EXPR(ShaderInd < GetNumShaderStages()); @@ -148,7 +150,7 @@ private: return m_StaticResCaches[ShaderInd]; } - ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const + const ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const { VERIFY_EXPR(ShaderInd < GetNumShaderStages()); return m_StaticVarsMgrs[ShaderInd]; diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp index a5278cb7..7d77ff48 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp @@ -75,7 +75,7 @@ public: }; // clang-format off - ShaderResourceCacheVk(DbgCacheContentType dbgContentType) + ShaderResourceCacheVk(DbgCacheContentType dbgContentType) noexcept #ifdef DILIGENT_DEBUG : m_DbgContentType{dbgContentType} #endif diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp index 0013fe23..9452a390 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp @@ -128,7 +128,7 @@ public: }; using TShaderStages = std::vector; - ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) : + ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) noexcept : m_LogicalDevice{LogicalDevice} { } diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp index 9039e04e..27689c1e 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp @@ -73,21 +73,25 @@ class ShaderVariableVkImpl; class ShaderVariableManagerVk { public: - ShaderVariableManagerVk(IObject& Owner, - const ShaderResourceLayoutVk& SrcLayout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheVk& ResourceCache); + ShaderVariableManagerVk(IObject& Owner, + ShaderResourceCacheVk& ResourceCache) noexcept : + m_Owner{Owner}, + m_ResourceCache{ResourceCache} + {} + + void Initialize(const ShaderResourceLayoutVk& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes); ~ShaderVariableManagerVk(); void DestroyVariables(IMemoryAllocator& Allocator); - ShaderVariableVkImpl* GetVariable(const Char* Name); - ShaderVariableVkImpl* GetVariable(Uint32 Index); + ShaderVariableVkImpl* GetVariable(const Char* Name) const; + ShaderVariableVkImpl* GetVariable(Uint32 Index) const; - void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags); + void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const; static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout, const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, @@ -115,7 +119,7 @@ private: Uint32 m_NumVariables = 0; #ifdef DILIGENT_DEBUG - IMemoryAllocator& m_DbgAllocator; + IMemoryAllocator* m_pDbgAllocator = nullptr; #endif }; diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp index 6cbe5da9..83512870 100644 --- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp @@ -413,15 +413,12 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre const auto ShaderType = StageInfo.Type; const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType); - new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice}; - m_ResourceLayoutIndex[ShaderTypeInd] = static_cast(s); - auto* pStaticResLayout = new (m_ShaderResourceLayouts + ShaderStages.size() + s) ShaderResourceLayoutVk{LogicalDevice}; - auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources}; - pStaticResLayout->InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); + auto& StaticResLayout = m_ShaderResourceLayouts[GetNumShaderStages() + s]; + StaticResLayout.InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]); - new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache}; + m_StaticVarsMgrs[s].Initialize(StaticResLayout, GetRawAllocator(), nullptr, 0); } ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(), m_Desc.ResourceLayout, m_PipelineLayout, @@ -464,37 +461,52 @@ void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& Cre } template -LinearAllocator PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, - std::vector& vkShaderStages, - std::vector& ShaderModules) +void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo, + std::vector& vkShaderStages, + std::vector& ShaderModules) { m_ResourceLayoutIndex.fill(-1); TShaderStages ShaderStages; ExtractShaders(CreateInfo, ShaderStages); - // Memory must be released if an exception is thrown. LinearAllocator MemPool{GetRawAllocator()}; - MemPool.AddSpace(GetNumShaderStages() * 2); - MemPool.AddSpace(GetNumShaderStages()); - MemPool.AddSpace(GetNumShaderStages()); + const auto NumShaderStages = GetNumShaderStages(); + VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size()); + + MemPool.AddSpace(NumShaderStages); + MemPool.AddSpace(NumShaderStages * 2); + MemPool.AddSpace(NumShaderStages); ReserveSpaceForPipelineDesc(CreateInfo, MemPool); MemPool.Reserve(); - m_ShaderResourceLayouts = MemPool.Allocate(GetNumShaderStages() * 2); - m_StaticResCaches = MemPool.Allocate(GetNumShaderStages()); - m_StaticVarsMgrs = MemPool.Allocate(GetNumShaderStages()); + const auto& LogicalDevice = GetDevice()->GetLogicalDevice(); + + m_StaticResCaches = MemPool.ConstructArray(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources); + + // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_StaticResCaches); + (void)Ptr; + + m_ShaderResourceLayouts = MemPool.ConstructArray(NumShaderStages * 2, LogicalDevice); + + m_StaticVarsMgrs = MemPool.Allocate(NumShaderStages); + for (Uint32 s = 0; s < NumShaderStages; ++s) + new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]}; 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, ShaderStages); // Create shader modules and initialize shader stages InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages); - - return MemPool; } PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters, @@ -503,15 +515,20 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector vkShaderStages; - std::vector ShaderModules; - - auto MemPool = InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + try + { + std::vector vkShaderStages; + std::vector ShaderModules; - CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); + CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass); + } + catch (...) + { + Destruct(); + throw; + } } @@ -521,39 +538,59 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* p TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc}, m_SRBMemAllocator{GetRawAllocator()} { - std::vector vkShaderStages; - std::vector ShaderModules; - - auto MemPool = InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); + try + { + std::vector vkShaderStages; + std::vector ShaderModules; - CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); + InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules); - void* Ptr = MemPool.Release(); - VERIFY_EXPR(Ptr == m_ShaderResourceLayouts); + CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline); + } + catch (...) + { + Destruct(); + throw; + } } PipelineStateVkImpl::~PipelineStateVkImpl() +{ + Destruct(); +} + +void PipelineStateVkImpl::Destruct() { m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask); m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask); auto& RawAllocator = GetRawAllocator(); - for (Uint32 s = 0; s < GetNumShaderStages() * 2; ++s) + for (Uint32 s = 0; s < GetNumShaderStages(); ++s) { - m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); + if (m_StaticVarsMgrs != nullptr) + { + m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); + m_StaticVarsMgrs[s].~ShaderVariableManagerVk(); + } + + if (m_ShaderResourceLayouts != nullptr) + { + m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk(); + m_ShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutVk(); + } + + if (m_StaticResCaches != nullptr) + { + m_StaticResCaches[s].~ShaderResourceCacheVk(); + } } - for (Uint32 s = 0; s < GetNumShaderStages(); ++s) + // All internal objects are allocted in contiguous chunks of memory. + if (void* pRawMem = m_StaticResCaches) { - m_StaticResCaches[s].~ShaderResourceCacheVk(); - m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator()); - m_StaticVarsMgrs[s].~ShaderVariableManagerVk(); + RawAllocator.Free(pRawMem); } - // m_ShaderResourceLayouts, m_StaticResCaches and m_StaticVarsMgrs are allocted in - // contiguous chunks of memory. - void* pRawMem = m_ShaderResourceLayouts; - RawAllocator.Free(pRawMem); } IMPLEMENT_QUERY_INTERFACE(PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase) @@ -746,7 +783,7 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY if (LayoutInd < 0) return nullptr; - auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); + const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd); return StaticVarMgr.GetVariable(Index); } diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 91008811..21b216db 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -75,7 +75,8 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR // Initialize vars manager to reference mutable and dynamic variables // Note that the cache has space for all variable types const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; - new (m_pShaderVarMgrs + s) ShaderVariableManagerVk{*this, SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes), m_ShaderResourceCache}; + new (m_pShaderVarMgrs + s) ShaderVariableManagerVk{*this, m_ShaderResourceCache}; + m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes)); } #ifdef DILIGENT_DEBUG m_ShaderResourceCache.DbgVerifyResourceInitialization(); diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp index 82d26b44..7e06bd69 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp @@ -65,20 +65,15 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayout } // Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes -ShaderVariableManagerVk::ShaderVariableManagerVk(IObject& Owner, - const ShaderResourceLayoutVk& SrcLayout, - IMemoryAllocator& Allocator, - const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, - Uint32 NumAllowedTypes, - ShaderResourceCacheVk& ResourceCache) : - // clang-format off - m_Owner {Owner }, - m_ResourceCache{ResourceCache} +void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout, + IMemoryAllocator& Allocator, + const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes, + Uint32 NumAllowedTypes) +{ #ifdef DILIGENT_DEBUG - , m_DbgAllocator {Allocator} + m_pDbgAllocator = &Allocator; #endif -// clang-format on -{ + const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes); VERIFY_EXPR(m_NumVariables == 0); auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables); @@ -119,10 +114,10 @@ ShaderVariableManagerVk::~ShaderVariableManagerVk() void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator) { - VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor"); - if (m_pVariables != nullptr) { + VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor"); + for (Uint32 v = 0; v < m_NumVariables; ++v) m_pVariables[v].~ShaderVariableVkImpl(); Allocator.Free(m_pVariables); @@ -130,7 +125,7 @@ void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator) } } -ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) +ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) const { ShaderVariableVkImpl* pVar = nullptr; for (Uint32 v = 0; v < m_NumVariables; ++v) @@ -147,7 +142,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) } -ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index) +ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index) const { if (Index >= m_NumVariables) { @@ -178,7 +173,7 @@ Uint32 ShaderVariableManagerVk::GetVariableIndex(const ShaderVariableVkImpl& Var } } -void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) +void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const { if (!pResourceMapping) { -- cgit v1.2.3 From 0c7e8e2efc95362cbc0998558bb41789a3943037 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 20 Oct 2020 14:06:33 -0700 Subject: Improved exception safety of SRB object creation --- .../include/ShaderResourceBindingD3D11Impl.hpp | 2 + .../src/ShaderResourceBindingD3D11Impl.cpp | 134 +++++++++++++-------- .../include/ShaderResourceBindingD3D12Impl.hpp | 2 + .../src/ShaderResourceBindingD3D12Impl.cpp | 88 +++++++++----- .../include/ShaderResourceBindingVkImpl.hpp | 2 + .../src/ShaderResourceBindingVkImpl.cpp | 88 +++++++++----- 6 files changed, 206 insertions(+), 110 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp index eb97dfdc..21437e0f 100644 --- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp +++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp @@ -100,6 +100,8 @@ public: } 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; diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp index f7ce059b..46833c81 100644 --- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp @@ -31,6 +31,7 @@ #include "DeviceContextD3D11Impl.hpp" #include "RenderDeviceD3D11Impl.hpp" #include "ShaderD3D11Impl.hpp" +#include "LinearAllocator.hpp" namespace Diligent { @@ -49,69 +50,104 @@ ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounter m_bIsStaticResourcesBound{false} // clang-format on { - m_ResourceLayoutIndex.fill(-1); - m_NumActiveShaders = static_cast(pPSO->GetNumShaderStages()); + try + { + m_ResourceLayoutIndex.fill(-1); + m_NumActiveShaders = static_cast(pPSO->GetNumShaderStages()); - // clang-format off - m_pResourceLayouts = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11", ShaderResourceLayoutD3D11, m_NumActiveShaders); - m_pBoundResourceCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheD3D11", ShaderResourceCacheD3D11, m_NumActiveShaders); - // clang-format on + LinearAllocator 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; - const auto& PSODesc = pPSO->GetDesc(); + m_pResourceLayouts = MemPool.Allocate(m_NumActiveShaders); + for (Uint8 s = 0; s < m_NumActiveShaders; ++s) + new (m_pResourceLayouts + s) ShaderResourceLayoutD3D11{*this, m_pBoundResourceCaches[s]}; // noexcept - // Reserve memory for resource layouts - for (Uint8 s = 0; s < m_NumActiveShaders; ++s) + // 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 (...) { - 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(); - new (m_pBoundResourceCaches + s) ShaderResourceCacheD3D11; - 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}; - new (m_pResourceLayouts + s) ShaderResourceLayoutD3D11{*this, m_pBoundResourceCaches[s]}; - 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; + Destruct(); + throw; } } ShaderResourceBindingD3D11Impl::~ShaderResourceBindingD3D11Impl() { - auto* pPSOD3D11Impl = ValidatedCast(m_pPSO); - for (Uint32 s = 0; s < m_NumActiveShaders; ++s) + 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& Allocator = pPSOD3D11Impl->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(s); - m_pBoundResourceCaches[s].Destroy(Allocator); - m_pBoundResourceCaches[s].~ShaderResourceCacheD3D11(); + 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(); + } } - GetRawAllocator().Free(m_pBoundResourceCaches); - for (Int32 l = 0; l < m_NumActiveShaders; ++l) + if (void* pRawMem = m_pBoundResourceCaches) { - m_pResourceLayouts[l].~ShaderResourceLayoutD3D11(); + GetRawAllocator().Free(pRawMem); } - GetRawAllocator().Free(m_pResourceLayouts); } IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingD3D11Impl, IID_ShaderResourceBindingD3D11, TBase) diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp index 846cb329..7be3372d 100644 --- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp +++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp @@ -78,6 +78,8 @@ public: } private: + void Destruct(); + ShaderResourceCacheD3D12 m_ShaderResourceCache; ShaderVariableManagerD3D12* m_pShaderVarMgrs = nullptr; diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp index 1c5ae5f5..1511bd01 100644 --- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp @@ -30,6 +30,7 @@ #include "PipelineStateD3D12Impl.hpp" #include "ShaderD3D12Impl.hpp" #include "RenderDeviceD3D12Impl.hpp" +#include "LinearAllocator.hpp" namespace Diligent { @@ -48,48 +49,73 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter m_NumShaders {static_cast(pPSO->GetNumShaderStages())} // clang-format on { - m_ResourceLayoutIndex.fill(-1); + try + { + m_ResourceLayoutIndex.fill(-1); + + LinearAllocator MemPool{GetRawAllocator()}; + MemPool.AddSpace(m_NumShaders); + MemPool.Reserve(); + m_pShaderVarMgrs = MemPool.ConstructArray(m_NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache)); - auto* pRenderDeviceD3D12Impl = ValidatedCast(pPSO->GetDevice()); - auto& ResCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); - pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, ResCacheDataAllocator); + // The memory is now owned by ShaderResourceBindingD3D12Impl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_pShaderVarMgrs); + (void)Ptr; - m_pShaderVarMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerD3D12", ShaderVariableManagerD3D12, m_NumShaders); + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects - for (Uint32 s = 0; s < m_NumShaders; ++s) + auto* pRenderDeviceD3D12Impl = ValidatedCast(pPSO->GetDevice()); + auto& ResCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); + pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, ResCacheDataAllocator); + + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + const auto ShaderType = pPSO->GetShaderStageType(s); + const auto& SrcLayout = pPSO->GetShaderResLayout(s); + const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType); + + auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + + // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object + const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; + m_pShaderVarMgrs[s].Initialize( + SrcLayout, + VarDataAllocator, + AllowedVarTypes, + _countof(AllowedVarTypes) // + ); + + m_ResourceLayoutIndex[ShaderInd] = static_cast(s); + } + } + catch (...) { - auto ShaderType = pPSO->GetShaderStageType(s); - auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType); - - auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); - - // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object - const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; - const auto& SrcLayout = pPSO->GetShaderResLayout(s); - // Create shader variable manager in place - new (m_pShaderVarMgrs + s) ShaderVariableManagerD3D12{*this, m_ShaderResourceCache}; - m_pShaderVarMgrs[s].Initialize( - SrcLayout, - VarDataAllocator, - AllowedVarTypes, - _countof(AllowedVarTypes) // - ); - - m_ResourceLayoutIndex[ShaderInd] = static_cast(s); + Destruct(); + throw; } } + ShaderResourceBindingD3D12Impl::~ShaderResourceBindingD3D12Impl() { - auto* pPSO = ValidatedCast(m_pPSO); - for (Uint32 s = 0; s < m_NumShaders; ++s) + Destruct(); +} + +void ShaderResourceBindingD3D12Impl::Destruct() +{ + if (m_pShaderVarMgrs != nullptr) { - auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); - m_pShaderVarMgrs[s].Destroy(VarDataAllocator); - m_pShaderVarMgrs[s].~ShaderVariableManagerD3D12(); + auto& SRBMemAllocator = m_pPSO->GetSRBMemoryAllocator(); + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s); + m_pShaderVarMgrs[s].Destroy(VarDataAllocator); + m_pShaderVarMgrs[s].~ShaderVariableManagerD3D12(); + } + GetRawAllocator().Free(m_pShaderVarMgrs); } - - GetRawAllocator().Free(m_pShaderVarMgrs); } IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingD3D12Impl, IID_ShaderResourceBindingD3D12, TBase) diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp index 026bb9da..00f2c33a 100644 --- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp +++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp @@ -76,6 +76,8 @@ public: bool StaticResourcesInitialized() const { return m_bStaticResourcesInitialized; } private: + void Destruct(); + ShaderResourceCacheVk m_ShaderResourceCache; ShaderVariableManagerVk* m_pShaderVarMgrs = nullptr; diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp index 21b216db..3e4a65cf 100644 --- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp @@ -30,6 +30,7 @@ #include "PipelineStateVkImpl.hpp" #include "ShaderVkImpl.hpp" #include "RenderDeviceVkImpl.hpp" +#include "LinearAllocator.hpp" namespace Diligent { @@ -47,52 +48,79 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR m_ShaderResourceCache{ShaderResourceCacheVk::DbgCacheContentType::SRBResources} // clang-format on { - m_ResourceLayoutIndex.fill(-1); + try + { + m_ResourceLayoutIndex.fill(-1); - m_NumShaders = static_cast(pPSO->GetNumShaderStages()); + m_NumShaders = static_cast(pPSO->GetNumShaderStages()); - auto* pRenderDeviceVkImpl = pPSO->GetDevice(); - // This will only allocate memory and initialize descriptor sets in the resource cache - // Resources will be initialized by InitializeResourceMemoryInCache() - auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); - pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name); + LinearAllocator MemPool{GetRawAllocator()}; + MemPool.AddSpace(m_NumShaders); + MemPool.Reserve(); + m_pShaderVarMgrs = MemPool.ConstructArray(m_NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache)); - m_pShaderVarMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders); + // The memory is now owned by ShaderResourceBindingVkImpl and will be freed by Destruct(). + auto* Ptr = MemPool.ReleaseOwnership(); + VERIFY_EXPR(Ptr == m_pShaderVarMgrs); + (void)Ptr; - for (Uint32 s = 0; s < m_NumShaders; ++s) - { - auto ShaderInd = GetShaderTypePipelineIndex(pPSO->GetShaderStageType(s), pPSO->GetDesc().PipelineType); + // It is important to construct all objects before initializing them because if an exception is thrown, + // destructors will be called for all objects - m_ResourceLayoutIndex[ShaderInd] = static_cast(s); + auto* pRenderDeviceVkImpl = pPSO->GetDevice(); + // This will only allocate memory and initialize descriptor sets in the resource cache + // Resources will be initialized by InitializeResourceMemoryInCache() + auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0); + pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name); - auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + auto ShaderInd = GetShaderTypePipelineIndex(pPSO->GetShaderStageType(s), pPSO->GetDesc().PipelineType); - const auto& SrcLayout = pPSO->GetShaderResLayout(s); - // Use source layout to initialize resource memory in the cache - SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache); + m_ResourceLayoutIndex[ShaderInd] = static_cast(s); - // Create shader variable manager in place - // Initialize vars manager to reference mutable and dynamic variables - // Note that the cache has space for all variable types - const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; - new (m_pShaderVarMgrs + s) ShaderVariableManagerVk{*this, m_ShaderResourceCache}; - m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes)); - } + auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); + + const auto& SrcLayout = pPSO->GetShaderResLayout(s); + // Use source layout to initialize resource memory in the cache + SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache); + + // Create shader variable manager in place + // Initialize vars manager to reference mutable and dynamic variables + // Note that the cache has space for all variable types + const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC}; + m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes)); + } #ifdef DILIGENT_DEBUG - m_ShaderResourceCache.DbgVerifyResourceInitialization(); + m_ShaderResourceCache.DbgVerifyResourceInitialization(); #endif + } + catch (...) + { + Destruct(); + throw; + } } ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl() { - for (Uint32 s = 0; s < m_NumShaders; ++s) + Destruct(); +} + +void ShaderResourceBindingVkImpl::Destruct() +{ + if (m_pShaderVarMgrs != nullptr) { - auto& VarDataAllocator = m_pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s); - m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator); - m_pShaderVarMgrs[s].~ShaderVariableManagerVk(); - } + auto& SRBMemAllocator = m_pPSO->GetSRBMemoryAllocator(); + for (Uint32 s = 0; s < m_NumShaders; ++s) + { + auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s); + m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator); + m_pShaderVarMgrs[s].~ShaderVariableManagerVk(); + } - GetRawAllocator().Free(m_pShaderVarMgrs); + GetRawAllocator().Free(m_pShaderVarMgrs); + } } IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingVkImpl, IID_ShaderResourceBindingVk, TBase) -- cgit v1.2.3 From b9d1a84943f61d1b48ffb1847cd0b3f7b8c60fb2 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 20 Oct 2020 18:05:02 -0700 Subject: Added ShaderResourceQueries device feature and EngineGLCreateInfo::ForceNonSeparablePrograms parameter (API 240078) --- Graphics/GraphicsEngine/interface/APIInfo.h | 2 +- Graphics/GraphicsEngine/interface/GraphicsTypes.h | 19 ++++++++++++++++++- .../GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp | 2 +- .../GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp | 2 +- .../include/RenderDeviceD3DBase.hpp | 1 + .../GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp | 8 +++++--- Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp | 2 +- .../GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp | 3 ++- 8 files changed, 30 insertions(+), 9 deletions(-) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h index 327f54c7..0ecbd92b 100644 --- a/Graphics/GraphicsEngine/interface/APIInfo.h +++ b/Graphics/GraphicsEngine/interface/APIInfo.h @@ -30,7 +30,7 @@ /// \file /// Diligent API information -#define DILIGENT_API_VERSION 240077 +#define DILIGENT_API_VERSION 240078 #include "../../../Primitives/interface/BasicTypes.h" diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h index 0f6b4b82..b05519c5 100644 --- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h +++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h @@ -1515,6 +1515,17 @@ struct DeviceFeatures /// Indicates if device supports separable programs DEVICE_FEATURE_STATE SeparablePrograms DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + /// Indicates if device supports resource queries from shader objects. + + /// \ note This feature indicates if IShader::GetResourceCount() and IShader::GetResourceDesc() methods + /// can be used to query the list of resources of individual shader objects. + /// Shader variable queries from pipeline state and shader resource binding objects are always + /// available. + /// + /// The feature is always enabled in Direct3D11, Direct3D12 and Vulkan. It is enabled in + /// OpenGL when separable programs are available, and it is always disabled in Metal. + DEVICE_FEATURE_STATE ShaderResourceQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); + /// Indicates if device supports indirect draw commands DEVICE_FEATURE_STATE IndirectRendering DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED); @@ -1616,6 +1627,7 @@ struct DeviceFeatures explicit DeviceFeatures(DEVICE_FEATURE_STATE State) noexcept : SeparablePrograms {State}, + ShaderResourceQueries {State}, IndirectRendering {State}, WireframeFill {State}, MultithreadedResourceCreation {State}, @@ -1647,7 +1659,7 @@ struct DeviceFeatures UniformBuffer8BitAccess {State} { # if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(*this) == 30, "Did you add a new feature to DeviceFeatures? Please handle its status above."); + static_assert(sizeof(*this) == 31, "Did you add a new feature to DeviceFeatures? Please handle its status above."); # endif } #endif @@ -1875,6 +1887,11 @@ struct EngineGLCreateInfo DILIGENT_DERIVE(EngineCreateInfo) /// provide additional runtime checking, validation, and logging /// functionality while possibly incurring performance penalties bool CreateDebugContext DEFAULT_INITIALIZER(false); + + /// Force using non-separable programs. + + /// Setting this to true is typically needed for testing purposes only. + bool ForceNonSeparablePrograms DEFAULT_INITIALIZER(false); }; typedef struct EngineGLCreateInfo EngineGLCreateInfo; diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp index 94847a51..8d45e547 100644 --- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp +++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp @@ -176,7 +176,7 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo #undef UNSUPPORTED_FEATURE #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 30, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif auto& TexCaps = m_DeviceCaps.TexCaps; diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp index ba91f7bc..377eb5a7 100644 --- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp +++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp @@ -297,7 +297,7 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo #undef CHECK_REQUIRED_FEATURE #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 30, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif auto& TexCaps = m_DeviceCaps.TexCaps; diff --git a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp index 104533c9..ea4a43bb 100644 --- a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp +++ b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp @@ -160,6 +160,7 @@ public: auto& Features = this->m_DeviceCaps.Features; Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; + Features.ShaderResourceQueries = DEVICE_FEATURE_STATE_ENABLED; Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED; Features.WireframeFill = DEVICE_FEATURE_STATE_ENABLED; Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_ENABLED; diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index 7911fa47..919d5aef 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -336,7 +336,8 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, const bool IsGL42OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 2); const bool IsGL41OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 1); - Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; + SET_FEATURE_STATE(SeparablePrograms, !InitAttribs.ForceNonSeparablePrograms, "Separable programs are"); + SET_FEATURE_STATE(ShaderResourceQueries, Features.SeparablePrograms != DEVICE_FEATURE_STATE_DISABLED, "Shader resource queries are"); Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED; Features.WireframeFill = DEVICE_FEATURE_STATE_ENABLED; // clang-format off @@ -395,7 +396,8 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, bool IsGLES32OrAbove = (MajorVersion >= 4) || (MajorVersion == 3 && MinorVersion >= 2); // clang-format off - SET_FEATURE_STATE(SeparablePrograms, IsGLES31OrAbove || strstr(Extensions, "separate_shader_objects"), "Separable programs are"); + SET_FEATURE_STATE(SeparablePrograms, (IsGLES31OrAbove || strstr(Extensions, "separate_shader_objects")) && !InitAttribs.ForceNonSeparablePrograms, "Separable programs are"); + SET_FEATURE_STATE(ShaderResourceQueries, Features.SeparablePrograms != DEVICE_FEATURE_STATE_DISABLED, "Shader resource queries are"); SET_FEATURE_STATE(IndirectRendering, IsGLES31OrAbove || strstr(Extensions, "draw_indirect"), "Indirect rendering is"); SET_FEATURE_STATE(WireframeFill, false, "Wireframe fill is"); SET_FEATURE_STATE(MultithreadedResourceCreation, false, "Multithreaded resource creation is"); @@ -456,7 +458,7 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, #undef SET_FEATURE_STATE #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 30, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif } diff --git a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp index 81d6753c..cbe1779f 100644 --- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp +++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp @@ -389,7 +389,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 30, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); + static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here."); #endif DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data(); diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp index 1441569e..ccfb74ac 100644 --- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp +++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp @@ -213,6 +213,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* // The following features are always enabled Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED; + Features.ShaderResourceQueries = DEVICE_FEATURE_STATE_ENABLED; Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED; Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_ENABLED; Features.ComputeShaders = DEVICE_FEATURE_STATE_ENABLED; @@ -222,7 +223,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters* Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED; #if defined(_MSC_VER) && defined(_WIN64) - static_assert(sizeof(DeviceFeatures) == 30, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary)."); + static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary)."); #endif const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits; -- cgit v1.2.3 From 1a36d301e62781a806a0bced72adf711382ea776 Mon Sep 17 00:00:00 2001 From: assiduous Date: Tue, 20 Oct 2020 18:18:43 -0700 Subject: GL backend: added info message about forcing non-separable programs --- Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'Graphics') diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp index 919d5aef..5aae4d90 100644 --- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp +++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp @@ -329,6 +329,9 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters, SET_FEATURE_STATE(WireframeFill, WireframeFillSupported, "Wireframe fill is"); } + if (InitAttribs.ForceNonSeparablePrograms) + LOG_INFO_MESSAGE("Forcing non-separable shader programs"); + if (m_DeviceCaps.DevType == RENDER_DEVICE_TYPE_GL) { const bool IsGL46OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 6); -- cgit v1.2.3