summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-15 17:55:38 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-15 17:59:25 +0000
commit259a9d5897937dcaaca1b4b294bb8d5250371e76 (patch)
treeb6123b30f228d05a7086a009cb35e2af713ed008 /Graphics
parentA number of corrections for PSO refactoring (diff)
downloadDiligentCore-259a9d5897937dcaaca1b4b294bb8d5250371e76.tar.gz
DiligentCore-259a9d5897937dcaaca1b4b294bb8d5250371e76.zip
Added GraphicsPipelineCreateInfo and ComputePipelineCreateInfo instead of single PipelineCreateInfo.
Some optimizations for dynamic memory allocations in PipelineState.
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp2
-rw-r--r--Graphics/GraphicsEngine/include/PipelineStateBase.hpp439
-rw-r--r--Graphics/GraphicsEngine/interface/InputLayout.h2
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h89
-rw-r--r--Graphics/GraphicsEngine/interface/RenderDevice.h49
-rw-r--r--Graphics/GraphicsEngine/src/APIInfo.cpp1
-rw-r--r--Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp17
-rw-r--r--Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp10
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp10
-rw-r--r--Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp229
-rw-r--r--Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp13
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp24
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp7
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp65
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp575
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp13
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp35
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp20
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp140
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp25
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp17
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp14
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp7
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp68
-rw-r--r--Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp12
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp147
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp16
29 files changed, 1198 insertions, 856 deletions
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<BaseInterface, ImplementationTraits>::
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<ShaderResourceVariableDesc*>(this->m_Desc.ResourceLayout.Variables));
- if (this->m_Desc.ResourceLayout.StaticSamplers != nullptr)
- RawAllocator.Free(const_cast<StaticSamplerDesc*>(this->m_Desc.ResourceLayout.StaticSamplers));
- if (this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements != nullptr)
- RawAllocator.Free(const_cast<LayoutElement*>(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<const PipelineStateBase>(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<IRenderPass> 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<SHADER_TYPE, MAX_SHADERS_IN_PIPELINE> m_ShaderStageTypes = {};
- size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout
+ RefCntAutoPtr<IRenderPass> 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 <typename ShaderImplType, typename TShaderStages>
- 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<ShaderImplType>(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<ShaderResourceVariableDesc>(SrcLayout.NumVariables);
+ for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
+ {
+ VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null");
+ MemPool.AddRequiredSize<Char>(strlen(SrcLayout.Variables[i].Name) + 1);
+ }
+ }
+
+ if (SrcLayout.StaticSamplers != nullptr)
+ {
+ MemPool.AddRequiredSize<StaticSamplerDesc>(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<Char>(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<LayoutElement>(InputLayout.NumElements);
+ for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
+ {
+ auto& LayoutElem = InputLayout.LayoutElements[i];
+ MemPool.AddRequiredSize<Char>(strlen(LayoutElem.HLSLSemantic) + 1);
+ BufferSlotsUsed = std::max(BufferSlotsUsed, LayoutElem.BufferSlot + 1);
+ }
+
+ MemPool.AddRequiredSize<Uint32>(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<ShaderResourceVariableDesc>(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<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 = 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<GraphicsPipelineDesc>(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 <typename ShaderImplType, typename TShaderStages>
+ 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<ShaderImplType>(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 <typename ShaderImplType, typename TShaderStages>
+ 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<ShaderImplType>(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<Uint8>(Subpass.RenderTargetAttachmentCount);
+ GraphicsPipeline.NumRenderTargets = static_cast<Uint8>(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<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);
+ 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<Uint8>(std::max<Uint32>(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<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;
- }
+ // 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<IPipelineStateD3D1
public:
using TPipelineStateBase = PipelineStateBase<IPipelineStateD3D11, RenderDeviceD3D11Impl>;
- 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<std::pair<SHADER_TYPE, ShaderD3D11Impl*>>& ShaderStages);
+
CComPtr<ID3D11BlendState> m_pd3d11BlendState;
CComPtr<ID3D11RasterizerState> m_pd3d11RasterizerState;
CComPtr<ID3D11DepthStencilState> m_pd3d11DepthStencilState;
@@ -147,8 +154,8 @@ private:
RefCntAutoPtr<ShaderD3D11Impl> 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<ShaderD3D11Impl>(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<std::pair<SHADER_TYPE, ShaderD3D11Impl*>> ShaderStages;
+ ExtractShaders<ShaderD3D11Impl>(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<ShaderResourceLayoutD3D11>(GetNumShaderStages());
+ MemPool.AddRequiredSize<ShaderResourceCacheD3D11>(GetNumShaderStages());
+
+ ValidateAndReserveSpace(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ m_pStaticResourceLayouts = MemPool.Allocate<ShaderResourceLayoutD3D11>(GetNumShaderStages());
+ m_pStaticResourceCaches = MemPool.Allocate<ShaderResourceCacheD3D11>(GetNumShaderStages());
+
+ InitGraphicsPipeline(CreateInfo, MemPool);
+ InitResourceLayouts(pRenderDeviceD3D11, CreateInfo, ShaderStages);
+
+ auto& GraphicsPipeline = GetGraphicsPipelineDesc();
#define INIT_SHADER(ShortName, ExpectedType) \
do \
{ \
- auto* pShader = ValidatedCast<ShaderD3D11Impl>(m_Desc.GraphicsPipeline.p##ShortName); \
+ auto* pShader = ValidatedCast<ShaderD3D11Impl>(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<D3D11_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D11_INPUT_ELEMENT_DESC>> d311InputElements(STD_ALLOCATOR_RAW_MEM(D3D11_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D11_INPUT_ELEMENT_DESC>"));
- LayoutElements_To_D3D11_INPUT_ELEMENT_DESCs(InputLayout, d311InputElements);
+ // Create input layout
+ const auto& InputLayout = GraphicsPipeline.InputLayout;
+ if (InputLayout.NumElements > 0)
+ {
+ std::vector<D3D11_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D11_INPUT_ELEMENT_DESC>> d311InputElements(STD_ALLOCATOR_RAW_MEM(D3D11_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D11_INPUT_ELEMENT_DESC>"));
+ LayoutElements_To_D3D11_INPUT_ELEMENT_DESCs(InputLayout, d311InputElements);
- ID3DBlob* pVSByteCode = m_pVS.RawPtr<ShaderD3D11Impl>()->GetBytecode();
- if (!pVSByteCode)
- LOG_ERROR_AND_THROW("Vertex Shader byte code does not exist");
+ ID3DBlob* pVSByteCode = m_pVS.RawPtr<ShaderD3D11Impl>()->GetBytecode();
+ if (!pVSByteCode)
+ LOG_ERROR_AND_THROW("Vertex Shader byte code does not exist");
- CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateInputLayout(d311InputElements.data(), static_cast<UINT>(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<UINT>(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<StaticSamplerInfo>"))
+// 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<std::pair<SHADER_TYPE, ShaderD3D11Impl*>> ShaderStages;
- ExtractShaders<ShaderD3D11Impl>(ShaderStages);
- VERIFY_EXPR(GetNumShaderStages() == ShaderStages.size());
+ ExtractShaders<ShaderD3D11Impl>(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<ShaderResourceLayoutD3D11>(GetNumShaderStages());
+ MemPool.AddRequiredSize<ShaderResourceCacheD3D11>(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<ShaderResourceLayoutD3D11>(GetNumShaderStages());
+ m_pStaticResourceCaches = MemPool.Allocate<ShaderResourceCacheD3D11>(GetNumShaderStages());
- m_pStaticResourceLayouts = reinterpret_cast<ShaderResourceLayoutD3D11*>(pRawMem);
- m_pStaticResourceCaches = reinterpret_cast<ShaderResourceCacheD3D11*>(m_pStaticResourceLayouts + GetNumShaderStages());
+ InitComputePipeline(CreateInfo, MemPool);
+ InitResourceLayouts(pRenderDeviceD3D11, CreateInfo, ShaderStages);
+ auto* pCS = ValidatedCast<ShaderD3D11Impl>(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<std::pair<SHADER_TYPE, ShaderD3D11Impl*>>& 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<StaticSamplerInfo>"));
std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderResLayoutDataSizes = {};
std::array<size_t, MAX_SHADERS_IN_PIPELINE> 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<IObject**>(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<IPipelineStateD3D1
public:
using TPipelineStateBase = PipelineStateBase<IPipelineStateD3D12, RenderDeviceD3D12Impl>;
- 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<D3D12PipelineShaderStageInfo>& ShaderStages);
+
CComPtr<ID3D12PipelineState> 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<D3D12_PRIMITIVE_TOPOLOGY_TYPE, PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES> 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<D3D12PipelineShaderStageInfo> ShaderStages;
+ ExtractShaders<ShaderD3D12Impl>(CreateInfo, ShaderStages);
+
+ // Memory must be released if an exception is thrown.
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ MemPool.AddRequiredSize<ShaderResourceLayoutD3D12>(GetNumShaderStages() * 2);
+ MemPool.AddRequiredSize<ShaderResourceCacheD3D12>(GetNumShaderStages());
+ MemPool.AddRequiredSize<ShaderVariableManagerD3D12>(GetNumShaderStages());
+
+ ValidateAndReserveSpace(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ auto pd3d12Device = pDeviceD3D12->GetD3D12Device();
+ m_RootSig.AllocateStaticSamplers(m_Desc.ResourceLayout);
+
+ m_pShaderResourceLayouts = MemPool.Allocate<ShaderResourceLayoutD3D12>(GetNumShaderStages() * 2);
+ m_pStaticResourceCaches = MemPool.Allocate<ShaderResourceCacheD3D12>(GetNumShaderStages());
+ m_pStaticVarManagers = MemPool.Allocate<ShaderVariableManagerD3D12>(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<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC>> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D12_INPUT_ELEMENT_DESC>"));
+
+ const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout;
+ if (InputLayout.NumElements > 0)
+ {
+ LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements);
+ d3d12PSODesc.InputLayout.NumElements = static_cast<UINT>(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<void**>(static_cast<ID3D12PipelineState**>(&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<D3D12_PIPELINE_STATE_FLAGS, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS> Flags;
+ PSS_SubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK> NodeMask;
+ PSS_SubObject<ID3D12RootSignature*, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> pRootSignature;
+ PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS> PS;
+ PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS> AS;
+ PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS> MS;
+ PSS_SubObject<D3D12_BLEND_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND> BlendState;
+ PSS_SubObject<D3D12_DEPTH_STENCIL_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL> DepthStencilState;
+ PSS_SubObject<D3D12_RASTERIZER_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER> RasterizerState;
+ PSS_SubObject<DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC> SampleDesc;
+ PSS_SubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK> SampleMask;
+ PSS_SubObject<DXGI_FORMAT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT> DSVFormat;
+ PSS_SubObject<D3D12_RT_FORMAT_ARRAY, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS> RTVFormatArray;
+ PSS_SubObject<D3D12_CACHED_PIPELINE_STATE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO> 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<D3D12PipelineShaderStageInfo> ShaderStages;
- ExtractShaders<ShaderD3D12Impl>(ShaderStages);
- VERIFY_EXPR(GetNumShaderStages() == ShaderStages.size());
+ ExtractShaders<ShaderD3D12Impl>(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<ShaderResourceLayoutD3D12>(GetNumShaderStages() * 2);
+ MemPool.AddRequiredSize<ShaderResourceCacheD3D12>(GetNumShaderStages());
+ MemPool.AddRequiredSize<ShaderVariableManagerD3D12>(GetNumShaderStages());
+
+ ValidateAndReserveSpace(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ auto pd3d12Device = pDeviceD3D12->GetD3D12Device();
+ m_RootSig.AllocateStaticSamplers(m_Desc.ResourceLayout);
+
+ m_pShaderResourceLayouts = MemPool.Allocate<ShaderResourceLayoutD3D12>(GetNumShaderStages() * 2);
+ m_pStaticResourceCaches = MemPool.Allocate<ShaderResourceCacheD3D12>(GetNumShaderStages());
+ m_pStaticVarManagers = MemPool.Allocate<ShaderVariableManagerD3D12>(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<void**>(static_cast<ID3D12PipelineState**>(&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<ShaderResourceLayoutD3D12*>(pRawMem);
- m_pStaticResourceCaches = reinterpret_cast<ShaderResourceCacheD3D12*>(m_pShaderResourceLayouts + GetNumShaderStages() * 2);
- m_pStaticVarManagers = reinterpret_cast<ShaderVariableManagerD3D12*>(m_pStaticResourceCaches + GetNumShaderStages());
+
+void PipelineStateD3D12Impl::InitResourceLayouts(RenderDeviceD3D12Impl* pDeviceD3D12,
+ const PipelineStateCreateInfo& CreateInfo,
+ std::vector<D3D12PipelineShaderStageInfo>& 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<void**>(static_cast<ID3D12PipelineState**>(&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<D3D12_INPUT_ELEMENT_DESC, STDAllocatorRawMem<D3D12_INPUT_ELEMENT_DESC>> d312InputElements(STD_ALLOCATOR_RAW_MEM(D3D12_INPUT_ELEMENT_DESC, GetRawAllocator(), "Allocator for vector<D3D12_INPUT_ELEMENT_DESC>"));
-
- const auto& InputLayout = m_Desc.GraphicsPipeline.InputLayout;
- if (InputLayout.NumElements > 0)
- {
- LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements);
- d3d12PSODesc.InputLayout.NumElements = static_cast<UINT>(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<void**>(static_cast<ID3D12PipelineState**>(&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<D3D12_PIPELINE_STATE_FLAGS, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_FLAGS> Flags;
- PSS_SubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_NODE_MASK> NodeMask;
- PSS_SubObject<ID3D12RootSignature*, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> pRootSignature;
- PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS> PS;
- PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS> AS;
- PSS_SubObject<D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS> MS;
- PSS_SubObject<D3D12_BLEND_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND> BlendState;
- PSS_SubObject<D3D12_DEPTH_STENCIL_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL> DepthStencilState;
- PSS_SubObject<D3D12_RASTERIZER_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RASTERIZER> RasterizerState;
- PSS_SubObject<DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC> SampleDesc;
- PSS_SubObject<UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK> SampleMask;
- PSS_SubObject<DXGI_FORMAT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL_FORMAT> DSVFormat;
- PSS_SubObject<D3D12_RT_FORMAT_ARRAY, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_RENDER_TARGET_FORMATS> RTVFormatArray;
- PSS_SubObject<D3D12_CACHED_PIPELINE_STATE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO> 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<size_t, MAX_SHADERS_IN_PIPELINE> 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<IObject**>(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<IPipelineStateGL, Ren
public:
using TPipelineStateBase = PipelineStateBase<IPipelineStateGL, RenderDeviceGLImpl>;
- 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<GLPipelineShaderStageInfo>& 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<GLObjectWrappers::GLProgramObj> 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<GLProgramResources> 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<RefCntAutoPtr<ISampler>> m_StaticSamplers;
+ using SamplerPtr = RefCntAutoPtr<ISampler>;
+ 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<GLPipelineShaderStageInfo> ShaderStages;
+ ExtractShaders<ShaderGLImpl>(CreateInfo, ShaderStages);
+
RefCntAutoPtr<ShaderGLImpl> 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<IShader**>(static_cast<ShaderGLImpl**>(&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<GLProgramObj>(GetNumShaderStages());
+ MemPool.AddRequiredSize<GLProgramResources>(GetNumShaderStages());
+ MemPool.AddRequiredSize<SamplerPtr>(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<GLPipelineShaderStageInfo> ShaderStages;
- ExtractShaders<ShaderGLImpl>(ShaderStages);
+ ExtractShaders<ShaderGLImpl>(CreateInfo, ShaderStages);
+
+ // Memory must be released if an exception is thrown.
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ MemPool.AddRequiredSize<GLProgramObj>(GetNumShaderStages());
+ MemPool.AddRequiredSize<GLProgramResources>(GetNumShaderStages());
+ MemPool.AddRequiredSize<SamplerPtr>(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<GLPipelineShaderStageInfo>& 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<GLProgramObj>(ShaderStages.size());
+ m_ProgramResources = MemPool.ConstructArray<GLProgramResources>(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<Uint32>(ShaderStages.size()), false));
- m_ProgramResources.resize(1);
+ m_GLPrograms = MemPool.Construct<GLProgramObj>(ShaderGLImpl::LinkProgram(Shaders.data(), static_cast<Uint32>(ShaderStages.size()), false));
+ m_ProgramResources = MemPool.Construct<GLProgramResources>();
+
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<Uint32>(m_GLPrograms.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr);
+ m_ResourceLayout.Initialize(m_ProgramResources, static_cast<Uint32>(ShaderStages.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr);
}
- m_StaticSamplers.resize(m_Desc.ResourceLayout.NumStaticSamplers);
+ m_StaticSamplers = MemPool.ConstructArray<SamplerPtr>(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<Uint32>(m_GLPrograms.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache);
+ m_StaticResourceLayout.Initialize(m_ProgramResources, static_cast<Uint32>(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<Uint32>(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<IObject**>(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<IObject**>(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<PipelineStateGLImpl>(pPSO);
auto* pIndexBufferGL = ValidatedCast<BufferGLImpl>(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<IPipelineStateVk, Ren
public:
using TPipelineStateBase = PipelineStateBase<IPipelineStateVk, RenderDeviceVkImpl>;
- 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 << "<Not set>";
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<RefCntAutoPtr<IPipelineState>, 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<RefCntAutoPtr<IPipelineState>, 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<VkPipelineShaderStageCreateInfo>& 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<VkPipelineShaderStageCreateInfo>& Stages,
const PipelineLayout& Layout,
- const PipelineStateDesc& Desc,
+ const PipelineStateDesc& PSODesc,
+ const GraphicsPipelineDesc& GraphicsPipeline,
VulkanUtilities::PipelineWrapper& Pipeline,
RefCntAutoPtr<IRenderPass>& 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<IRenderPassVk>()->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<ShaderVkImpl>(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<ShaderResourceLayoutVk*>(pRawMem);
- m_StaticResCaches = reinterpret_cast<ShaderResourceCacheVk*>(m_ShaderResourceLayouts + GetNumShaderStages() * 2);
- m_StaticVarsMgrs = reinterpret_cast<ShaderVariableManagerVk*>(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<Int8>(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<VkPipelineShaderStageCreateInfo> VkShaderStages;
- std::vector<VulkanUtilities::ShaderModuleWrapper> 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<ShaderVkImpl>(CreateInfo, ShaderStages);
+
+ // Memory must be released if an exception is thrown.
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ MemPool.AddRequiredSize<ShaderResourceLayoutVk>(GetNumShaderStages() * 2);
+ MemPool.AddRequiredSize<ShaderResourceCacheVk>(GetNumShaderStages());
+ MemPool.AddRequiredSize<ShaderVariableManagerVk>(GetNumShaderStages());
+
+ ValidateAndReserveSpace(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ m_ShaderResourceLayouts = MemPool.Allocate<ShaderResourceLayoutVk>(GetNumShaderStages() * 2);
+ m_StaticResCaches = MemPool.Allocate<ShaderResourceCacheVk>(GetNumShaderStages());
+ m_StaticVarsMgrs = MemPool.Allocate<ShaderVariableManagerVk>(GetNumShaderStages());
+
+ InitGraphicsPipeline(CreateInfo, MemPool);
+ InitResourceLayouts(pDeviceVk, CreateInfo, ShaderStages);
+
+ // Create shader modules and initialize shader stages
+ std::vector<VkPipelineShaderStageCreateInfo> VkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> 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<ShaderVkImpl>(CreateInfo, ShaderStages);
+
+ // Memory must be released if an exception is thrown.
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ MemPool.AddRequiredSize<ShaderResourceLayoutVk>(GetNumShaderStages() * 2);
+ MemPool.AddRequiredSize<ShaderResourceCacheVk>(GetNumShaderStages());
+ MemPool.AddRequiredSize<ShaderVariableManagerVk>(GetNumShaderStages());
+
+ ValidateAndReserveSpace(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ m_ShaderResourceLayouts = MemPool.Allocate<ShaderResourceLayoutVk>(GetNumShaderStages() * 2);
+ m_StaticResCaches = MemPool.Allocate<ShaderResourceCacheVk>(GetNumShaderStages());
+ m_StaticVarsMgrs = MemPool.Allocate<ShaderVariableManagerVk>(GetNumShaderStages());
+
+ InitComputePipeline(CreateInfo, MemPool);
+ InitResourceLayouts(pDeviceVk, CreateInfo, ShaderStages);
+
+ // Create shader modules and initialize shader stages
+ std::vector<VkPipelineShaderStageCreateInfo> VkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> 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<IObject**>(ppPipelineState));
+ OnCreateDeviceObject(pPipelineStateVk);
+ } //
+ );
+}
+
+
+void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
{
CreateDeviceObject(
"Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState,