summaryrefslogtreecommitdiffstats
path: root/Graphics
diff options
context:
space:
mode:
authorazhirnov <zh1dron@gmail.com>2020-10-21 22:15:55 +0000
committerazhirnov <zh1dron@gmail.com>2020-10-25 10:50:53 +0000
commit42217cc1ec7f81c028dcc5c1f845a2fc3b3da497 (patch)
tree2efcb7c0fdeae582ecb5c8d13c7bedd593ab9a3c /Graphics
parentFixed Mac/iOS build (diff)
parentUpdated Metal testing environment (diff)
downloadDiligentCore-42217cc1ec7f81c028dcc5c1f845a2fc3b3da497.tar.gz
DiligentCore-42217cc1ec7f81c028dcc5c1f845a2fc3b3da497.zip
Merge branch 'master' into ray_tracing
# Conflicts: # Graphics/GraphicsEngine/interface/PipelineState.h # Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp # Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp # Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
Diffstat (limited to 'Graphics')
-rw-r--r--Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp31
-rw-r--r--Graphics/GraphicsEngine/CMakeLists.txt1
-rw-r--r--Graphics/GraphicsEngine/include/BufferBase.hpp10
-rw-r--r--Graphics/GraphicsEngine/include/DeviceContextBase.hpp10
-rw-r--r--Graphics/GraphicsEngine/include/PipelineStateBase.hpp753
-rw-r--r--Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp78
-rw-r--r--Graphics/GraphicsEngine/include/TextureBase.hpp3
-rw-r--r--Graphics/GraphicsEngine/interface/APIInfo.h119
-rw-r--r--Graphics/GraphicsEngine/interface/GraphicsTypes.h43
-rw-r--r--Graphics/GraphicsEngine/interface/InputLayout.h2
-rw-r--r--Graphics/GraphicsEngine/interface/PipelineState.h138
-rw-r--r--Graphics/GraphicsEngine/interface/RenderDevice.h53
-rw-r--r--Graphics/GraphicsEngine/interface/Shader.h4
-rw-r--r--Graphics/GraphicsEngine/src/APIInfo.cpp5
-rw-r--r--Graphics/GraphicsEngine/src/BufferBase.cpp6
-rw-r--r--Graphics/GraphicsEngine/src/PipelineStateBase.cpp260
-rw-r--r--Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp4
-rw-r--r--Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp48
-rw-r--r--Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp13
-rw-r--r--Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp23
-rw-r--r--Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp4
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp22
-rw-r--r--Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp323
-rw-r--r--Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp40
-rw-r--r--Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp134
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp93
-rwxr-xr-xGraphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp91
-rw-r--r--Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp4
-rw-r--r--Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp37
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RenderDeviceD3D12Impl.hpp10
-rw-r--r--Graphics/GraphicsEngineD3D12/include/RootSignature.hpp22
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp27
-rw-r--r--Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp18
-rw-r--r--Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp4
-rw-r--r--Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp2
-rw-r--r--Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp65
-rw-r--r--Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp420
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp40
-rw-r--r--Graphics/GraphicsEngineD3D12/src/RootSignature.cpp73
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp97
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp78
-rw-r--r--Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp23
-rw-r--r--Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp6
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp1
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp14
-rw-r--r--Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp49
-rw-r--r--Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp95
-rw-r--r--Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h1
-rw-r--r--Graphics/GraphicsEngineMetal/interface/SamplerMtl.h1
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp12
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp10
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp2
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp42
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp23
-rw-r--r--Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp4
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp48
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp4
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp231
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp40
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp6
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp19
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp4
-rw-r--r--Graphics/GraphicsEngineOpenGL/src/VAOCache.cpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/PipelineStateVkImpl.hpp35
-rw-r--r--Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp10
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp2
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp68
-rw-r--r--Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp24
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp3
-rw-r--r--Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp6
-rw-r--r--Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp68
-rw-r--r--Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp22
-rw-r--r--Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp18
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp30
-rw-r--r--Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp678
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp19
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp91
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp314
-rw-r--r--Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp29
-rw-r--r--Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp6
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp29
-rw-r--r--Graphics/ShaderTools/include/SPIRVShaderResources.hpp19
-rw-r--r--Graphics/ShaderTools/src/SPIRVShaderResources.cpp49
91 files changed, 3270 insertions, 2119 deletions
diff --git a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
index 00cb22e4..499509fb 100644
--- a/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
+++ b/Graphics/GraphicsAccessories/src/GraphicsAccessories.cpp
@@ -771,16 +771,16 @@ const Char* GetUsageString(USAGE Usage)
{
// clang-format off
#define INIT_USGAGE_STR(Usage)UsageStrings[Usage] = #Usage
- INIT_USGAGE_STR( USAGE_STATIC );
- INIT_USGAGE_STR( USAGE_DEFAULT );
- INIT_USGAGE_STR( USAGE_DYNAMIC );
- INIT_USGAGE_STR( USAGE_STAGING );
- INIT_USGAGE_STR( USAGE_UNIFIED );
+ INIT_USGAGE_STR(USAGE_IMMUTABLE);
+ INIT_USGAGE_STR(USAGE_DEFAULT);
+ INIT_USGAGE_STR(USAGE_DYNAMIC);
+ INIT_USGAGE_STR(USAGE_STAGING);
+ INIT_USGAGE_STR(USAGE_UNIFIED);
#undef INIT_USGAGE_STR
// clang-format on
bUsageStringsInit = true;
}
- if (Usage >= USAGE_STATIC && Usage < USAGE_NUM_USAGES)
+ if (Usage >= USAGE_IMMUTABLE && Usage < USAGE_NUM_USAGES)
return UsageStrings[Usage];
else
{
@@ -797,13 +797,13 @@ const Char* GetResourceDimString(RESOURCE_DIMENSION TexType)
{
TexTypeStrings[RESOURCE_DIM_UNDEFINED] = "Undefined";
TexTypeStrings[RESOURCE_DIM_BUFFER] = "Buffer";
- TexTypeStrings[RESOURCE_DIM_TEX_1D] = "Tex 1D";
- TexTypeStrings[RESOURCE_DIM_TEX_1D_ARRAY] = "Tex 1D Array";
- TexTypeStrings[RESOURCE_DIM_TEX_2D] = "Tex 2D";
- TexTypeStrings[RESOURCE_DIM_TEX_2D_ARRAY] = "Tex 2D Array";
- TexTypeStrings[RESOURCE_DIM_TEX_3D] = "Tex 3D";
- TexTypeStrings[RESOURCE_DIM_TEX_CUBE] = "Tex Cube";
- TexTypeStrings[RESOURCE_DIM_TEX_CUBE_ARRAY] = "Tex Cube Array";
+ TexTypeStrings[RESOURCE_DIM_TEX_1D] = "Texture 1D";
+ TexTypeStrings[RESOURCE_DIM_TEX_1D_ARRAY] = "Texture 1D Array";
+ TexTypeStrings[RESOURCE_DIM_TEX_2D] = "Texture 2D";
+ TexTypeStrings[RESOURCE_DIM_TEX_2D_ARRAY] = "Texture 2D Array";
+ TexTypeStrings[RESOURCE_DIM_TEX_3D] = "Texture 3D";
+ TexTypeStrings[RESOURCE_DIM_TEX_CUBE] = "Texture Cube";
+ TexTypeStrings[RESOURCE_DIM_TEX_CUBE_ARRAY] = "Texture Cube Array";
static_assert(RESOURCE_DIM_NUM_DIMENSIONS == RESOURCE_DIM_TEX_CUBE_ARRAY + 1, "Not all texture type strings initialized.");
bTexTypeStrsInit = true;
@@ -1337,7 +1337,7 @@ Int32 GetShaderTypePipelineIndex(SHADER_TYPE ShaderType, PIPELINE_TYPE PipelineT
{
VERIFY(IsConsistentShaderType(ShaderType, PipelineType), "Shader type ", GetShaderTypeLiteralName(ShaderType),
" is inconsistent with pipeline type ", GetPipelineTypeString(PipelineType));
- VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "Only single shader stage should be provided");
+ VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "More than one shader type is specified");
static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
switch (ShaderType)
@@ -1488,7 +1488,8 @@ Uint32 GetStagingTextureLocationOffset(const TextureDesc& TexDesc,
// For non-compressed formats, BlockWidth is 1.
Offset += (LocationX / FmtAttribs.BlockWidth) * FmtAttribs.GetElementSize();
- // Note: this addressing complies with how Vulkan addresses textures when copying data to/from buffer:
+ // Note: this addressing complies with how Vulkan (as well as OpenGL/GLES and Metal) address
+ // textures when copying data to/from buffers:
// address of (x,y,z) = bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
}
diff --git a/Graphics/GraphicsEngine/CMakeLists.txt b/Graphics/GraphicsEngine/CMakeLists.txt
index 3162b6a0..47692deb 100644
--- a/Graphics/GraphicsEngine/CMakeLists.txt
+++ b/Graphics/GraphicsEngine/CMakeLists.txt
@@ -72,6 +72,7 @@ set(SOURCE
src/DefaultShaderSourceStreamFactory.cpp
src/EngineMemory.cpp
src/FramebufferBase.cpp
+ src/PipelineStateBase.cpp
src/ResourceMappingBase.cpp
src/RenderPassBase.cpp
src/TextureBase.cpp
diff --git a/Graphics/GraphicsEngine/include/BufferBase.hpp b/Graphics/GraphicsEngine/include/BufferBase.hpp
index 9ae6db92..605bc2ed 100644
--- a/Graphics/GraphicsEngine/include/BufferBase.hpp
+++ b/Graphics/GraphicsEngine/include/BufferBase.hpp
@@ -30,12 +30,14 @@
/// \file
/// Implementation of the Diligent::BufferBase template class
+#include <memory>
+
#include "Buffer.h"
#include "GraphicsTypes.h"
#include "DeviceObjectBase.hpp"
#include "GraphicsAccessories.hpp"
#include "STDAllocator.hpp"
-#include <memory>
+#include "FormatString.hpp"
namespace Diligent
{
@@ -232,6 +234,9 @@ void BufferBase<BaseInterface, RenderDeviceImplType, BufferViewImplType, TBuffVi
{
BufferViewDesc ViewDesc;
ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS;
+ auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\'');
+ ViewDesc.Name = UAVName.c_str();
+
IBufferView* pUAV = nullptr;
CreateViewInternal(ViewDesc, &pUAV, true);
m_pDefaultUAV.reset(static_cast<BufferViewImplType*>(pUAV));
@@ -242,6 +247,9 @@ void BufferBase<BaseInterface, RenderDeviceImplType, BufferViewImplType, TBuffVi
{
BufferViewDesc ViewDesc;
ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE;
+ auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\'');
+ ViewDesc.Name = SRVName.c_str();
+
IBufferView* pSRV = nullptr;
CreateViewInternal(ViewDesc, &pSRV, true);
m_pDefaultSRV.reset(static_cast<BufferViewImplType*>(pSRV));
diff --git a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
index dd8851c7..c16219da 100644
--- a/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
+++ b/Graphics/GraphicsEngine/include/DeviceContextBase.hpp
@@ -1672,6 +1672,13 @@ inline void DeviceContextBase<BaseInterface, ImplementationTraits>::
return;
}
+ const auto& PSODesc = m_pPipelineState->GetDesc();
+ if (!PSODesc.IsAnyGraphicsPipeline())
+ {
+ LOG_ERROR_MESSAGE("Pipeline state '", PSODesc.Name, "' is not a graphics pipeline");
+ return;
+ }
+
TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN};
TEXTURE_FORMAT BoundDSVFormat = TEX_FORMAT_UNKNOWN;
@@ -1685,8 +1692,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 b54a2f76..1effd32f 100644
--- a/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
+++ b/Graphics/GraphicsEngine/include/PipelineStateBase.hpp
@@ -38,11 +38,16 @@
#include "STDAllocator.hpp"
#include "EngineMemory.h"
#include "GraphicsAccessories.hpp"
-#include "StringPool.hpp"
+#include "LinearAllocator.hpp"
namespace Diligent
{
+void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false);
+void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false);
+
+void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept;
+
/// Template class implementing base functionality for a pipeline state object.
/// \tparam BaseInterface - base interface that this class will inheret
@@ -57,298 +62,17 @@ class PipelineStateBase : public DeviceObjectBase<BaseInterface, RenderDeviceImp
public:
using TDeviceObjectBase = DeviceObjectBase<BaseInterface, RenderDeviceImplType, PipelineStateDesc>;
- /// \param pRefCounters - reference counters object that controls the lifetime of this PSO
- /// \param pDevice - pointer to the device.
- /// \param PSODesc - pipeline state description.
- /// \param bIsDeviceInternal - flag indicating if the blend state is an internal device object and
+ /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO
+ /// \param pDevice - Pointer to the device.
+ /// \param CreateInfo - Pipeline state create info.
+ /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and
/// must not keep a strong reference to the device.
PipelineStateBase(IReferenceCounters* pRefCounters,
RenderDeviceImplType* pDevice,
const PipelineStateDesc& PSODesc,
bool bIsDeviceInternal = false) :
- TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal},
- m_NumShaders{0}
+ TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal}
{
- ValidateDesc();
-
- const auto& SrcLayout = PSODesc.ResourceLayout;
- size_t StringPoolSize = 0;
- if (SrcLayout.Variables != nullptr)
- {
- for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
- StringPoolSize += strlen(SrcLayout.Variables[i].Name) + 1;
- }
-
- if (SrcLayout.StaticSamplers != nullptr)
- {
- for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i)
- StringPoolSize += strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1;
- }
-
- if (PSODesc.IsAnyGraphicsPipeline())
- {
- CheckAndCorrectBlendStateDesc();
- CheckRasterizerStateDesc();
- CheckAndCorrectDepthStencilDesc();
-
- const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout;
- for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
- StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1;
- }
- else
- {
- DEV_CHECK_ERR(PSODesc.GraphicsPipeline.InputLayout.NumElements == 0, "Compute pipelines must not have input layout elements");
- }
-
- 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)
- {
- VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null");
- Variables[i] = SrcLayout.Variables[i];
- Variables[i].Name = m_StringPool.CopyString(SrcLayout.Variables[i].Name);
- }
- }
-
- 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)
- {
- VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null");
-#ifdef DILIGENT_DEVELOPMENT
- {
- const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor;
- 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);
- }
- }
-
-
- if (this->m_Desc.IsComputePipeline())
- {
- const auto& ComputePipeline = PSODesc.ComputePipeline;
- if (ComputePipeline.pCS == nullptr)
- {
- LOG_ERROR_AND_THROW("Compute shader is not provided");
- }
-
-#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \
- if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \
- { \
- LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \
- }
-
- VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute")
-
- m_pCS = ComputePipeline.pCS;
- m_ppShaders[0] = ComputePipeline.pCS;
- m_NumShaders = 1;
- }
- else
- {
- const auto& GraphicsPipeline = PSODesc.GraphicsPipeline;
-
- VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex")
- VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel")
- VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry")
- VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull")
- VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain")
- VALIDATE_SHADER_TYPE(GraphicsPipeline.pAS, SHADER_TYPE_AMPLIFICATION, "amplification")
- VALIDATE_SHADER_TYPE(GraphicsPipeline.pMS, SHADER_TYPE_MESH, "mesh")
-#undef VALIDATE_SHADER_TYPE
-
- if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS)
- {
- DEV_CHECK_ERR(GraphicsPipeline.pVS, "Vertex shader must be defined");
- DEV_CHECK_ERR(!GraphicsPipeline.pAS && !GraphicsPipeline.pMS, "Mesh shaders are not supported in graphics pipeline");
- m_pVS = GraphicsPipeline.pVS;
- m_pPS = GraphicsPipeline.pPS;
- m_pGS = GraphicsPipeline.pGS;
- m_pDS = GraphicsPipeline.pDS;
- m_pHS = GraphicsPipeline.pHS;
- }
- else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH)
- {
- DEV_CHECK_ERR(GraphicsPipeline.pMS, "Mesh shader must be defined");
- DEV_CHECK_ERR(!GraphicsPipeline.pVS && !GraphicsPipeline.pGS && !GraphicsPipeline.pDS && !GraphicsPipeline.pHS,
- "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline");
- DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout ignored in mesh shader");
- DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ||
- GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED,
- "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)");
- m_pAS = GraphicsPipeline.pAS;
- m_pMS = GraphicsPipeline.pMS;
- m_pPS = GraphicsPipeline.pPS;
- }
-
- if (GraphicsPipeline.pVS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pVS;
- if (GraphicsPipeline.pPS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pPS;
- if (GraphicsPipeline.pGS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pGS;
- if (GraphicsPipeline.pHS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pHS;
- if (GraphicsPipeline.pDS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pDS;
- if (GraphicsPipeline.pAS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pAS;
- if (GraphicsPipeline.pMS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pMS;
-
- DEV_CHECK_ERR(m_NumShaders > 0, "There must be at least one shader in the Pipeline State");
-
- m_pRenderPass = PSODesc.GraphicsPipeline.pRenderPass;
-
- for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt)
- {
- auto RTVFmt = GraphicsPipeline.RTVFormats[rt];
- if (RTVFmt != TEX_FORMAT_UNKNOWN)
- {
- LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt,
- " must be set to TEX_FORMAT_UNKNOWN");
- }
- }
-
- if (m_pRenderPass)
- {
- const auto& RPDesc = m_pRenderPass->GetDesc();
- VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount);
- const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex];
-
- this->m_Desc.GraphicsPipeline.NumRenderTargets = static_cast<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;
- }
- }
-
- if (Subpass.pDepthStencilAttachment != nullptr)
- {
- const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment;
- if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED)
- {
- VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount);
- this->m_Desc.GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format;
- }
- }
- }
-
- const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout;
- LayoutElement* pLayoutElements = nullptr;
- if (InputLayout.NumElements > 0)
- {
- pLayoutElements = ALLOCATE(GetRawAllocator(), "Raw memory for input layout elements", LayoutElement, InputLayout.NumElements);
- }
- this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements;
- for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem)
- {
- pLayoutElements[Elem] = InputLayout.LayoutElements[Elem];
- pLayoutElements[Elem].HLSLSemantic = m_StringPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic);
- }
-
-
- // Correct description and compute offsets and tight strides
- std::array<Uint32, MAX_BUFFER_SLOTS> Strides, TightStrides = {};
- // Set all strides to an invalid value because an application may want to use 0 stride
- for (auto& Stride : Strides)
- Stride = LAYOUT_ELEMENT_AUTO_STRIDE;
-
- for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
- {
- auto& LayoutElem = pLayoutElements[i];
-
- if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16)
- LayoutElem.IsNormalized = false; // Floating point values cannot be normalized
-
- auto BuffSlot = LayoutElem.BufferSlot;
- if (BuffSlot >= Strides.size())
- {
- UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")");
- continue;
- }
- m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1);
-
- auto& CurrAutoStride = TightStrides[BuffSlot];
- // If offset is not explicitly specified, use current auto stride value
- if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET)
- {
- LayoutElem.RelativeOffset = CurrAutoStride;
- }
-
- // If stride is explicitly specified, use it for the current buffer slot
- if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE)
- {
- // Verify that the value is consistent with the previously specified stride, if any
- if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride)
- {
- LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot,
- ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ",
- LayoutElem.Stride, ", while current value is ", Strides[BuffSlot],
- ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow "
- "the engine compute strides automatically.");
- }
- Strides[BuffSlot] = LayoutElem.Stride;
- }
-
- CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType));
- }
-
- for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
- {
- auto& LayoutElem = pLayoutElements[i];
-
- auto BuffSlot = LayoutElem.BufferSlot;
- // If no input elements explicitly specified stride for this buffer slot, use automatic stride
- if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE)
- {
- Strides[BuffSlot] = TightStrides[BuffSlot];
- }
- else
- {
- if (Strides[BuffSlot] < TightStrides[BuffSlot])
- {
- LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot,
- " is smaller than the minimum stride ", TightStrides[BuffSlot],
- " required to accomodate all input elements.");
- }
- }
- if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE)
- LayoutElem.Stride = Strides[BuffSlot];
- }
-
- if (m_BufferSlotsUsed > 0)
- {
- m_pStrides = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", Uint32, m_BufferSlotsUsed);
-
- // Set strides for all unused slots to 0
- for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i)
- {
- auto Stride = Strides[i];
- m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0;
- }
- }
- }
-
- 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,
@@ -356,6 +80,35 @@ public:
this->m_Desc.CommandQueueMask &= DeviceQueuesMask;
}
+ /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO
+ /// \param pDevice - Pointer to the device.
+ /// \param GraphicsPipelineCI - Graphics pipeline create information.
+ /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and
+ /// must not keep a strong reference to the device.
+ PipelineStateBase(IReferenceCounters* pRefCounters,
+ RenderDeviceImplType* pDevice,
+ const GraphicsPipelineStateCreateInfo& GraphicsPipelineCI,
+ bool bIsDeviceInternal = false) :
+ PipelineStateBase{pRefCounters, pDevice, GraphicsPipelineCI.PSODesc, bIsDeviceInternal}
+ {
+ ValidateGraphicsPipelineCreateInfo(GraphicsPipelineCI);
+ }
+
+ /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO
+ /// \param pDevice - Pointer to the device.
+ /// \param ComputePipelineCI - Compute pipeline create information.
+ /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and
+ /// must not keep a strong reference to the device.
+ PipelineStateBase(IReferenceCounters* pRefCounters,
+ RenderDeviceImplType* pDevice,
+ const ComputePipelineStateCreateInfo& ComputePipelineCI,
+ bool bIsDeviceInternal = false) :
+ PipelineStateBase{pRefCounters, pDevice, ComputePipelineCI.PSODesc, bIsDeviceInternal}
+ {
+ ValidateComputePipelineCreateInfo(ComputePipelineCI);
+ }
+
+
~PipelineStateBase()
{
/*
@@ -375,16 +128,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)
@@ -399,28 +142,8 @@ public:
return m_BufferSlotsUsed;
}
- IShader* GetVS() { return m_pVS; }
- IShader* GetPS() { return m_pPS; }
- IShader* GetGS() { return m_pGS; }
- IShader* GetDS() { return m_pDS; }
- IShader* GetHS() { return m_pHS; }
- IShader* GetCS() { return m_pCS; }
-
- IShader* const* GetShaders() const { return m_ppShaders.data(); }
- Uint32 GetNumShaders() const { return m_NumShaders; }
-
- template <typename ShaderType>
- ShaderType* GetShader(Uint32 ShaderInd)
- {
- VERIFY_EXPR(ShaderInd < m_NumShaders);
- return ValidatedCast<ShaderType>(m_ppShaders[ShaderInd]);
- }
- template <typename ShaderType>
- ShaderType* GetShader(Uint32 ShaderInd) const
- {
- VERIFY_EXPR(ShaderInd < m_NumShaders);
- return ValidatedCast<ShaderType>(m_ppShaders[ShaderInd]);
- }
+ SHADER_TYPE GetShaderStageType(Uint32 Stage) const { return m_ShaderStageTypes[Stage]; }
+ Uint32 GetNumShaderStages() const { return m_NumShaderStages; }
// This function only compares shader resource layout hashes, so
// it can potentially give false negatives
@@ -429,27 +152,12 @@ public:
return m_ShaderResourceLayoutHash != ValidatedCast<const PipelineStateBase>(pPSO)->m_ShaderResourceLayoutHash;
}
-protected:
- Uint32 m_BufferSlotsUsed = 0;
- Uint32 m_NumShaders = 0; ///< Number of shaders that this PSO uses
- Uint32* m_pStrides = nullptr;
-
- StringPool m_StringPool;
-
- RefCntAutoPtr<IShader> m_pVS; ///< Strong reference to the vertex shader
- RefCntAutoPtr<IShader> m_pPS; ///< Strong reference to the pixel shader
- RefCntAutoPtr<IShader> m_pGS; ///< Strong reference to the geometry shader
- RefCntAutoPtr<IShader> m_pDS; ///< Strong reference to the domain shader
- RefCntAutoPtr<IShader> m_pHS; ///< Strong reference to the hull shader
- RefCntAutoPtr<IShader> m_pCS; ///< Strong reference to the compute shader
- RefCntAutoPtr<IShader> m_pAS; ///< Strong reference to the amplification shader
- RefCntAutoPtr<IShader> m_pMS; ///< Strong reference to the mesh shader
-
- RefCntAutoPtr<IRenderPass> m_pRenderPass; ///< Strong reference to the render pass object
-
- std::array<IShader*, MAX_SHADERS_IN_PIPELINE> m_ppShaders = {}; ///< Array of pointers to the shaders used by this PSO
- size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout
-
+ virtual const GraphicsPipelineDesc& DILIGENT_CALL_TYPE GetGraphicsPipelineDesc() const override final
+ {
+ VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline());
+ VERIFY_EXPR(m_pGraphicsPipelineDesc != nullptr);
+ return *m_pGraphicsPipelineDesc;
+ }
protected:
Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
@@ -512,143 +220,312 @@ protected:
return LayoutInd;
}
-private:
-#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(this->m_Desc.PipelineType), " PSO '", this->m_Desc.Name, "' is invalid: ", ##__VA_ARGS__)
- void ValidateDesc() const
+ void ReserveSpaceForPipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo,
+ LinearAllocator& MemPool) noexcept
{
- if (this->m_Desc.IsComputePipeline())
+ MemPool.AddSpace<GraphicsPipelineDesc>();
+ ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool);
+
+ const auto& InputLayout = CreateInfo.GraphicsPipeline.InputLayout;
+ MemPool.AddSpace<LayoutElement>(InputLayout.NumElements);
+ for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
{
- if (this->m_Desc.GraphicsPipeline.pRenderPass != nullptr)
+ auto& LayoutElem = InputLayout.LayoutElements[i];
+ MemPool.AddSpaceForString(LayoutElem.HLSLSemantic);
+ m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, static_cast<Uint8>(LayoutElem.BufferSlot + 1));
+ }
+
+ MemPool.AddSpace<Uint32>(m_BufferSlotsUsed);
+ }
+
+ void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo,
+ LinearAllocator& MemPool) const noexcept
+ {
+ ReserveResourceLayout(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));
+ VERIFY(m_ShaderStageTypes[m_NumShaderStages] == SHADER_TYPE_UNKNOWN, "This shader stage is already initialized.");
+ m_ShaderStageTypes[m_NumShaderStages++] = ShaderType;
+ }
+ };
+
+ switch (CreateInfo.PSODesc.PipelineType)
+ {
+ case PIPELINE_TYPE_GRAPHICS:
{
- LOG_PSO_ERROR_AND_THROW("GraphicsPipeline.pRenderPass must be null for compute pipelines");
+ AddShaderStage(CreateInfo.pVS);
+ AddShaderStage(CreateInfo.pHS);
+ AddShaderStage(CreateInfo.pDS);
+ AddShaderStage(CreateInfo.pGS);
+ AddShaderStage(CreateInfo.pPS);
+ VERIFY(CreateInfo.pVS != nullptr, "Vertex shader must not be null");
+ break;
}
+
+ case PIPELINE_TYPE_MESH:
+ {
+ AddShaderStage(CreateInfo.pAS);
+ AddShaderStage(CreateInfo.pMS);
+ AddShaderStage(CreateInfo.pPS);
+ VERIFY(CreateInfo.pMS != nullptr, "Mesh shader must not be null");
+ break;
+ }
+
+ default:
+ UNEXPECTED("unknown pipeline type");
}
- else
+
+ 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();
+
+ VERIFY_EXPR(CreateInfo.PSODesc.PipelineType == PIPELINE_TYPE_COMPUTE);
+ VERIFY_EXPR(CreateInfo.pCS != nullptr);
+ VERIFY_EXPR(CreateInfo.pCS->GetDesc().ShaderType == SHADER_TYPE_COMPUTE);
+
+ ShaderStages.emplace_back(SHADER_TYPE_COMPUTE, ValidatedCast<ShaderImplType>(CreateInfo.pCS));
+ m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_COMPUTE;
+
+ VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages);
+ }
+
+
+ void InitializePipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo,
+ LinearAllocator& MemPool)
+ {
+ this->m_pGraphicsPipelineDesc = MemPool.Copy(CreateInfo.GraphicsPipeline);
+
+ auto& GraphicsPipeline = *this->m_pGraphicsPipelineDesc;
+ CorrectGraphicsPipelineDesc(GraphicsPipeline);
+
+ CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool);
+
+ m_pRenderPass = GraphicsPipeline.pRenderPass;
+ if (m_pRenderPass)
{
- const auto& GraphicsPipeline = this->m_Desc.GraphicsPipeline;
- if (GraphicsPipeline.pRenderPass != nullptr)
+ const auto& RPDesc = m_pRenderPass->GetDesc();
+ VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount);
+ const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex];
+
+ GraphicsPipeline.NumRenderTargets = static_cast<Uint8>(Subpass.RenderTargetAttachmentCount);
+ for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt)
{
- if (GraphicsPipeline.NumRenderTargets != 0)
- LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used");
- if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN)
- LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
+ const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt];
+ if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED)
+ {
+ VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount);
+ GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format;
+ }
+ }
- for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
+ if (Subpass.pDepthStencilAttachment != nullptr)
+ {
+ const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment;
+ if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED)
{
- if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN)
- LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
+ VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount);
+ GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format;
}
+ }
+ }
+
+ const auto& InputLayout = GraphicsPipeline.InputLayout;
+ LayoutElement* pLayoutElements = MemPool.Allocate<LayoutElement>(InputLayout.NumElements);
+ for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem)
+ {
+ const auto& SrcElem = InputLayout.LayoutElements[Elem];
+ pLayoutElements[Elem] = SrcElem;
+ VERIFY_EXPR(SrcElem.HLSLSemantic != nullptr);
+ pLayoutElements[Elem].HLSLSemantic = MemPool.CopyString(SrcElem.HLSLSemantic);
+ }
+ GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements;
+
+
+ // Correct description and compute offsets and tight strides
+ std::array<Uint32, MAX_BUFFER_SLOTS> Strides, TightStrides = {};
+ // Set all strides to an invalid value because an application may want to use 0 stride
+ for (auto& Stride : Strides)
+ Stride = LAYOUT_ELEMENT_AUTO_STRIDE;
+
+ for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
+ {
+ auto& LayoutElem = pLayoutElements[i];
- const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc();
- if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount)
- LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'");
+ if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16)
+ LayoutElem.IsNormalized = false; // Floating point values cannot be normalized
+
+ auto BuffSlot = LayoutElem.BufferSlot;
+ if (BuffSlot >= Strides.size())
+ {
+ UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds the maximum allowed value (", Strides.size() - 1, ")");
+ continue;
+ }
+ VERIFY_EXPR(BuffSlot < m_BufferSlotsUsed);
+
+ auto& CurrAutoStride = TightStrides[BuffSlot];
+ // If offset is not explicitly specified, use current auto stride value
+ if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET)
+ {
+ LayoutElem.RelativeOffset = CurrAutoStride;
+ }
+
+ // If stride is explicitly specified, use it for the current buffer slot
+ if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE)
+ {
+ // Verify that the value is consistent with the previously specified stride, if any
+ if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride)
+ {
+ LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot,
+ ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ",
+ LayoutElem.Stride, ", while current value is ", Strides[BuffSlot],
+ ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow "
+ "the engine compute strides automatically.");
+ }
+ Strides[BuffSlot] = LayoutElem.Stride;
+ }
+
+ CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType));
+ }
+
+ for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
+ {
+ auto& LayoutElem = pLayoutElements[i];
+
+ auto BuffSlot = LayoutElem.BufferSlot;
+ // If no input elements explicitly specified stride for this buffer slot, use automatic stride
+ if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE)
+ {
+ Strides[BuffSlot] = TightStrides[BuffSlot];
}
else
{
- if (GraphicsPipeline.SubpassIndex != 0)
- LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used");
+ if (Strides[BuffSlot] < TightStrides[BuffSlot])
+ {
+ LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot,
+ " is smaller than the minimum stride ", TightStrides[BuffSlot],
+ " required to accomodate all input elements.");
+ }
}
+ if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE)
+ LayoutElem.Stride = Strides[BuffSlot];
+ }
+
+ 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;
}
}
- void CheckRasterizerStateDesc() const
+ void InitializePipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo,
+ LinearAllocator& MemPool)
{
- const auto& RSDesc = this->m_Desc.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");
+ CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool);
}
- void CheckAndCorrectDepthStencilDesc()
+private:
+ static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) noexcept
{
- auto& DSSDesc = this->m_Desc.GraphicsPipeline.DepthStencilDesc;
- if (DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN)
+ if (SrcLayout.Variables != nullptr)
{
- if (DSSDesc.DepthEnable)
- LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled");
- else
- DSSDesc.DepthFunc = DepthStencilStateDesc{}.DepthFunc;
+ MemPool.AddSpace<ShaderResourceVariableDesc>(SrcLayout.NumVariables);
+ for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
+ {
+ VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null");
+ MemPool.AddSpaceForString(SrcLayout.Variables[i].Name);
+ }
}
- auto CheckAndCorrectStencilOpDesc = [&](StencilOpDesc& OpDesc, const char* FaceName) //
+ if (SrcLayout.ImmutableSamplers != nullptr)
{
- if (DSSDesc.StencilEnable)
- {
- if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
- if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
- if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
- if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
- LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled");
- }
- else
+ MemPool.AddSpace<ImmutableSamplerDesc>(SrcLayout.NumImmutableSamplers);
+ for (Uint32 i = 0; i < SrcLayout.NumImmutableSamplers; ++i)
{
- if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
- OpDesc.StencilFailOp = StencilOpDesc{}.StencilFailOp;
- if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
- OpDesc.StencilDepthFailOp = StencilOpDesc{}.StencilDepthFailOp;
- if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
- OpDesc.StencilPassOp = StencilOpDesc{}.StencilPassOp;
- if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
- OpDesc.StencilFunc = StencilOpDesc{}.StencilFunc;
+ VERIFY(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName != nullptr, "Immutable sampler or texture name can't be null");
+ MemPool.AddSpaceForString(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName);
}
- };
- CheckAndCorrectStencilOpDesc(DSSDesc.FrontFace, "FrontFace");
- CheckAndCorrectStencilOpDesc(DSSDesc.BackFace, "BackFace");
+ }
}
- void CheckAndCorrectBlendStateDesc()
+ static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool)
{
- auto& BlendDesc = this->m_Desc.GraphicsPipeline.BlendDesc;
- for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
+ if (SrcLayout.Variables != nullptr)
{
- auto& RTDesc = BlendDesc.RenderTargets[rt];
- // clang-format off
- const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
- const auto LogicOpEnable = RTDesc.LogicOperationEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
- // clang-format on
- if (BlendEnable)
+ auto* Variables = MemPool.Allocate<ShaderResourceVariableDesc>(SrcLayout.NumVariables);
+ DstLayout.Variables = Variables;
+ for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
{
- if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED");
- if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED");
- if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED");
-
- if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
- if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
- if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
- LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED");
+ const auto& SrcVar = SrcLayout.Variables[i];
+ Variables[i] = SrcVar;
+ Variables[i].Name = MemPool.CopyString(SrcVar.Name);
}
- else
+ }
+
+ if (SrcLayout.ImmutableSamplers != nullptr)
+ {
+ auto* ImmutableSamplers = MemPool.Allocate<ImmutableSamplerDesc>(SrcLayout.NumImmutableSamplers);
+ DstLayout.ImmutableSamplers = ImmutableSamplers;
+ for (Uint32 i = 0; i < SrcLayout.NumImmutableSamplers; ++i)
{
- if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
- RTDesc.SrcBlend = RenderTargetBlendDesc{}.SrcBlend;
- if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
- RTDesc.DestBlend = RenderTargetBlendDesc{}.DestBlend;
- if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
- RTDesc.BlendOp = RenderTargetBlendDesc{}.BlendOp;
-
- if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
- RTDesc.SrcBlendAlpha = RenderTargetBlendDesc{}.SrcBlendAlpha;
- if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
- RTDesc.DestBlendAlpha = RenderTargetBlendDesc{}.DestBlendAlpha;
- if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
- RTDesc.BlendOpAlpha = RenderTargetBlendDesc{}.BlendOpAlpha;
- }
+ const auto& SrcSmplr = SrcLayout.ImmutableSamplers[i];
+#ifdef DILIGENT_DEVELOPMENT
+ {
+ const auto& BorderColor = SrcSmplr.Desc.BorderColor;
+ if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) ||
+ (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) ||
+ (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1)))
+ {
+ LOG_WARNING_MESSAGE("Immutable sampler for variable \"", SrcSmplr.SamplerOrTextureName, "\" specifies border color (",
+ BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3],
+ "). D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors");
+ }
+ }
+#endif
- if (!LogicOpEnable)
- RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp;
+ ImmutableSamplers[i] = SrcSmplr;
+ ImmutableSamplers[i].SamplerOrTextureName = MemPool.CopyString(SrcSmplr.SamplerOrTextureName);
+ }
}
}
-#undef LOG_PSO_ERROR_AND_THROW
+
+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 = {};
+
+ RefCntAutoPtr<IRenderPass> m_pRenderPass; ///< Strong reference to the render pass object
+
+ GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp
index 5648e39d..1130fbff 100644
--- a/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp
+++ b/Graphics/GraphicsEngine/include/ShaderResourceVariableBase.hpp
@@ -32,6 +32,7 @@
#include <vector>
+#include "Atomics.hpp"
#include "ShaderResourceVariable.h"
#include "PipelineState.h"
#include "StringTools.hpp"
@@ -114,15 +115,15 @@ inline Uint32 GetAllowedTypeBits(const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVar
return AllowedTypeBits;
}
-inline Int32 FindStaticSampler(const StaticSamplerDesc* StaticSamplers,
- Uint32 NumStaticSamplers,
- SHADER_TYPE ShaderType,
- const char* ResourceName,
- const char* SamplerSuffix)
+inline Int32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers,
+ Uint32 NumImtblSamplers,
+ SHADER_TYPE ShaderType,
+ const char* ResourceName,
+ const char* SamplerSuffix)
{
- for (Uint32 s = 0; s < NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < NumImtblSamplers; ++s)
{
- const auto& StSam = StaticSamplers[s];
+ const auto& StSam = ImtblSamplers[s];
if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(ResourceName, StSam.SamplerOrTextureName, SamplerSuffix))
return s;
}
@@ -214,6 +215,28 @@ inline const char* GetResourceTypeName<BUFFER_VIEW_TYPE>()
return "buffer view";
}
+inline RESOURCE_DIMENSION GetResourceViewDimension(const ITextureView* pTexView)
+{
+ VERIFY_EXPR(pTexView != nullptr);
+ return pTexView->GetDesc().TextureDim;
+}
+
+inline RESOURCE_DIMENSION GetResourceViewDimension(const IBufferView* /*pBuffView*/)
+{
+ return RESOURCE_DIM_BUFFER;
+}
+
+inline Uint32 GetResourceSampleCount(const ITextureView* pTexView)
+{
+ VERIFY_EXPR(pTexView != nullptr);
+ return const_cast<ITextureView*>(pTexView)->GetTexture()->GetDesc().SampleCount;
+}
+
+inline Uint32 GetResourceSampleCount(const IBufferView* /*pBuffView*/)
+{
+ return 0;
+}
+
template <typename ResourceAttribsType,
typename ResourceViewImplType,
typename ViewTypeEnumType>
@@ -254,8 +277,6 @@ bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs,
if (!IsExpectedViewType)
{
- std::string ExpectedViewTypeName;
-
std::stringstream ss;
ss << "Error binding " << ExpectedResourceType << " '" << pViewImpl->GetDesc().Name << "' to variable '"
<< Attribs.GetPrintName(ArrayIndex) << '\'';
@@ -279,11 +300,45 @@ bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs,
BindingOK = false;
}
+
+ const auto ExpectedResourceDim = Attribs.GetResourceDimension();
+ if (ExpectedResourceDim != RESOURCE_DIM_UNDEFINED)
+ {
+ auto ResourceDim = GetResourceViewDimension(pViewImpl);
+ if (ResourceDim != ExpectedResourceDim)
+ {
+ LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '",
+ Attribs.GetPrintName(ArrayIndex), "': incorrect resource dimension: ",
+ GetResourceDimString(ExpectedResourceDim), " is expected, but the actual dimension is ",
+ GetResourceDimString(ResourceDim));
+
+ BindingOK = false;
+ }
+
+ if (ResourceDim == RESOURCE_DIM_TEX_2D || ResourceDim == RESOURCE_DIM_TEX_2D_ARRAY)
+ {
+ auto SampleCount = GetResourceSampleCount(pViewImpl);
+ auto IsMS = Attribs.IsMultisample();
+ if (IsMS && SampleCount == 1)
+ {
+ LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '",
+ Attribs.GetPrintName(ArrayIndex), "': multisample texture is expected.");
+ BindingOK = false;
+ }
+ else if (!IsMS && SampleCount > 1)
+ {
+ LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '",
+ Attribs.GetPrintName(ArrayIndex), "': single-sample texture is expected.");
+ BindingOK = false;
+ }
+ }
+ }
}
if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedView != nullptr && pCachedView != pViewImpl)
{
- auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType);
+ const auto* VarTypeStr = GetShaderVariableTypeLiteralName(VarType);
+
std::stringstream ss;
ss << "Non-null resource '" << pCachedView->GetDesc().Name << "' is already bound to " << VarTypeStr
<< " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\'';
@@ -305,6 +360,7 @@ bool VerifyResourceViewBinding(const ResourceAttribsType& Attribs,
BindingOK = false;
}
+
return BindingOK;
}
@@ -340,7 +396,7 @@ template <typename ResourceLayoutType,
struct ShaderVariableBase : public ResourceVariableBaseInterface
{
ShaderVariableBase(ResourceLayoutType& ParentResLayout) :
- m_ParentResLayout(ParentResLayout)
+ m_ParentResLayout{ParentResLayout}
{
}
diff --git a/Graphics/GraphicsEngine/include/TextureBase.hpp b/Graphics/GraphicsEngine/include/TextureBase.hpp
index 1805f7d3..559df1ea 100644
--- a/Graphics/GraphicsEngine/include/TextureBase.hpp
+++ b/Graphics/GraphicsEngine/include/TextureBase.hpp
@@ -30,13 +30,14 @@
/// \file
/// Implementation of the Diligent::TextureBase template class
+#include <memory>
+
#include "Texture.h"
#include "GraphicsTypes.h"
#include "DeviceObjectBase.hpp"
#include "GraphicsAccessories.hpp"
#include "STDAllocator.hpp"
#include "FormatString.hpp"
-#include <memory>
namespace Diligent
{
diff --git a/Graphics/GraphicsEngine/interface/APIInfo.h b/Graphics/GraphicsEngine/interface/APIInfo.h
index a7596e3f..0ecbd92b 100644
--- a/Graphics/GraphicsEngine/interface/APIInfo.h
+++ b/Graphics/GraphicsEngine/interface/APIInfo.h
@@ -30,7 +30,7 @@
/// \file
/// Diligent API information
-#define DILIGENT_API_VERSION 240074
+#define DILIGENT_API_VERSION 240078
#include "../../../Primitives/interface/BasicTypes.h"
@@ -39,64 +39,65 @@ DILIGENT_BEGIN_NAMESPACE(Diligent)
/// Diligent API Info. This tructure can be used to verify API compatibility.
struct APIInfo
{
- size_t StructSize DEFAULT_INITIALIZER(0);
- int APIVersion DEFAULT_INITIALIZER(0);
- size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0);
- size_t BlendStateDescSize DEFAULT_INITIALIZER(0);
- size_t BufferDescSize DEFAULT_INITIALIZER(0);
- size_t BufferDataSize DEFAULT_INITIALIZER(0);
- size_t BufferFormatSize DEFAULT_INITIALIZER(0);
- size_t BufferViewDescSize DEFAULT_INITIALIZER(0);
- size_t StencilOpDescSize DEFAULT_INITIALIZER(0);
- size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0);
- size_t SamplerCapsSize DEFAULT_INITIALIZER(0);
- size_t TextureCapsSize DEFAULT_INITIALIZER(0);
- size_t DeviceCapsSize DEFAULT_INITIALIZER(0);
- size_t DrawAttribsSize DEFAULT_INITIALIZER(0);
- size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0);
- size_t ViewportSize DEFAULT_INITIALIZER(0);
- size_t RectSize DEFAULT_INITIALIZER(0);
- size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0);
- size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0);
- size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0);
- size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0);
- size_t SwapChainDescSize DEFAULT_INITIALIZER(0);
- size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0);
- size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0);
- size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0);
- size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0);
- size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0);
- size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0);
- size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0);
- size_t BoxSize DEFAULT_INITIALIZER(0);
- size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0);
- size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0);
- size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0);
- size_t StateTransitionDescSize DEFAULT_INITIALIZER(0);
- size_t LayoutElementSize DEFAULT_INITIALIZER(0);
- size_t InputLayoutDescSize DEFAULT_INITIALIZER(0);
- size_t SampleDescSize DEFAULT_INITIALIZER(0);
- size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0);
- size_t StaticSamplerDescSize DEFAULT_INITIALIZER(0);
- size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0);
- size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0);
- size_t ComputePipelineDescSize DEFAULT_INITIALIZER(0);
- size_t PipelineStateDescSize DEFAULT_INITIALIZER(0);
- size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0);
- size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0);
- size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0);
- size_t SamplerDescSize DEFAULT_INITIALIZER(0);
- size_t ShaderDescSize DEFAULT_INITIALIZER(0);
- size_t ShaderMacroSize DEFAULT_INITIALIZER(0);
- size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0);
- size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0);
- size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0);
- size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0);
- size_t TextureDescSize DEFAULT_INITIALIZER(0);
- size_t TextureSubResDataSize DEFAULT_INITIALIZER(0);
- size_t TextureDataSize DEFAULT_INITIALIZER(0);
- size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0);
- size_t TextureViewDescSize DEFAULT_INITIALIZER(0);
+ size_t StructSize DEFAULT_INITIALIZER(0);
+ int APIVersion DEFAULT_INITIALIZER(0);
+ size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0);
+ size_t BlendStateDescSize DEFAULT_INITIALIZER(0);
+ size_t BufferDescSize DEFAULT_INITIALIZER(0);
+ size_t BufferDataSize DEFAULT_INITIALIZER(0);
+ size_t BufferFormatSize DEFAULT_INITIALIZER(0);
+ size_t BufferViewDescSize DEFAULT_INITIALIZER(0);
+ size_t StencilOpDescSize DEFAULT_INITIALIZER(0);
+ size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0);
+ size_t SamplerCapsSize DEFAULT_INITIALIZER(0);
+ size_t TextureCapsSize DEFAULT_INITIALIZER(0);
+ size_t DeviceCapsSize DEFAULT_INITIALIZER(0);
+ size_t DrawAttribsSize DEFAULT_INITIALIZER(0);
+ size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0);
+ size_t ViewportSize DEFAULT_INITIALIZER(0);
+ size_t RectSize DEFAULT_INITIALIZER(0);
+ size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0);
+ size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0);
+ size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0);
+ size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0);
+ size_t SwapChainDescSize DEFAULT_INITIALIZER(0);
+ size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0);
+ size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t BoxSize DEFAULT_INITIALIZER(0);
+ size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0);
+ size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0);
+ size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0);
+ size_t StateTransitionDescSize DEFAULT_INITIALIZER(0);
+ size_t LayoutElementSize DEFAULT_INITIALIZER(0);
+ size_t InputLayoutDescSize DEFAULT_INITIALIZER(0);
+ size_t SampleDescSize DEFAULT_INITIALIZER(0);
+ size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0);
+ size_t ImmutableSamplerDescSize DEFAULT_INITIALIZER(0);
+ size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0);
+ size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0);
+ size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t ComputePipelineStateCreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t PipelineStateDescSize DEFAULT_INITIALIZER(0);
+ size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0);
+ size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0);
+ size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0);
+ size_t SamplerDescSize DEFAULT_INITIALIZER(0);
+ size_t ShaderDescSize DEFAULT_INITIALIZER(0);
+ size_t ShaderMacroSize DEFAULT_INITIALIZER(0);
+ size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0);
+ size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0);
+ size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0);
+ size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0);
+ size_t TextureDescSize DEFAULT_INITIALIZER(0);
+ size_t TextureSubResDataSize DEFAULT_INITIALIZER(0);
+ size_t TextureDataSize DEFAULT_INITIALIZER(0);
+ size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0);
+ size_t TextureViewDescSize DEFAULT_INITIALIZER(0);
};
typedef struct APIInfo APIInfo;
diff --git a/Graphics/GraphicsEngine/interface/GraphicsTypes.h b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
index 56db9e61..85dbcff6 100644
--- a/Graphics/GraphicsEngine/interface/GraphicsTypes.h
+++ b/Graphics/GraphicsEngine/interface/GraphicsTypes.h
@@ -105,7 +105,7 @@ DILIGENT_TYPED_ENUM(USAGE, Uint8)
/// when it is created, since it cannot be changed after creation. \n
/// D3D11 Counterpart: D3D11_USAGE_IMMUTABLE. OpenGL counterpart: GL_STATIC_DRAW
/// \remarks Static buffers do not allow CPU access and must use CPU_ACCESS_NONE flag.
- USAGE_STATIC = 0,
+ USAGE_IMMUTABLE = 0,
/// A resource that requires read and write access by the GPU and can also be occasionally
/// written by the CPU. \n
@@ -213,16 +213,16 @@ DEFINE_FLAG_ENUM_OPERATORS(MAP_FLAGS)
/// - TextureViewDesc to describe texture view type
DILIGENT_TYPED_ENUM(RESOURCE_DIMENSION, Uint8)
{
- RESOURCE_DIM_UNDEFINED = 0, ///< Texture type undefined
- RESOURCE_DIM_BUFFER, ///< Buffer
- RESOURCE_DIM_TEX_1D, ///< One-dimensional texture
- RESOURCE_DIM_TEX_1D_ARRAY, ///< One-dimensional texture array
- RESOURCE_DIM_TEX_2D, ///< Two-dimensional texture
- RESOURCE_DIM_TEX_2D_ARRAY, ///< Two-dimensional texture array
- RESOURCE_DIM_TEX_3D, ///< Three-dimensional texture
- RESOURCE_DIM_TEX_CUBE, ///< Cube-map texture
- RESOURCE_DIM_TEX_CUBE_ARRAY, ///< Cube-map array texture
- RESOURCE_DIM_NUM_DIMENSIONS ///< Helper value that stores the total number of texture types in the enumeration
+ RESOURCE_DIM_UNDEFINED = 0, ///< Texture type undefined
+ RESOURCE_DIM_BUFFER, ///< Buffer
+ RESOURCE_DIM_TEX_1D, ///< One-dimensional texture
+ RESOURCE_DIM_TEX_1D_ARRAY, ///< One-dimensional texture array
+ RESOURCE_DIM_TEX_2D, ///< Two-dimensional texture
+ RESOURCE_DIM_TEX_2D_ARRAY, ///< Two-dimensional texture array
+ RESOURCE_DIM_TEX_3D, ///< Three-dimensional texture
+ RESOURCE_DIM_TEX_CUBE, ///< Cube-map texture
+ RESOURCE_DIM_TEX_CUBE_ARRAY, ///< Cube-map array texture
+ RESOURCE_DIM_NUM_DIMENSIONS ///< Helper value that stores the total number of texture types in the enumeration
};
/// Texture view type
@@ -1517,6 +1517,17 @@ struct DeviceFeatures
/// Indicates if device supports separable programs
DEVICE_FEATURE_STATE SeparablePrograms DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
+ /// Indicates if device supports resource queries from shader objects.
+
+ /// \ note This feature indicates if IShader::GetResourceCount() and IShader::GetResourceDesc() methods
+ /// can be used to query the list of resources of individual shader objects.
+ /// Shader variable queries from pipeline state and shader resource binding objects are always
+ /// available.
+ ///
+ /// The feature is always enabled in Direct3D11, Direct3D12 and Vulkan. It is enabled in
+ /// OpenGL when separable programs are available, and it is always disabled in Metal.
+ DEVICE_FEATURE_STATE ShaderResourceQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
+
/// Indicates if device supports indirect draw commands
DEVICE_FEATURE_STATE IndirectRendering DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
@@ -1621,6 +1632,7 @@ struct DeviceFeatures
explicit DeviceFeatures(DEVICE_FEATURE_STATE State) noexcept :
SeparablePrograms {State},
+ ShaderResourceQueries {State},
IndirectRendering {State},
WireframeFill {State},
MultithreadedResourceCreation {State},
@@ -1653,7 +1665,7 @@ struct DeviceFeatures
UniformBuffer8BitAccess {State}
{
# if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(*this) == 31, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
+ static_assert(sizeof(*this) == 32, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
# endif
}
#endif
@@ -1712,7 +1724,7 @@ struct GraphicsAdapterInfo
/// The amount of local video memory that is inaccessible by CPU, in bytes.
- /// \note Device-local memory is where USAGE_DEFAULT and USAGE_STATIC resources
+ /// \note Device-local memory is where USAGE_DEFAULT and USAGE_IMMUTABLE resources
/// are typically allocated.
///
/// On some devices it may not be possible to query the memory size,
@@ -1881,6 +1893,11 @@ struct EngineGLCreateInfo DILIGENT_DERIVE(EngineCreateInfo)
/// provide additional runtime checking, validation, and logging
/// functionality while possibly incurring performance penalties
bool CreateDebugContext DEFAULT_INITIALIZER(false);
+
+ /// Force using non-separable programs.
+
+ /// Setting this to true is typically needed for testing purposes only.
+ bool ForceNonSeparablePrograms DEFAULT_INITIALIZER(false);
};
typedef struct EngineGLCreateInfo EngineGLCreateInfo;
diff --git a/Graphics/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 2ea0d224..f953b851 100644
--- a/Graphics/GraphicsEngine/interface/PipelineState.h
+++ b/Graphics/GraphicsEngine/interface/PipelineState.h
@@ -96,32 +96,36 @@ struct ShaderResourceVariableDesc
typedef struct ShaderResourceVariableDesc ShaderResourceVariableDesc;
-/// Static sampler description
-struct StaticSamplerDesc
+/// Immutable sampler description.
+
+/// An immutable sampler is compiled into the pipeline state and can't be changed.
+/// It is generally more efficient than a regular sampler and should be used
+/// whenever possible.
+struct ImmutableSamplerDesc
{
- /// Shader stages that this static sampler applies to. More than one shader stage can be specified.
+ /// Shader stages that this immutable sampler applies to. More than one shader stage can be specified.
SHADER_TYPE ShaderStages DEFAULT_INITIALIZER(SHADER_TYPE_UNKNOWN);
/// The name of the sampler itself or the name of the texture variable that
- /// this static sampler is assigned to if combined texture samplers are used.
+ /// this immutable sampler is assigned to if combined texture samplers are used.
const Char* SamplerOrTextureName DEFAULT_INITIALIZER(nullptr);
/// Sampler description
struct SamplerDesc Desc;
#if DILIGENT_CPP_INTERFACE
- StaticSamplerDesc()noexcept{}
+ ImmutableSamplerDesc()noexcept{}
- StaticSamplerDesc(SHADER_TYPE _ShaderStages,
- const Char* _SamplerOrTextureName,
- const SamplerDesc& _Desc)noexcept :
+ ImmutableSamplerDesc(SHADER_TYPE _ShaderStages,
+ const Char* _SamplerOrTextureName,
+ const SamplerDesc& _Desc)noexcept :
ShaderStages {_ShaderStages },
SamplerOrTextureName{_SamplerOrTextureName},
Desc {_Desc }
{}
#endif
};
-typedef struct StaticSamplerDesc StaticSamplerDesc;
+typedef struct ImmutableSamplerDesc ImmutableSamplerDesc;
/// Pipeline layout description
struct PipelineResourceLayoutDesc
@@ -129,19 +133,19 @@ struct PipelineResourceLayoutDesc
/// Default shader resource variable type. This type will be used if shader
/// variable description is not found in the Variables array
/// or if Variables == nullptr
- SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType DEFAULT_INITIALIZER(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
+ SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType DEFAULT_INITIALIZER(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
/// Number of elements in Variables array
- Uint32 NumVariables DEFAULT_INITIALIZER(0);
+ Uint32 NumVariables DEFAULT_INITIALIZER(0);
/// Array of shader resource variable descriptions
- const ShaderResourceVariableDesc* Variables DEFAULT_INITIALIZER(nullptr);
+ const ShaderResourceVariableDesc* Variables DEFAULT_INITIALIZER(nullptr);
- /// Number of static samplers in StaticSamplers array
- Uint32 NumStaticSamplers DEFAULT_INITIALIZER(0);
+ /// Number of immutable samplers in ImmutableSamplers array
+ Uint32 NumImmutableSamplers DEFAULT_INITIALIZER(0);
- /// Array of static sampler descriptions
- const StaticSamplerDesc* StaticSamplers DEFAULT_INITIALIZER(nullptr);
+ /// Array of immutable sampler descriptions
+ const ImmutableSamplerDesc* ImmutableSamplers DEFAULT_INITIALIZER(nullptr);
};
typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc;
@@ -151,29 +155,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;
@@ -348,19 +329,9 @@ 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;
-
- // TODO (AZ): use pointer
- /// Ray tracing pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_RAY_TRACING.
- RayTracingPipelineDesc RayTracingPipeline;
-
#if DILIGENT_CPP_INTERFACE
bool IsAnyGraphicsPipeline() const { return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH; }
- bool IsComputePipeline () const { return PipelineType == PIPELINE_TYPE_COMPUTE; }
+ bool IsComputePipeline() const { return PipelineType == PIPELINE_TYPE_COMPUTE; }
#endif
};
typedef struct PipelineStateDesc PipelineStateDesc;
@@ -370,7 +341,7 @@ typedef struct PipelineStateDesc PipelineStateDesc;
DILIGENT_TYPED_ENUM(PSO_CREATE_FLAGS, Uint32)
{
/// Null flag.
- PSO_CREATE_FLAG_NONE = 0x00,
+ PSO_CREATE_FLAG_NONE = 0x00,
/// Ignore missing variables.
@@ -378,15 +349,15 @@ DILIGENT_TYPED_ENUM(PSO_CREATE_FLAGS, Uint32)
/// provided as part of the pipeline resource layout description
/// that is not found in any of the designated shader stages.
/// Use this flag to silence these warnings.
- PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES = 0x01,
+ PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES = 0x01,
- /// Ignore missing static samplers.
+ /// Ignore missing immutable samplers.
- /// By default, the engine outputs a warning for every static sampler
+ /// By default, the engine outputs a warning for every immutable sampler
/// provided as part of the pipeline resource layout description
/// that is not found in any of the designated shader stages.
/// Use this flag to silence these warnings.
- PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS = 0x02,
+ PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS = 0x02,
};
DEFINE_FLAG_ENUM_OPERATORS(PSO_CREATE_FLAGS);
@@ -398,10 +369,57 @@ 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);
+
+#if DILIGENT_CPP_INTERFACE
+ ComputePipelineStateCreateInfo() noexcept
+ {
+ PSODesc.PipelineType = PIPELINE_TYPE_COMPUTE;
+ }
+#endif
+};
+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}};
@@ -419,10 +437,13 @@ 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.
+ /// This method must only be called for a graphics or mesh pipeline.
+ VIRTUAL const GraphicsPipelineDesc REF METHOD(GetGraphicsPipelineDesc)(THIS) CONST PURE;
/// Binds resources for all shaders in the pipeline state
@@ -512,6 +533,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 027d0f5c..19d98a94 100644
--- a/Graphics/GraphicsEngine/interface/RenderDevice.h
+++ b/Graphics/GraphicsEngine/interface/RenderDevice.h
@@ -78,7 +78,7 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject)
/// \param [in] BuffDesc - Buffer description, see Diligent::BufferDesc for details.
/// \param [in] pBuffData - Pointer to Diligent::BufferData structure that describes
/// initial buffer data or nullptr if no data is provided.
- /// Static buffers (USAGE_STATIC) must be initialized at creation time.
+ /// Immutable buffers (USAGE_IMMUTABLE) must be initialized at creation time.
/// \param [out] ppBuffer - Address of the memory location where the pointer to the
/// buffer interface will be stored. The function calls AddRef(),
/// so that the new buffer will contain one reference and must be
@@ -109,7 +109,7 @@ DILIGENT_BEGIN_INTERFACE(IRenderDevice, IObject)
/// \param [in] TexDesc - Texture description, see Diligent::TextureDesc for details.
/// \param [in] pData - Pointer to Diligent::TextureData structure that describes
/// initial texture data or nullptr if no data is provided.
- /// Static textures (USAGE_STATIC) must be initialized at creation time.
+ /// Immutable textures (USAGE_IMMUTABLE) must be initialized at creation time.
///
/// \param [out] ppTexture - Address of the memory location where the pointer to the
/// texture interface will be stored.
@@ -156,17 +156,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 - Graphics pipeline state create info, see Diligent::GraphicsPipelineStateCreateInfo for details.
/// \param [out] ppPipelineState - Address of the memory location where the pointer to the
/// pipeline state interface will be stored.
/// The function calls AddRef(), so that the new object will contain
/// 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 - Compute pipeline state create info, see Diligent::ComputePipelineStateCreateInfo for details.
+ /// \param [out] ppPipelineState - Address of the memory location where the pointer to the
+ /// pipeline state interface will be stored.
+ /// The function calls AddRef(), so that the new object will contain
+ /// one reference.
+ VIRTUAL void METHOD(CreateComputePipelineState)(THIS_
+ const ComputePipelineStateCreateInfo REF PSOCreateInfo,
+ IPipelineState** ppPipelineState) PURE;
/// Creates a new fence object
@@ -312,20 +322,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/interface/Shader.h b/Graphics/GraphicsEngine/interface/Shader.h
index 03dc06f0..950ecc77 100644
--- a/Graphics/GraphicsEngine/interface/Shader.h
+++ b/Graphics/GraphicsEngine/interface/Shader.h
@@ -352,7 +352,9 @@ DILIGENT_TYPED_ENUM(SHADER_RESOURCE_TYPE, Uint8)
SHADER_RESOURCE_TYPE_SAMPLER,
/// Input attachment in a render pass
- SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT
+ SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT,
+
+ SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT
};
// clang-format on
diff --git a/Graphics/GraphicsEngine/src/APIInfo.cpp b/Graphics/GraphicsEngine/src/APIInfo.cpp
index f71b943e..e4111327 100644
--- a/Graphics/GraphicsEngine/src/APIInfo.cpp
+++ b/Graphics/GraphicsEngine/src/APIInfo.cpp
@@ -87,10 +87,11 @@ static APIInfo InitAPIInfo()
INIT_STRUCTURE_SIZE(InputLayoutDesc);
INIT_STRUCTURE_SIZE(SampleDesc);
INIT_STRUCTURE_SIZE(ShaderResourceVariableDesc);
- INIT_STRUCTURE_SIZE(StaticSamplerDesc);
+ INIT_STRUCTURE_SIZE(ImmutableSamplerDesc);
INIT_STRUCTURE_SIZE(PipelineResourceLayoutDesc);
INIT_STRUCTURE_SIZE(GraphicsPipelineDesc);
- INIT_STRUCTURE_SIZE(ComputePipelineDesc);
+ INIT_STRUCTURE_SIZE(GraphicsPipelineStateCreateInfo);
+ INIT_STRUCTURE_SIZE(ComputePipelineStateCreateInfo);
INIT_STRUCTURE_SIZE(PipelineStateDesc);
INIT_STRUCTURE_SIZE(RasterizerStateDesc);
INIT_STRUCTURE_SIZE(ResourceMappingEntry);
diff --git a/Graphics/GraphicsEngine/src/BufferBase.cpp b/Graphics/GraphicsEngine/src/BufferBase.cpp
index c42fd698..aab770fd 100644
--- a/Graphics/GraphicsEngine/src/BufferBase.cpp
+++ b/Graphics/GraphicsEngine/src/BufferBase.cpp
@@ -74,7 +74,7 @@ void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps)
switch (Desc.Usage)
{
- case USAGE_STATIC:
+ case USAGE_IMMUTABLE:
case USAGE_DEFAULT:
VERIFY_BUFFER(Desc.CPUAccessFlags == CPU_ACCESS_NONE, "static and default buffers can't have any CPU access flags set.");
break;
@@ -117,8 +117,8 @@ void ValidateBufferDesc(const BufferDesc& Desc, const DeviceCaps& deviceCaps)
void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData)
{
- if (Desc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr))
- LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as static buffers must be initialized at creation time.");
+ if (Desc.Usage == USAGE_IMMUTABLE && (pBuffData == nullptr || pBuffData->pData == nullptr))
+ LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as immutable buffers must be initialized at creation time.");
if (Desc.Usage == USAGE_DYNAMIC && pBuffData != nullptr && pBuffData->pData != nullptr)
LOG_BUFFER_ERROR_AND_THROW("initial data must be null for dynamic buffers.");
diff --git a/Graphics/GraphicsEngine/src/PipelineStateBase.cpp b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp
new file mode 100644
index 00000000..fedc332d
--- /dev/null
+++ b/Graphics/GraphicsEngine/src/PipelineStateBase.cpp
@@ -0,0 +1,260 @@
+/*
+ * Copyright 2019-2020 Diligent Graphics LLC
+ * Copyright 2015-2019 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#include "pch.h"
+#include "PipelineStateBase.hpp"
+
+namespace Diligent
+{
+
+#define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(PSODesc.PipelineType), " PSO '", PSODesc.Name, "' is invalid: ", ##__VA_ARGS__)
+
+namespace
+{
+
+void ValidateRasterizerStateDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false)
+{
+ const auto& RSDesc = GraphicsPipeline.RasterizerDesc;
+ if (RSDesc.FillMode == FILL_MODE_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED");
+ if (RSDesc.CullMode == CULL_MODE_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED");
+}
+
+void ValidateDepthStencilDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false)
+{
+ const auto& DSSDesc = GraphicsPipeline.DepthStencilDesc;
+ if (DSSDesc.DepthEnable && DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN)
+ LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled");
+
+ auto CheckStencilOpDesc = [&](const StencilOpDesc& OpDesc, const char* FaceName) //
+ {
+ if (DSSDesc.StencilEnable)
+ {
+ if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
+ if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
+ if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
+ if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
+ LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled");
+ }
+ };
+ CheckStencilOpDesc(DSSDesc.FrontFace, "FrontFace");
+ CheckStencilOpDesc(DSSDesc.BackFace, "BackFace");
+}
+
+void CorrectDepthStencilDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept
+{
+ auto& DSSDesc = GraphicsPipeline.DepthStencilDesc;
+ if (!DSSDesc.DepthEnable && DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN)
+ DSSDesc.DepthFunc = DepthStencilStateDesc{}.DepthFunc;
+
+ auto CorrectStencilOpDesc = [&](StencilOpDesc& OpDesc) //
+ {
+ if (!DSSDesc.StencilEnable)
+ {
+ if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
+ OpDesc.StencilFailOp = StencilOpDesc{}.StencilFailOp;
+ if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
+ OpDesc.StencilDepthFailOp = StencilOpDesc{}.StencilDepthFailOp;
+ if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
+ OpDesc.StencilPassOp = StencilOpDesc{}.StencilPassOp;
+ if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
+ OpDesc.StencilFunc = StencilOpDesc{}.StencilFunc;
+ }
+ };
+ CorrectStencilOpDesc(DSSDesc.FrontFace);
+ CorrectStencilOpDesc(DSSDesc.BackFace);
+}
+
+void ValidateBlendStateDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false)
+{
+ const auto& BlendDesc = GraphicsPipeline.BlendDesc;
+ for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
+ {
+ auto& RTDesc = BlendDesc.RenderTargets[rt];
+
+ const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
+ if (BlendEnable)
+ {
+ if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED");
+ if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED");
+ if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED");
+
+ if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
+ if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
+ if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
+ LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED");
+ }
+ }
+}
+
+void CorrectBlendStateDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept
+{
+ auto& BlendDesc = GraphicsPipeline.BlendDesc;
+ for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
+ {
+ auto& RTDesc = BlendDesc.RenderTargets[rt];
+ // clang-format off
+ const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
+ const auto LogicOpEnable = RTDesc.LogicOperationEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
+ // clang-format on
+ if (!BlendEnable)
+ {
+ if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
+ RTDesc.SrcBlend = RenderTargetBlendDesc{}.SrcBlend;
+ if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
+ RTDesc.DestBlend = RenderTargetBlendDesc{}.DestBlend;
+ if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
+ RTDesc.BlendOp = RenderTargetBlendDesc{}.BlendOp;
+
+ if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
+ RTDesc.SrcBlendAlpha = RenderTargetBlendDesc{}.SrcBlendAlpha;
+ if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
+ RTDesc.DestBlendAlpha = RenderTargetBlendDesc{}.DestBlendAlpha;
+ if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
+ RTDesc.BlendOpAlpha = RenderTargetBlendDesc{}.BlendOpAlpha;
+ }
+
+ if (!LogicOpEnable)
+ RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp;
+ }
+}
+
+} // namespace
+
+#define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \
+ if (Shader != nullptr && Shader->GetDesc().ShaderType != ExpectedType) \
+ { \
+ LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \
+ }
+
+void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false)
+{
+ const auto& PSODesc = CreateInfo.PSODesc;
+ if (PSODesc.PipelineType != PIPELINE_TYPE_GRAPHICS && PSODesc.PipelineType != PIPELINE_TYPE_MESH)
+ LOG_PSO_ERROR_AND_THROW("Pipeline type must be GRAPHICS or MESH");
+
+ const auto& GraphicsPipeline = CreateInfo.GraphicsPipeline;
+
+ ValidateBlendStateDesc(PSODesc, GraphicsPipeline);
+ ValidateRasterizerStateDesc(PSODesc, GraphicsPipeline);
+ ValidateDepthStencilDesc(PSODesc, GraphicsPipeline);
+
+
+ if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS)
+ {
+ if (CreateInfo.pVS == nullptr)
+ LOG_ERROR_AND_THROW("Vertex shader must not be null");
+
+ DEV_CHECK_ERR(CreateInfo.pAS == nullptr && CreateInfo.pMS == nullptr, "Mesh shaders are not supported in graphics pipeline");
+ }
+ else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH)
+ {
+ if (CreateInfo.pMS == nullptr)
+ LOG_ERROR_AND_THROW("Mesh shader must not be null");
+
+ DEV_CHECK_ERR(CreateInfo.pVS == nullptr && CreateInfo.pGS == nullptr && CreateInfo.pDS == nullptr && CreateInfo.pHS == nullptr,
+ "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline");
+ DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout is ignored in a mesh pipeline");
+ DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ||
+ GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED,
+ "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)");
+ }
+
+
+ VALIDATE_SHADER_TYPE(CreateInfo.pVS, SHADER_TYPE_VERTEX, "vertex")
+ VALIDATE_SHADER_TYPE(CreateInfo.pPS, SHADER_TYPE_PIXEL, "pixel")
+ VALIDATE_SHADER_TYPE(CreateInfo.pGS, SHADER_TYPE_GEOMETRY, "geometry")
+ VALIDATE_SHADER_TYPE(CreateInfo.pHS, SHADER_TYPE_HULL, "hull")
+ VALIDATE_SHADER_TYPE(CreateInfo.pDS, SHADER_TYPE_DOMAIN, "domain")
+ VALIDATE_SHADER_TYPE(CreateInfo.pAS, SHADER_TYPE_AMPLIFICATION, "amplification")
+ VALIDATE_SHADER_TYPE(CreateInfo.pMS, SHADER_TYPE_MESH, "mesh")
+
+
+ if (GraphicsPipeline.pRenderPass != nullptr)
+ {
+ if (GraphicsPipeline.NumRenderTargets != 0)
+ LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used");
+ if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN)
+ LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
+
+ for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
+ {
+ if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN)
+ LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
+ }
+
+ const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc();
+ if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount)
+ LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'");
+ }
+ else
+ {
+ for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt)
+ {
+ auto RTVFmt = GraphicsPipeline.RTVFormats[rt];
+ if (RTVFmt != TEX_FORMAT_UNKNOWN)
+ {
+ LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt,
+ " must be set to TEX_FORMAT_UNKNOWN");
+ }
+ }
+
+ if (GraphicsPipeline.SubpassIndex != 0)
+ LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used");
+ }
+}
+
+void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false)
+{
+ const auto& PSODesc = CreateInfo.PSODesc;
+ if (PSODesc.PipelineType != PIPELINE_TYPE_COMPUTE)
+ LOG_PSO_ERROR_AND_THROW("Pipeline type must be COMPUTE");
+
+ if (CreateInfo.pCS == nullptr)
+ LOG_ERROR_AND_THROW("Compute shader must not be null");
+
+ VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute");
+}
+#undef VALIDATE_SHADER_TYPE
+#undef LOG_PSO_ERROR_AND_THROW
+
+void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept
+{
+ CorrectBlendStateDesc(GraphicsPipeline);
+ CorrectDepthStencilDesc(GraphicsPipeline);
+}
+
+} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp b/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp
index 5a87cfd7..96de94f9 100644
--- a/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/D3D11TypeConversions.hpp
@@ -79,7 +79,7 @@ inline D3D11_USAGE UsageToD3D11Usage(USAGE Usage)
switch (Usage)
{
// clang-format off
- case USAGE_STATIC: return D3D11_USAGE_IMMUTABLE;
+ case USAGE_IMMUTABLE: return D3D11_USAGE_IMMUTABLE;
case USAGE_DEFAULT: return D3D11_USAGE_DEFAULT;
case USAGE_DYNAMIC: return D3D11_USAGE_DYNAMIC;
case USAGE_STAGING: return D3D11_USAGE_STAGING;
@@ -93,7 +93,7 @@ inline USAGE D3D11UsageToUsage(D3D11_USAGE D3D11Usage)
switch (D3D11Usage)
{
// clang-format off
- case D3D11_USAGE_IMMUTABLE: return USAGE_STATIC;
+ case D3D11_USAGE_IMMUTABLE: return USAGE_IMMUTABLE;
case D3D11_USAGE_DEFAULT: return USAGE_DEFAULT;
case D3D11_USAGE_DYNAMIC: return USAGE_DYNAMIC;
case D3D11_USAGE_STAGING: return USAGE_STAGING;
diff --git a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp
index 02f922a6..520e9bb0 100644
--- a/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/PipelineStateD3D11Impl.hpp
@@ -36,6 +36,7 @@
#include "ShaderResourceLayoutD3D11.hpp"
#include "SRBMemoryAllocator.hpp"
#include "RenderDeviceD3D11Impl.hpp"
+#include "ShaderD3D11Impl.hpp"
namespace Diligent
{
@@ -48,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;
@@ -117,27 +121,45 @@ public:
const ShaderResourceLayoutD3D11& GetStaticResourceLayout(Uint32 s) const
{
- VERIFY_EXPR(s < m_NumShaders);
+ VERIFY_EXPR(s < GetNumShaderStages());
return m_pStaticResourceLayouts[s];
}
ShaderResourceCacheD3D11& GetStaticResourceCache(Uint32 s)
{
- VERIFY_EXPR(s < m_NumShaders);
+ VERIFY_EXPR(s < GetNumShaderStages());
return m_pStaticResourceCaches[s];
}
- void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const;
+ const ShaderD3D11Impl* GetShaderByType(SHADER_TYPE ShaderType) const;
+ const ShaderD3D11Impl* GetShader(Uint32 Index) const;
+
+ void SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const;
private:
+ template <typename PSOCreateInfoType>
+ void InitInternalObjects(const PSOCreateInfoType& CreateInfo);
+
+ void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
+ const std::vector<std::pair<SHADER_TYPE, ShaderD3D11Impl*>>& ShaderStages);
+
+ void Destruct();
+
CComPtr<ID3D11BlendState> m_pd3d11BlendState;
CComPtr<ID3D11RasterizerState> m_pd3d11RasterizerState;
CComPtr<ID3D11DepthStencilState> m_pd3d11DepthStencilState;
CComPtr<ID3D11InputLayout> m_pd3d11InputLayout;
+ RefCntAutoPtr<ShaderD3D11Impl> m_pVS;
+ RefCntAutoPtr<ShaderD3D11Impl> m_pPS;
+ RefCntAutoPtr<ShaderD3D11Impl> m_pGS;
+ RefCntAutoPtr<ShaderD3D11Impl> m_pDS;
+ RefCntAutoPtr<ShaderD3D11Impl> m_pHS;
+ 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;
@@ -146,20 +168,20 @@ private:
// indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1};
- std::array<Uint16, MAX_SHADERS_IN_PIPELINE + 1> m_StaticSamplerOffsets = {};
- struct StaticSamplerInfo
+ std::array<Uint16, MAX_SHADERS_IN_PIPELINE + 1> m_ImmutableSamplerOffsets = {};
+ struct ImmutableSamplerInfo
{
const D3DShaderResourceAttribs& Attribs;
RefCntAutoPtr<ISampler> pSampler;
- StaticSamplerInfo(const D3DShaderResourceAttribs& _Attribs,
- RefCntAutoPtr<ISampler> _pSampler) :
+ ImmutableSamplerInfo(const D3DShaderResourceAttribs& _Attribs,
+ RefCntAutoPtr<ISampler> _pSampler) :
// clang-format off
Attribs {_Attribs},
pSampler {std::move(_pSampler)}
// clang-format on
{}
};
- std::vector<StaticSamplerInfo, STDAllocatorRawMem<StaticSamplerInfo>> m_StaticSamplers;
+ std::vector<ImmutableSamplerInfo, STDAllocatorRawMem<ImmutableSamplerInfo>> m_ImmutableSamplers;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/RenderDeviceD3D11Impl.hpp
index 2d279b86..8565935d 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,
@@ -132,6 +136,9 @@ public:
Uint64 GetCommandQueueMask() const { return Uint64{1}; }
private:
+ template <typename PSOCreateInfoType>
+ void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState);
+
virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final;
EngineD3D11CreateInfo m_EngineAttribs;
diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp
index eb97dfdc..21437e0f 100644
--- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceBindingD3D11Impl.hpp
@@ -100,6 +100,8 @@ public:
}
private:
+ void Destruct();
+
// The caches are indexed by the shader order in the PSO, not shader index
ShaderResourceCacheD3D11* m_pBoundResourceCaches = nullptr;
ShaderResourceLayoutD3D11* m_pResourceLayouts = nullptr;
diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp
index dc70eec1..7aa7126d 100644
--- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceCacheD3D11.hpp
@@ -51,7 +51,7 @@ namespace Diligent
class ShaderResourceCacheD3D11
{
public:
- ShaderResourceCacheD3D11()
+ ShaderResourceCacheD3D11() noexcept
{}
~ShaderResourceCacheD3D11();
diff --git a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp
index 4b4d13b2..9b2c2d9b 100644
--- a/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp
+++ b/Graphics/GraphicsEngineD3D11/include/ShaderResourceLayoutD3D11.hpp
@@ -47,14 +47,19 @@ namespace Diligent
class ShaderResourceLayoutD3D11
{
public:
- ShaderResourceLayoutD3D11(IObject& Owner,
- std::shared_ptr<const ShaderResourcesD3D11> pSrcResources,
- const PipelineResourceLayoutDesc& ResourceLayout,
- const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes,
- Uint32 NumVarTypes,
- ShaderResourceCacheD3D11& ResourceCache,
- IMemoryAllocator& ResCacheDataAllocator,
- IMemoryAllocator& ResLayoutDataAllocator);
+ ShaderResourceLayoutD3D11(IObject& Owner,
+ ShaderResourceCacheD3D11& ResourceCache) noexcept :
+ m_Owner{Owner},
+ m_ResourceCache{ResourceCache}
+ {
+ }
+
+ void Initialize(std::shared_ptr<const ShaderResourcesD3D11> pSrcResources,
+ const PipelineResourceLayoutDesc& ResourceLayout,
+ const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes,
+ Uint32 NumVarTypes,
+ IMemoryAllocator& ResCacheDataAllocator,
+ IMemoryAllocator& ResLayoutDataAllocator);
~ShaderResourceLayoutD3D11();
// clang-format off
@@ -68,7 +73,7 @@ public:
static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources,
const PipelineResourceLayoutDesc& ResourceLayout,
const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes);
+ Uint32 NumAllowedTypes) noexcept;
void CopyResources(ShaderResourceCacheD3D11& DstCache) const;
diff --git a/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp
index de7c843d..16e77806 100644
--- a/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/BufferD3D11Impl.cpp
@@ -62,8 +62,8 @@ BufferD3D11Impl::BufferD3D11Impl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Unified resources are not supported in Direct3D11");
}
- if (m_Desc.Usage == USAGE_STATIC)
- VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
+ if (m_Desc.Usage == USAGE_IMMUTABLE)
+ VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers");
if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER)
{
diff --git a/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/DeviceContextD3D11Impl.cpp
index c396b15c..9286f3f8 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);
+ const 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;
@@ -179,9 +181,9 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState*
{
#ifdef DILIGENT_DEVELOPMENT
bool ResourcesPresent = false;
- for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaders(); ++s)
+ for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaderStages(); ++s)
{
- auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
+ auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s);
if (pShaderD3D11->GetD3D11Resources()->GetTotalResources() > 0)
ResourcesPresent = true;
}
@@ -206,7 +208,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState*
#endif
auto NumShaders = pShaderResBindingD3D11->GetNumActiveShaders();
- VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaders(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state");
+ VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaderStages(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state");
#ifdef DILIGENT_DEVELOPMENT
{
@@ -233,7 +235,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState*
const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType);
#ifdef DILIGENT_DEVELOPMENT
- auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
+ auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s);
VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType);
#endif
@@ -380,7 +382,7 @@ void DeviceContextD3D11Impl::TransitionAndCommitShaderResources(IPipelineState*
const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType);
#ifdef DILIGENT_DEVELOPMENT
- auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
+ auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s);
VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType);
#endif
@@ -671,9 +673,9 @@ void DeviceContextD3D11Impl::SetBlendFactors(const float* pBlendFactors)
{
Uint32 SampleMask = 0xFFFFFFFF;
ID3D11BlendState* pd3d11BS = nullptr;
- if (m_pPipelineState)
+ if (m_pPipelineState && m_pPipelineState->GetDesc().IsAnyGraphicsPipeline())
{
- SampleMask = m_pPipelineState->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 39a6ca4a..108f149c 100644
--- a/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/PipelineStateD3D11Impl.cpp
@@ -31,49 +31,74 @@
#include "RenderDeviceD3D11Impl.hpp"
#include "ShaderResourceBindingD3D11Impl.hpp"
#include "EngineMemory.h"
-#include "ShaderD3D11Impl.hpp"
namespace Diligent
{
-PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
- RenderDeviceD3D11Impl* pRenderDeviceD3D11,
- const PipelineStateCreateInfo& CreateInfo) :
+template <typename PSOCreateInfoType>
+void PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo)
+{
+ m_ResourceLayoutIndex.fill(-1);
+
+ std::vector<std::pair<SHADER_TYPE, ShaderD3D11Impl*>> ShaderStages;
+ ExtractShaders<ShaderD3D11Impl>(CreateInfo, ShaderStages);
+
+ const auto NumShaderStages = GetNumShaderStages();
+ VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size());
+
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ MemPool.AddSpace<ShaderResourceCacheD3D11>(NumShaderStages);
+ MemPool.AddSpace<ShaderResourceLayoutD3D11>(NumShaderStages);
+
+ ReserveSpaceForPipelineDesc(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ m_pStaticResourceCaches = MemPool.ConstructArray<ShaderResourceCacheD3D11>(NumShaderStages);
+
+ // The memory is now owned by PipelineStateD3D11Impl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_pStaticResourceCaches);
+ (void)Ptr;
+
+ m_pStaticResourceLayouts = MemPool.Allocate<ShaderResourceLayoutD3D11>(NumShaderStages);
+ for (Uint32 i = 0; i < NumShaderStages; ++i)
+ new (m_pStaticResourceLayouts + i) ShaderResourceLayoutD3D11{*this, m_pStaticResourceCaches[i]}; // noexcept
+
+ InitializePipelineDesc(CreateInfo, MemPool);
+
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
+
+ InitResourceLayouts(CreateInfo, ShaderStages);
+}
+
+
+PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
+ RenderDeviceD3D11Impl* pRenderDeviceD3D11,
+ const GraphicsPipelineStateCreateInfo& CreateInfo) :
// clang-format off
TPipelineStateBase
{
pRefCounters,
pRenderDeviceD3D11,
- CreateInfo.PSODesc
+ CreateInfo
},
m_SRBMemAllocator{GetRawAllocator()},
- m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector<StaticSamplerInfo>"))
+ m_ImmutableSamplers (STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector<ImmutableSamplerInfo>"))
// clang-format on
{
- m_ResourceLayoutIndex.fill(-1);
-
- if (m_Desc.IsComputePipeline())
+ try
{
- auto* pCS = ValidatedCast<ShaderD3D11Impl>(m_Desc.ComputePipeline.pCS);
- m_pCS = pCS;
- if (m_pCS == nullptr)
- {
- LOG_ERROR_AND_THROW("Compute shader is null");
- }
+ InitInternalObjects(CreateInfo);
- 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)
- {
+ 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) \
{ \
@@ -98,22 +123,22 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR
auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device();
D3D11_BLEND_DESC D3D11BSDesc = {};
- BlendStateDesc_To_D3D11_BLEND_DESC(m_Desc.GraphicsPipeline.BlendDesc, 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);
+ 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);
+ 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;
+ 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>"));
@@ -127,75 +152,141 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR
"Failed to create the Direct3D11 input layout");
}
}
- else
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
+}
+
+PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
+ RenderDeviceD3D11Impl* pRenderDeviceD3D11,
+ const ComputePipelineStateCreateInfo& CreateInfo) :
+ // clang-format off
+ TPipelineStateBase
+ {
+ pRefCounters,
+ pRenderDeviceD3D11,
+ CreateInfo
+ },
+ m_SRBMemAllocator{GetRawAllocator()},
+ m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector<ImmutableSamplerInfo>"))
+// clang-format on
+{
+ try
+ {
+ InitInternalObjects(CreateInfo);
+
+ m_pCS = ValidatedCast<ShaderD3D11Impl>(CreateInfo.pCS);
+ if (m_pCS == nullptr)
+ {
+ LOG_ERROR_AND_THROW("Compute shader is null");
+ }
+
+ if (m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE)
+ {
+ LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(SHADER_TYPE_COMPUTE), " shader is expeceted while ", GetShaderTypeLiteralName(m_pCS->GetDesc().ShaderType), " provided");
+ }
+ m_ShaderResourceLayoutHash = m_pCS->GetD3D11Resources()->GetHash();
+ }
+ catch (...)
{
- UNEXPECTED(GetPipelineTypeString(m_Desc.PipelineType), " pipelines are not supported by Direct3D11 backend");
+ Destruct();
+ throw;
}
+}
- m_pStaticResourceLayouts = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11", ShaderResourceLayoutD3D11, m_NumShaders);
- m_pStaticResourceCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheD3D11", ShaderResourceCacheD3D11, m_NumShaders);
+PipelineStateD3D11Impl::~PipelineStateD3D11Impl()
+{
+ Destruct();
+}
+void PipelineStateD3D11Impl::Destruct()
+{
+ if (m_pStaticResourceLayouts != nullptr)
+ {
+ for (Uint32 l = 0; l < GetNumShaderStages(); ++l)
+ {
+ m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11();
+ }
+ }
+
+ if (m_pStaticResourceCaches != nullptr)
+ {
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
+ {
+ m_pStaticResourceCaches[s].Destroy(GetRawAllocator());
+ m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11();
+ }
+ }
+
+ // All subobjects are allocated in contiguous chunks of memory.
+ if (auto* pRawMem = m_pStaticResourceCaches)
+ GetRawAllocator().Free(pRawMem);
+}
+
+IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase)
+
+
+void PipelineStateD3D11Impl::InitResourceLayouts(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 < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < ShaderStages.size(); ++s)
{
- auto* pShader = GetShader<const ShaderD3D11Impl>(s);
+ auto* pShader = ShaderStages[s].second;
pResources[s] = &(*pShader->GetD3D11Resources());
}
- ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, m_NumShaders,
+ ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(),
(CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
- (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0);
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0);
}
#endif
- decltype(m_StaticSamplers) StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector<StaticSamplerInfo>"));
+ decltype(m_ImmutableSamplers) ImmutableSamplers{STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector<ImmutableSamplerInfo>")};
+
std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderResLayoutDataSizes = {};
std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderResCacheDataSizes = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < ShaderStages.size(); ++s)
{
- const auto* pShader = GetShader<const ShaderD3D11Impl>(s);
- const auto& ShaderDesc = pShader->GetDesc();
- const auto& ShaderResources = *pShader->GetD3D11Resources();
- VERIFY_EXPR(ShaderDesc.ShaderType == ShaderResources.GetShaderType());
+ const auto* pShader = ShaderStages[s].second;
+ const auto& ShaderDesc = pShader->GetDesc();
+ const auto& Resources = *pShader->GetD3D11Resources();
+ VERIFY_EXPR(ShaderDesc.ShaderType == Resources.GetShaderType());
- new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D11;
- // Do not initialize the cache as this will be performed by the resource layout
+ // The cache will be initialized by the resource layout
// Shader resource layout will only contain dynamic and mutable variables
const SHADER_RESOURCE_VARIABLE_TYPE StaticVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
- // clang-format off
- new (m_pStaticResourceLayouts + s)
- ShaderResourceLayoutD3D11
- {
- *this,
- pShader->GetD3D11Resources(),
- m_Desc.ResourceLayout,
- StaticVarTypes,
- _countof(StaticVarTypes),
- m_pStaticResourceCaches[s],
- GetRawAllocator(),
- GetRawAllocator()
- };
- // clang-format on
-
- // Initialize static samplers
- for (Uint32 sam = 0; sam < ShaderResources.GetNumSamplers(); ++sam)
+ m_pStaticResourceLayouts[s].Initialize(
+ pShader->GetD3D11Resources(),
+ m_Desc.ResourceLayout,
+ StaticVarTypes,
+ _countof(StaticVarTypes),
+ GetRawAllocator(),
+ GetRawAllocator() //
+ );
+
+ // Initialize immutable samplers
+ for (Uint32 sam = 0; sam < Resources.GetNumSamplers(); ++sam)
{
- const auto& SamplerAttribs = ShaderResources.GetSampler(sam);
- constexpr bool LogStaticSamplerArrayError = true;
- auto SrcStaticSamplerInd = ShaderResources.FindStaticSampler(SamplerAttribs, ResourceLayout, LogStaticSamplerArrayError);
- if (SrcStaticSamplerInd >= 0)
+ const auto& SamplerAttribs = Resources.GetSampler(sam);
+ constexpr bool LogImtblSamplerArrayError = true;
+ auto SrcImtblSamplerInd = Resources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError);
+ if (SrcImtblSamplerInd >= 0)
{
- const auto& SrcStaticSamplerInfo = ResourceLayout.StaticSamplers[SrcStaticSamplerInd];
- RefCntAutoPtr<ISampler> pStaticSampler;
- pRenderDeviceD3D11->CreateSampler(SrcStaticSamplerInfo.Desc, &pStaticSampler);
- StaticSamplers.emplace_back(SamplerAttribs, std::move(pStaticSampler));
+ const auto& SrcImtblSamplerInfo = ResourceLayout.ImmutableSamplers[SrcImtblSamplerInd];
+
+ RefCntAutoPtr<ISampler> pImbtlSampler;
+ GetDevice()->CreateSampler(SrcImtblSamplerInfo.Desc, &pImbtlSampler);
+ ImmutableSamplers.emplace_back(SamplerAttribs, std::move(pImbtlSampler));
}
}
- m_StaticSamplerOffsets[s + 1] = static_cast<Uint16>(StaticSamplers.size());
+ m_ImmutableSamplerOffsets[s + 1] = static_cast<Uint16>(ImmutableSamplers.size());
if (m_Desc.SRBAllocationGranularity > 1)
{
@@ -204,8 +295,8 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR
SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE,
SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC //
};
- ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(ShaderResources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes));
- ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(ShaderResources);
+ ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(Resources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes));
+ ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(Resources);
}
auto ShaderInd = GetShaderTypePipelineIndex(ShaderDesc.ShaderType, m_Desc.PipelineType);
@@ -214,40 +305,20 @@ PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pR
if (m_Desc.SRBAllocationGranularity > 1)
{
- m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderResLayoutDataSizes.data(), m_NumShaders, ShaderResCacheDataSizes.data());
+ m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderResLayoutDataSizes.data(), GetNumShaderStages(), ShaderResCacheDataSizes.data());
}
- m_StaticSamplers.reserve(StaticSamplers.size());
- for (auto& Sam : StaticSamplers)
- m_StaticSamplers.emplace_back(std::move(Sam));
+ m_ImmutableSamplers.reserve(ImmutableSamplers.size());
+ for (auto& ImtblSam : ImmutableSamplers)
+ m_ImmutableSamplers.emplace_back(std::move(ImtblSam));
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- // Initialize static samplers in the static resource cache to avoid warning messages
- SetStaticSamplers(m_pStaticResourceCaches[s], s);
+ // Initialize immutable samplers in the static resource cache to avoid warning messages
+ SetImmutableSamplers(m_pStaticResourceCaches[s], s);
}
}
-
-PipelineStateD3D11Impl::~PipelineStateD3D11Impl()
-{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- m_pStaticResourceCaches[s].Destroy(GetRawAllocator());
- m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11();
- }
- GetRawAllocator().Free(m_pStaticResourceCaches);
-
- for (Uint32 l = 0; l < m_NumShaders; ++l)
- {
- m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11();
- }
- GetRawAllocator().Free(m_pStaticResourceLayouts);
-}
-
-IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase)
-
-
ID3D11BlendState* PipelineStateD3D11Impl::GetD3D11BlendState()
{
return m_pd3d11BlendState;
@@ -270,9 +341,8 @@ ID3D11InputLayout* PipelineStateD3D11Impl::GetD3D11InputLayout()
void PipelineStateD3D11Impl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources)
{
- auto* pRenderDeviceD3D11 = ValidatedCast<RenderDeviceD3D11Impl>(GetDevice());
- auto& SRBAllocator = pRenderDeviceD3D11->GetSRBAllocator();
- auto pShaderResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingD3D11Impl instance", ShaderResourceBindingD3D11Impl)(this, false);
+ auto& SRBAllocator = GetDevice()->GetSRBAllocator();
+ auto pShaderResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingD3D11Impl instance", ShaderResourceBindingD3D11Impl)(this, false);
if (InitStaticResources)
pShaderResBinding->InitializeStaticResources(nullptr);
pShaderResBinding->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast<IObject**>(static_cast<IShaderResourceBinding**>(ppShaderResourceBinding)));
@@ -289,13 +359,13 @@ bool PipelineStateD3D11Impl::IsCompatibleWith(const IPipelineState* pPSO) const
if (m_ShaderResourceLayoutHash != pPSOD3D11->m_ShaderResourceLayoutHash)
return false;
- if (m_NumShaders != pPSOD3D11->m_NumShaders)
+ if (GetNumShaderStages() != pPSOD3D11->GetNumShaderStages())
return false;
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- auto* pShader0 = GetShader<const ShaderD3D11Impl>(s);
- auto* pShader1 = pPSOD3D11->GetShader<const ShaderD3D11Impl>(s);
+ auto* pShader0 = GetShader(s);
+ auto* pShader1 = pPSOD3D11->GetShader(s);
if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType)
return false;
const auto& Res0 = *pShader0->GetD3D11Resources();
@@ -352,7 +422,7 @@ ID3D11ComputeShader* PipelineStateD3D11Impl::GetD3D11ComputeShader()
void PipelineStateD3D11Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
auto& StaticResLayout = m_pStaticResourceLayouts[s];
if ((ShaderFlags & StaticResLayout.GetShaderType()) != 0)
@@ -366,7 +436,7 @@ Uint32 PipelineStateD3D11Impl::GetStaticVariableCount(SHADER_TYPE ShaderType) co
if (LayoutInd < 0)
return 0;
- VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= m_NumShaders);
+ VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= GetNumShaderStages());
return m_pStaticResourceLayouts[LayoutInd].GetTotalResourceCount();
}
@@ -376,7 +446,7 @@ IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByName(SHADER_
if (LayoutInd < 0)
return nullptr;
- VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= m_NumShaders);
+ VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= GetNumShaderStages());
return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Name);
}
@@ -386,23 +456,48 @@ IShaderResourceVariable* PipelineStateD3D11Impl::GetStaticVariableByIndex(SHADER
if (LayoutInd < 0)
return nullptr;
- VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= m_NumShaders);
+ VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= GetNumShaderStages());
return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Index);
}
-void PipelineStateD3D11Impl::SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const
+void PipelineStateD3D11Impl::SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const
{
auto NumCachedSamplers = ResourceCache.GetSamplerCount();
- for (Uint32 s = m_StaticSamplerOffsets[ShaderInd]; s < m_StaticSamplerOffsets[ShaderInd + 1]; ++s)
+ for (Uint32 s = m_ImmutableSamplerOffsets[ShaderInd]; s < m_ImmutableSamplerOffsets[ShaderInd + 1]; ++s)
{
- auto& SamplerInfo = m_StaticSamplers[s];
+ auto& SamplerInfo = m_ImmutableSamplers[s];
const auto& SamAttribs = SamplerInfo.Attribs;
auto* pSamplerD3D11Impl = SamplerInfo.pSampler.RawPtr<SamplerD3D11Impl>();
- // Limiting EndBindPoint is required when initializing static samplers in a Shader's static cache
+ // Limiting EndBindPoint is required when initializing immutable samplers in a Shader's static cache
auto EndBindPoint = std::min(static_cast<Uint32>(SamAttribs.BindPoint) + SamAttribs.BindCount, NumCachedSamplers);
for (Uint32 BindPoint = SamAttribs.BindPoint; BindPoint < EndBindPoint; ++BindPoint)
ResourceCache.SetSampler(BindPoint, pSamplerD3D11Impl);
}
}
+const ShaderD3D11Impl* PipelineStateD3D11Impl::GetShaderByType(SHADER_TYPE ShaderType) const
+{
+ switch (ShaderType)
+ {
+ // clang-format off
+ case SHADER_TYPE_VERTEX: return m_pVS;
+ case SHADER_TYPE_PIXEL: return m_pPS;
+ case SHADER_TYPE_GEOMETRY: return m_pGS;
+ case SHADER_TYPE_HULL: return m_pHS;
+ case SHADER_TYPE_DOMAIN: return m_pDS;
+ case SHADER_TYPE_COMPUTE: return m_pCS;
+ default: UNEXPECTED("unsupported shader type"); return nullptr;
+ // clang-format on
+ }
+}
+
+const ShaderD3D11Impl* PipelineStateD3D11Impl::GetShader(Uint32 Index) const
+{
+ if (Index < GetNumShaderStages())
+ return GetShaderByType(GetShaderStageType(Index));
+
+ UNEXPECTED("Shader index is out of range");
+ return nullptr;
+}
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp
index d0d4957b..06cda6ad 100644
--- a/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/RenderDeviceD3D11Impl.cpp
@@ -177,7 +177,7 @@ RenderDeviceD3D11Impl::RenderDeviceD3D11Impl(IReferenceCounters* pRefCo
#undef UNSUPPORTED_FEATURE
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
+ static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
#endif
auto& TexCaps = m_DeviceCaps.TexCaps;
@@ -255,7 +255,7 @@ void RenderDeviceD3D11Impl::CreateBufferFromD3DResource(ID3D11Buffer* pd3d11Buff
CreateDeviceObject("buffer", BuffDesc, ppBuffer,
[&]() //
{
- BufferD3D11Impl* pBufferD3D11(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d11Buffer));
+ BufferD3D11Impl* pBufferD3D11{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d11Buffer)};
pBufferD3D11->QueryInterface(IID_Buffer, reinterpret_cast<IObject**>(ppBuffer));
pBufferD3D11->CreateDefaultViews();
OnCreateDeviceObject(pBufferD3D11);
@@ -267,7 +267,7 @@ void RenderDeviceD3D11Impl::CreateBuffer(const BufferDesc& BuffDesc, const Buffe
CreateDeviceObject("buffer", BuffDesc, ppBuffer,
[&]() //
{
- BufferD3D11Impl* pBufferD3D11(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData));
+ BufferD3D11Impl* pBufferD3D11{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D11Impl instance", BufferD3D11Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData)};
pBufferD3D11->QueryInterface(IID_Buffer, reinterpret_cast<IObject**>(ppBuffer));
pBufferD3D11->CreateDefaultViews();
OnCreateDeviceObject(pBufferD3D11);
@@ -279,7 +279,7 @@ void RenderDeviceD3D11Impl::CreateShader(const ShaderCreateInfo& ShaderCI, IShad
CreateDeviceObject("shader", ShaderCI.Desc, ppShader,
[&]() //
{
- ShaderD3D11Impl* pShaderD3D11(NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D11Impl instance", ShaderD3D11Impl)(this, ShaderCI));
+ ShaderD3D11Impl* pShaderD3D11{NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D11Impl instance", ShaderD3D11Impl)(this, ShaderCI)};
pShaderD3D11->QueryInterface(IID_Shader, reinterpret_cast<IObject**>(ppShader));
OnCreateDeviceObject(pShaderD3D11);
@@ -296,7 +296,7 @@ void RenderDeviceD3D11Impl::CreateTexture1DFromD3DResource(ID3D11Texture1D* pd3d
CreateDeviceObject("texture", TexDesc, ppTexture,
[&]() //
{
- TextureBaseD3D11* pTextureD3D11 = NEW_RC_OBJ(m_TexObjAllocator, "Texture1D_D3D11 instance", Texture1D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture);
+ TextureBaseD3D11* pTextureD3D11{NEW_RC_OBJ(m_TexObjAllocator, "Texture1D_D3D11 instance", Texture1D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture)};
pTextureD3D11->QueryInterface(IID_Texture, reinterpret_cast<IObject**>(ppTexture));
pTextureD3D11->CreateDefaultViews();
OnCreateDeviceObject(pTextureD3D11);
@@ -313,7 +313,7 @@ void RenderDeviceD3D11Impl::CreateTexture2DFromD3DResource(ID3D11Texture2D* pd3d
CreateDeviceObject("texture", TexDesc, ppTexture,
[&]() //
{
- TextureBaseD3D11* pTextureD3D11 = NEW_RC_OBJ(m_TexObjAllocator, "Texture2D_D3D11 instance", Texture2D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture);
+ TextureBaseD3D11* pTextureD3D11{NEW_RC_OBJ(m_TexObjAllocator, "Texture2D_D3D11 instance", Texture2D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture)};
pTextureD3D11->QueryInterface(IID_Texture, reinterpret_cast<IObject**>(ppTexture));
pTextureD3D11->CreateDefaultViews();
OnCreateDeviceObject(pTextureD3D11);
@@ -330,7 +330,7 @@ void RenderDeviceD3D11Impl::CreateTexture3DFromD3DResource(ID3D11Texture3D* pd3d
CreateDeviceObject("texture", TexDesc, ppTexture,
[&]() //
{
- TextureBaseD3D11* pTextureD3D11 = NEW_RC_OBJ(m_TexObjAllocator, "Texture3D_D3D11 instance", Texture3D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture);
+ TextureBaseD3D11* pTextureD3D11{NEW_RC_OBJ(m_TexObjAllocator, "Texture3D_D3D11 instance", Texture3D_D3D11)(m_TexViewObjAllocator, this, InitialState, pd3d11Texture)};
pTextureD3D11->QueryInterface(IID_Texture, reinterpret_cast<IObject**>(ppTexture));
pTextureD3D11->CreateDefaultViews();
OnCreateDeviceObject(pTextureD3D11);
@@ -378,7 +378,7 @@ void RenderDeviceD3D11Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampl
m_SamplersRegistry.Find(SamplerDesc, reinterpret_cast<IDeviceObject**>(ppSampler));
if (*ppSampler == nullptr)
{
- SamplerD3D11Impl* pSamplerD3D11(NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D11Impl instance", SamplerD3D11Impl)(this, SamplerDesc));
+ SamplerD3D11Impl* pSamplerD3D11{NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D11Impl instance", SamplerD3D11Impl)(this, SamplerDesc)};
pSamplerD3D11->QueryInterface(IID_Sampler, reinterpret_cast<IObject**>(ppSampler));
OnCreateDeviceObject(pSamplerD3D11);
m_SamplersRegistry.Add(SamplerDesc, *ppSampler);
@@ -386,23 +386,35 @@ void RenderDeviceD3D11Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampl
});
}
-void RenderDeviceD3D11Impl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+template <typename PSOCreateInfoType>
+void RenderDeviceD3D11Impl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState)
{
CreateDeviceObject("Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState,
[&]() //
{
- PipelineStateD3D11Impl* pPipelineStateD3D11(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D11Impl instance", PipelineStateD3D11Impl)(this, PSOCreateInfo));
+ PipelineStateD3D11Impl* pPipelineStateD3D11{NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D11Impl instance", PipelineStateD3D11Impl)(this, PSOCreateInfo)};
pPipelineStateD3D11->QueryInterface(IID_PipelineState, reinterpret_cast<IObject**>(ppPipelineState));
OnCreateDeviceObject(pPipelineStateD3D11);
});
}
+
+void RenderDeviceD3D11Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
+void RenderDeviceD3D11Impl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
void RenderDeviceD3D11Impl::CreateFence(const FenceDesc& Desc, IFence** ppFence)
{
CreateDeviceObject("Fence", Desc, ppFence,
[&]() //
{
- FenceD3D11Impl* pFenceD3D11(NEW_RC_OBJ(m_FenceAllocator, "FenceD3D11Impl instance", FenceD3D11Impl)(this, Desc));
+ FenceD3D11Impl* pFenceD3D11{NEW_RC_OBJ(m_FenceAllocator, "FenceD3D11Impl instance", FenceD3D11Impl)(this, Desc)};
pFenceD3D11->QueryInterface(IID_Fence, reinterpret_cast<IObject**>(ppFence));
OnCreateDeviceObject(pFenceD3D11);
});
@@ -413,7 +425,7 @@ void RenderDeviceD3D11Impl::CreateQuery(const QueryDesc& Desc, IQuery** ppQuery)
CreateDeviceObject("Query", Desc, ppQuery,
[&]() //
{
- QueryD3D11Impl* pQueryD3D11(NEW_RC_OBJ(m_QueryAllocator, "QueryD3D11Impl instance", QueryD3D11Impl)(this, Desc));
+ QueryD3D11Impl* pQueryD3D11{NEW_RC_OBJ(m_QueryAllocator, "QueryD3D11Impl instance", QueryD3D11Impl)(this, Desc)};
pQueryD3D11->QueryInterface(IID_Query, reinterpret_cast<IObject**>(ppQuery));
OnCreateDeviceObject(pQueryD3D11);
});
@@ -424,7 +436,7 @@ void RenderDeviceD3D11Impl::CreateRenderPass(const RenderPassDesc& Desc, IRender
CreateDeviceObject("RenderPass", Desc, ppRenderPass,
[&]() //
{
- RenderPassD3D11Impl* pRenderPassD3D11(NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D11Impl instance", RenderPassD3D11Impl)(this, Desc));
+ RenderPassD3D11Impl* pRenderPassD3D11{NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D11Impl instance", RenderPassD3D11Impl)(this, Desc)};
pRenderPassD3D11->QueryInterface(IID_RenderPass, reinterpret_cast<IObject**>(ppRenderPass));
OnCreateDeviceObject(pRenderPassD3D11);
});
@@ -435,7 +447,7 @@ void RenderDeviceD3D11Impl::CreateFramebuffer(const FramebufferDesc& Desc, IFram
CreateDeviceObject("Framebuffer", Desc, ppFramebuffer,
[&]() //
{
- FramebufferD3D11Impl* pFramebufferD3D11(NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D11Impl instance", FramebufferD3D11Impl)(this, Desc));
+ FramebufferD3D11Impl* pFramebufferD3D11{NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D11Impl instance", FramebufferD3D11Impl)(this, Desc)};
pFramebufferD3D11->QueryInterface(IID_Framebuffer, reinterpret_cast<IObject**>(ppFramebuffer));
OnCreateDeviceObject(pFramebufferD3D11);
});
diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp
index 62fd2df7..46833c81 100644
--- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceBindingD3D11Impl.cpp
@@ -31,6 +31,7 @@
#include "DeviceContextD3D11Impl.hpp"
#include "RenderDeviceD3D11Impl.hpp"
#include "ShaderD3D11Impl.hpp"
+#include "LinearAllocator.hpp"
namespace Diligent
{
@@ -49,74 +50,104 @@ ShaderResourceBindingD3D11Impl::ShaderResourceBindingD3D11Impl(IReferenceCounter
m_bIsStaticResourcesBound{false}
// clang-format on
{
- m_ResourceLayoutIndex.fill(-1);
- m_NumActiveShaders = static_cast<Uint8>(pPSO->GetNumShaders());
+ try
+ {
+ m_ResourceLayoutIndex.fill(-1);
+ m_NumActiveShaders = static_cast<Uint8>(pPSO->GetNumShaderStages());
- // clang-format off
- m_pResourceLayouts = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11", ShaderResourceLayoutD3D11, m_NumActiveShaders);
- m_pBoundResourceCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheD3D11", ShaderResourceCacheD3D11, m_NumActiveShaders);
- // clang-format on
+ LinearAllocator MemPool{GetRawAllocator()};
+ MemPool.AddSpace<ShaderResourceCacheD3D11>(m_NumActiveShaders);
+ MemPool.AddSpace<ShaderResourceLayoutD3D11>(m_NumActiveShaders);
- const auto& PSODesc = pPSO->GetDesc();
+ MemPool.Reserve();
- // Reserve memory for resource layouts
- for (Uint8 s = 0; s < m_NumActiveShaders; ++s)
- {
- auto* pShaderD3D11 = pPSO->GetShader<ShaderD3D11Impl>(s);
-
- auto& SRBMemAllocator = pPSO->GetSRBMemoryAllocator();
- auto& ResCacheDataAllocator = SRBMemAllocator.GetResourceCacheDataAllocator(s);
- auto& ResLayoutDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);
-
- // Initialize resource cache to have enough space to contain all shader resources, including static ones
- // Static resources are copied before resources are committed
- const auto& Resources = *pShaderD3D11->GetD3D11Resources();
- new (m_pBoundResourceCaches + s) ShaderResourceCacheD3D11;
- m_pBoundResourceCaches[s].Initialize(Resources, ResCacheDataAllocator);
-
- // Shader resource layout will only contain dynamic and mutable variables
- // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache#Shader-Resource-Cache-Initialization
- SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
- // clang-format off
- new (m_pResourceLayouts + s)
- ShaderResourceLayoutD3D11
- {
- *this,
+ m_pBoundResourceCaches = MemPool.ConstructArray<ShaderResourceCacheD3D11>(m_NumActiveShaders);
+
+ // The memory is now owned by ShaderResourceBindingD3D11Impl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_pBoundResourceCaches);
+ (void)Ptr;
+
+ m_pResourceLayouts = MemPool.Allocate<ShaderResourceLayoutD3D11>(m_NumActiveShaders);
+ for (Uint8 s = 0; s < m_NumActiveShaders; ++s)
+ new (m_pResourceLayouts + s) ShaderResourceLayoutD3D11{*this, m_pBoundResourceCaches[s]}; // noexcept
+
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
+
+ const auto& PSODesc = pPSO->GetDesc();
+
+ // Reserve memory for resource layouts
+ for (Uint8 s = 0; s < m_NumActiveShaders; ++s)
+ {
+ auto* pShaderD3D11 = pPSO->GetShader(s);
+
+ auto& SRBMemAllocator = pPSO->GetSRBMemoryAllocator();
+ auto& ResCacheDataAllocator = SRBMemAllocator.GetResourceCacheDataAllocator(s);
+ auto& ResLayoutDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);
+
+ // Initialize resource cache to have enough space to contain all shader resources, including static ones
+ // Static resources are copied before resources are committed
+ const auto& Resources = *pShaderD3D11->GetD3D11Resources();
+ m_pBoundResourceCaches[s].Initialize(Resources, ResCacheDataAllocator);
+
+ // Shader resource layout will only contain dynamic and mutable variables
+ // http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-cache#Shader-Resource-Cache-Initialization
+ SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+ m_pResourceLayouts[s].Initialize(
pShaderD3D11->GetD3D11Resources(),
PSODesc.ResourceLayout,
VarTypes,
_countof(VarTypes),
- m_pBoundResourceCaches[s],
ResCacheDataAllocator,
- ResLayoutDataAllocator
- };
- // clang-format on
+ ResLayoutDataAllocator //
+ );
- const auto ShaderType = pShaderD3D11->GetDesc().ShaderType;
- const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PSODesc.PipelineType);
- VERIFY_EXPR(ShaderType == m_pResourceLayouts[s].GetShaderType());
- m_ShaderTypes[s] = ShaderType;
+ const auto ShaderType = pShaderD3D11->GetDesc().ShaderType;
+ const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, PSODesc.PipelineType);
+ VERIFY_EXPR(ShaderType == m_pResourceLayouts[s].GetShaderType());
+ m_ShaderTypes[s] = ShaderType;
- m_ResourceLayoutIndex[ShaderInd] = s;
+ m_ResourceLayoutIndex[ShaderInd] = s;
+ }
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
}
}
ShaderResourceBindingD3D11Impl::~ShaderResourceBindingD3D11Impl()
{
- auto* pPSOD3D11Impl = ValidatedCast<PipelineStateD3D11Impl>(m_pPSO);
- for (Uint32 s = 0; s < m_NumActiveShaders; ++s)
+ Destruct();
+}
+
+void ShaderResourceBindingD3D11Impl::Destruct()
+{
+ if (m_pResourceLayouts != nullptr)
+ {
+ for (Int32 l = 0; l < m_NumActiveShaders; ++l)
+ {
+ m_pResourceLayouts[l].~ShaderResourceLayoutD3D11();
+ }
+ }
+
+ if (m_pBoundResourceCaches != nullptr)
{
- auto& Allocator = pPSOD3D11Impl->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(s);
- m_pBoundResourceCaches[s].Destroy(Allocator);
- m_pBoundResourceCaches[s].~ShaderResourceCacheD3D11();
+ auto& SRBMemAllocator = m_pPSO->GetSRBMemoryAllocator();
+ for (Uint32 s = 0; s < m_NumActiveShaders; ++s)
+ {
+ auto& Allocator = SRBMemAllocator.GetResourceCacheDataAllocator(s);
+ m_pBoundResourceCaches[s].Destroy(Allocator);
+ m_pBoundResourceCaches[s].~ShaderResourceCacheD3D11();
+ }
}
- GetRawAllocator().Free(m_pBoundResourceCaches);
- for (Int32 l = 0; l < m_NumActiveShaders; ++l)
+ if (void* pRawMem = m_pBoundResourceCaches)
{
- m_pResourceLayouts[l].~ShaderResourceLayoutD3D11();
+ GetRawAllocator().Free(pRawMem);
}
- GetRawAllocator().Free(m_pResourceLayouts);
}
IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingD3D11Impl, IID_ShaderResourceBindingD3D11, TBase)
@@ -151,14 +182,13 @@ void ShaderResourceBindingD3D11Impl::InitializeStaticResources(const IPipelineSt
}
const auto* pPSOD3D11 = ValidatedCast<const PipelineStateD3D11Impl>(pPipelineState);
- auto ppShaders = pPSOD3D11->GetShaders();
- auto NumShaders = pPSOD3D11->GetNumShaders();
+ auto NumShaders = pPSOD3D11->GetNumShaderStages();
VERIFY_EXPR(NumShaders == m_NumActiveShaders);
for (Uint32 shader = 0; shader < NumShaders; ++shader)
{
const auto& StaticResLayout = pPSOD3D11->GetStaticResourceLayout(shader);
- auto* pShaderD3D11 = ValidatedCast<ShaderD3D11Impl>(ppShaders[shader]);
+ auto* pShaderD3D11 = pPSOD3D11->GetShader(shader);
#ifdef DILIGENT_DEVELOPMENT
if (!StaticResLayout.dvpVerifyBindings())
{
@@ -178,7 +208,7 @@ void ShaderResourceBindingD3D11Impl::InitializeStaticResources(const IPipelineSt
}
#endif
StaticResLayout.CopyResources(m_pBoundResourceCaches[shader]);
- pPSOD3D11->SetStaticSamplers(m_pBoundResourceCaches[shader], shader);
+ pPSOD3D11->SetImmutableSamplers(m_pBoundResourceCaches[shader], shader);
}
m_bIsStaticResourcesBound = true;
diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp
index 28086285..3aaf82b7 100755
--- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceCacheD3D11.cpp
@@ -148,61 +148,60 @@ void ShaderResourceCacheD3D11::Initialize(Uint32 CBCount, Uint32 SRVCount, Uint3
void ShaderResourceCacheD3D11::Destroy(IMemoryAllocator& MemAllocator)
{
- VERIFY(IsInitialized(), "Resource cache is not initialized");
+ if (!IsInitialized())
+ return;
+
VERIFY(m_pdbgMemoryAllocator == &MemAllocator, "The allocator does not match the one used to create resources");
- if (IsInitialized())
+ // Explicitly destory all objects
+ auto CBCount = GetCBCount();
+ if (CBCount != 0)
{
- // Explicitly destory all objects
- auto CBCount = GetCBCount();
- if (CBCount != 0)
- {
- CachedCB* CBs = nullptr;
- ID3D11Buffer** d3d11CBs = nullptr;
- GetCBArrays(CBs, d3d11CBs);
- for (size_t cb = 0; cb < CBCount; ++cb)
- CBs[cb].~CachedCB();
- }
+ CachedCB* CBs = nullptr;
+ ID3D11Buffer** d3d11CBs = nullptr;
+ GetCBArrays(CBs, d3d11CBs);
+ for (size_t cb = 0; cb < CBCount; ++cb)
+ CBs[cb].~CachedCB();
+ }
- auto SRVCount = GetSRVCount();
- if (SRVCount != 0)
- {
- CachedResource* SRVResources = nullptr;
- ID3D11ShaderResourceView** d3d11SRVs = nullptr;
- GetSRVArrays(SRVResources, d3d11SRVs);
- for (size_t srv = 0; srv < SRVCount; ++srv)
- SRVResources[srv].~CachedResource();
- }
+ auto SRVCount = GetSRVCount();
+ if (SRVCount != 0)
+ {
+ CachedResource* SRVResources = nullptr;
+ ID3D11ShaderResourceView** d3d11SRVs = nullptr;
+ GetSRVArrays(SRVResources, d3d11SRVs);
+ for (size_t srv = 0; srv < SRVCount; ++srv)
+ SRVResources[srv].~CachedResource();
+ }
- auto SamplerCount = GetSamplerCount();
- if (SamplerCount != 0)
- {
- CachedSampler* Samplers = nullptr;
- ID3D11SamplerState** d3d11Samplers = nullptr;
- GetSamplerArrays(Samplers, d3d11Samplers);
- for (size_t sam = 0; sam < SamplerCount; ++sam)
- Samplers[sam].~CachedSampler();
- }
+ auto SamplerCount = GetSamplerCount();
+ if (SamplerCount != 0)
+ {
+ CachedSampler* Samplers = nullptr;
+ ID3D11SamplerState** d3d11Samplers = nullptr;
+ GetSamplerArrays(Samplers, d3d11Samplers);
+ for (size_t sam = 0; sam < SamplerCount; ++sam)
+ Samplers[sam].~CachedSampler();
+ }
- auto UAVCount = GetUAVCount();
- if (UAVCount != 0)
- {
- CachedResource* UAVResources = nullptr;
- ID3D11UnorderedAccessView** d3d11UAVs = nullptr;
- GetUAVArrays(UAVResources, d3d11UAVs);
- for (size_t uav = 0; uav < UAVCount; ++uav)
- UAVResources[uav].~CachedResource();
- }
+ auto UAVCount = GetUAVCount();
+ if (UAVCount != 0)
+ {
+ CachedResource* UAVResources = nullptr;
+ ID3D11UnorderedAccessView** d3d11UAVs = nullptr;
+ GetUAVArrays(UAVResources, d3d11UAVs);
+ for (size_t uav = 0; uav < UAVCount; ++uav)
+ UAVResources[uav].~CachedResource();
+ }
- m_SRVOffset = InvalidResourceOffset;
- m_SamplerOffset = InvalidResourceOffset;
- m_UAVOffset = InvalidResourceOffset;
- m_MemoryEndOffset = InvalidResourceOffset;
+ m_SRVOffset = InvalidResourceOffset;
+ m_SamplerOffset = InvalidResourceOffset;
+ m_UAVOffset = InvalidResourceOffset;
+ m_MemoryEndOffset = InvalidResourceOffset;
- if (m_pResourceData != nullptr)
- MemAllocator.Free(m_pResourceData);
- m_pResourceData = nullptr;
- }
+ if (m_pResourceData != nullptr)
+ MemAllocator.Free(m_pResourceData);
+ m_pResourceData = nullptr;
}
ShaderResourceCacheD3D11::~ShaderResourceCacheD3D11()
diff --git a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp
index fd6c7299..f7c1958d 100755
--- a/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/ShaderResourceLayoutD3D11.cpp
@@ -84,11 +84,11 @@ ShaderResourceLayoutD3D11::~ShaderResourceLayoutD3D11()
size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources,
const PipelineResourceLayoutDesc& ResourceLayout,
const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes)
+ Uint32 NumAllowedTypes) noexcept
{
- // Skip static samplers as they are initialized directly in the resource cache by the PSO
- constexpr bool CountStaticSamplers = false;
- auto ResCounters = SrcResources.CountResources(ResourceLayout, AllowedVarTypes, NumAllowedTypes, CountStaticSamplers);
+ // Skip immutable samplers as they are initialized directly in the resource cache by the PSO
+ constexpr bool CountImtblSamplers = false;
+ auto ResCounters = SrcResources.CountResources(ResourceLayout, AllowedVarTypes, NumAllowedTypes, CountImtblSamplers);
// clang-format off
auto MemSize = ResCounters.NumCBs * sizeof(ConstBuffBindInfo) +
ResCounters.NumTexSRVs * sizeof(TexSRVBindInfo) +
@@ -101,28 +101,23 @@ size_t ShaderResourceLayoutD3D11::GetRequiredMemorySize(const ShaderResourcesD3D
}
-ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject& Owner,
- std::shared_ptr<const ShaderResourcesD3D11> pSrcResources,
- const PipelineResourceLayoutDesc& ResourceLayout,
- const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes,
- Uint32 NumVarTypes,
- ShaderResourceCacheD3D11& ResourceCache,
- IMemoryAllocator& ResCacheDataAllocator,
- IMemoryAllocator& ResLayoutDataAllocator) :
- // clang-format off
- m_Owner {Owner},
- m_pResources {std::move(pSrcResources)},
- m_ResourceCache {ResourceCache}
-// clang-format on
+void ShaderResourceLayoutD3D11::Initialize(std::shared_ptr<const ShaderResourcesD3D11> pSrcResources,
+ const PipelineResourceLayoutDesc& ResourceLayout,
+ const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes,
+ Uint32 NumVarTypes,
+ IMemoryAllocator& ResCacheDataAllocator,
+ IMemoryAllocator& ResLayoutDataAllocator)
{
+ m_pResources = std::move(pSrcResources);
+
// http://diligentgraphics.com/diligent-engine/architecture/d3d11/shader-resource-layout#Shader-Resource-Layout-Initialization
const auto AllowedTypeBits = GetAllowedTypeBits(VarTypes, NumVarTypes);
// Count total number of resources of allowed types
- // Skip static samplers as they are initialized directly in the resource cache by the PSO
- constexpr bool CountStaticSamplers = false;
- auto ResCounters = m_pResources->CountResources(ResourceLayout, VarTypes, NumVarTypes, CountStaticSamplers);
+ // Skip immutable samplers as they are initialized directly in the resource cache by the PSO
+ constexpr bool CountImtblSamplers = false;
+ auto ResCounters = m_pResources->CountResources(ResourceLayout, VarTypes, NumVarTypes, CountImtblSamplers);
// Initialize offsets
size_t CurrentOffset = 0;
@@ -192,12 +187,12 @@ ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject&
auto VarType = m_pResources->FindVariableType(Sampler, ResourceLayout);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- // Constructor of PipelineStateD3D11Impl initializes static samplers and will log the error, if any
- constexpr bool LogStaticSamplerArrayError = false;
- auto StaticSamplerInd = m_pResources->FindStaticSampler(Sampler, ResourceLayout, LogStaticSamplerArrayError);
- if (StaticSamplerInd >= 0)
+ // Constructor of PipelineStateD3D11Impl initializes immutable samplers and will log the error, if any
+ constexpr bool LogImtblSamplerArrayError = false;
+ auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sampler, ResourceLayout, LogImtblSamplerArrayError);
+ if (ImtblSamplerInd >= 0)
{
- // Skip static samplers as they are initialized directly in the resource cache by the PSO
+ // Skip immutble samplers as they are initialized directly in the resource cache by the PSO
return;
}
// Initialize current sampler in place, increment sampler counter
@@ -241,10 +236,10 @@ ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject&
AssignedSamplerIndex = TexSRVBindInfo::InvalidSamplerIndex;
#ifdef DILIGENT_DEBUG
// Shader error will be logged by the PipelineStateD3D11Impl
- constexpr bool LogStaticSamplerArrayError = false;
- if (m_pResources->FindStaticSampler(AssignedSamplerAttribs, ResourceLayout, LogStaticSamplerArrayError) < 0)
+ constexpr bool LogImtblSamplerArrayError = false;
+ if (m_pResources->FindImmutableSampler(AssignedSamplerAttribs, ResourceLayout, LogImtblSamplerArrayError) < 0)
{
- UNEXPECTED("Unable to find non-static sampler assigned to texture SRV '", TexSRV.Name, "'.");
+ UNEXPECTED("Unable to find non-immutable sampler assigned to texture SRV '", TexSRV.Name, "'.");
}
#endif
}
@@ -252,10 +247,10 @@ ShaderResourceLayoutD3D11::ShaderResourceLayoutD3D11(IObject&
{
#ifdef DILIGENT_DEBUG
// Shader error will be logged by the PipelineStateD3D11Impl
- constexpr bool LogStaticSamplerArrayError = false;
- if (m_pResources->FindStaticSampler(AssignedSamplerAttribs, ResourceLayout, LogStaticSamplerArrayError) >= 0)
+ constexpr bool LogImtblSamplerArrayError = false;
+ if (m_pResources->FindImmutableSampler(AssignedSamplerAttribs, ResourceLayout, LogImtblSamplerArrayError) >= 0)
{
- UNEXPECTED("Static sampler '", AssignedSamplerAttribs.Name, "' is assigned to texture SRV '", TexSRV.Name, "'.");
+ UNEXPECTED("Immutable sampler '", AssignedSamplerAttribs.Name, "' is assigned to texture SRV '", TexSRV.Name, "'.");
}
#endif
}
@@ -412,7 +407,7 @@ void ShaderResourceLayoutD3D11::CopyResources(ShaderResourceCacheD3D11& DstCache
[&](const SamplerBindInfo& sam) //
{
- //VERIFY(!sam.IsStaticSampler, "Variables are not created for static samplers");
+ //VERIFY(!sam.IsImmutableSampler, "Variables are not created for immutable samplers");
for (auto SamSlot = sam.m_Attribs.BindPoint; SamSlot < sam.m_Attribs.BindPoint + sam.m_Attribs.BindCount; ++SamSlot)
{
VERIFY_EXPR(SamSlot < m_ResourceCache.GetSamplerCount() && SamSlot < DstCache.GetSamplerCount());
@@ -429,7 +424,7 @@ void ShaderResourceLayoutD3D11::ConstBuffBindInfo::BindResource(IDeviceObject* p
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
- RefCntAutoPtr<BufferD3D11Impl> pBuffD3D11Impl(pBuffer, IID_BufferD3D11);
+ RefCntAutoPtr<BufferD3D11Impl> pBuffD3D11Impl{pBuffer, IID_BufferD3D11};
#ifdef DILIGENT_DEVELOPMENT
{
auto& CachedCB = m_ParentResLayout.m_ResourceCache.GetCB(m_Attribs.BindPoint + ArrayIndex);
@@ -448,18 +443,19 @@ void ShaderResourceLayoutD3D11::TexSRVBindInfo::BindResource(IDeviceObject* pVie
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
- RefCntAutoPtr<TextureViewD3D11Impl> pViewD3D11(pView, IID_TextureViewD3D11);
+ RefCntAutoPtr<TextureViewD3D11Impl> pViewD3D11{pView, IID_TextureViewD3D11};
#ifdef DILIGENT_DEVELOPMENT
{
auto& CachedSRV = ResourceCache.GetSRV(m_Attribs.BindPoint + ArrayIndex);
- VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, CachedSRV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
+ VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE},
+ CachedSRV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
}
#endif
if (ValidSamplerAssigned())
{
auto& Sampler = m_ParentResLayout.GetResource<SamplerBindInfo>(SamplerIndex);
- //VERIFY(!Sampler.IsStaticSampler, "Static samplers are not assigned to texture SRVs as they are initialized directly in the shader resource cache");
+ //VERIFY(!Sampler.IsImmutableSampler, "Immutable samplers are not assigned to texture SRVs as they are initialized directly in the shader resource cache");
VERIFY_EXPR(Sampler.m_Attribs.BindCount == m_Attribs.BindCount || Sampler.m_Attribs.BindCount == 1);
auto SamplerBindPoint = Sampler.m_Attribs.BindPoint + (Sampler.m_Attribs.BindCount != 1 ? ArrayIndex : 0);
@@ -501,11 +497,11 @@ void ShaderResourceLayoutD3D11::SamplerBindInfo::BindResource(IDeviceObject* pSa
"Array index (", ArrayIndex, ") is out of range for variable '", m_Attribs.Name,
"'. Max allowed index: ", m_Attribs.BindCount - 1);
auto& ResourceCache = m_ParentResLayout.m_ResourceCache;
- //VERIFY(!IsStaticSampler, "Cannot bind sampler to a static sampler");
+ //VERIFY(!IsImmutableSampler, "Cannot bind sampler to an immutable sampler");
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
- RefCntAutoPtr<SamplerD3D11Impl> pSamplerD3D11(pSampler, IID_SamplerD3D11);
+ RefCntAutoPtr<SamplerD3D11Impl> pSamplerD3D11{pSampler, IID_SamplerD3D11};
#ifdef DILIGENT_DEVELOPMENT
if (pSampler && !pSamplerD3D11)
@@ -548,11 +544,13 @@ void ShaderResourceLayoutD3D11::BuffSRVBindInfo::BindResource(IDeviceObject* pVi
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
- RefCntAutoPtr<BufferViewD3D11Impl> pViewD3D11(pView, IID_BufferViewD3D11);
+ RefCntAutoPtr<BufferViewD3D11Impl> pViewD3D11{pView, IID_BufferViewD3D11};
#ifdef DILIGENT_DEVELOPMENT
{
auto& CachedSRV = ResourceCache.GetSRV(m_Attribs.BindPoint + ArrayIndex);
- VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE}, CachedSRV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
+ VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE},
+ CachedSRV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
+ VerifyBufferViewModeD3D(pViewD3D11.RawPtr(), m_Attribs, m_ParentResLayout.GetShaderName());
}
#endif
ResourceCache.SetBufSRV(m_Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11));
@@ -568,11 +566,12 @@ void ShaderResourceLayoutD3D11::TexUAVBindInfo::BindResource(IDeviceObject* pVie
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
- RefCntAutoPtr<TextureViewD3D11Impl> pViewD3D11(pView, IID_TextureViewD3D11);
+ RefCntAutoPtr<TextureViewD3D11Impl> pViewD3D11{pView, IID_TextureViewD3D11};
#ifdef DILIGENT_DEVELOPMENT
{
auto& CachedUAV = ResourceCache.GetUAV(m_Attribs.BindPoint + ArrayIndex);
- VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_UNORDERED_ACCESS}, CachedUAV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
+ VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {TEXTURE_VIEW_UNORDERED_ACCESS},
+ CachedUAV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
}
#endif
ResourceCache.SetTexUAV(m_Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11));
@@ -588,11 +587,13 @@ void ShaderResourceLayoutD3D11::BuffUAVBindInfo::BindResource(IDeviceObject* pVi
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
- RefCntAutoPtr<BufferViewD3D11Impl> pViewD3D11(pView, IID_BufferViewD3D11);
+ RefCntAutoPtr<BufferViewD3D11Impl> pViewD3D11{pView, IID_BufferViewD3D11};
#ifdef DILIGENT_DEVELOPMENT
{
auto& CachedUAV = ResourceCache.GetUAV(m_Attribs.BindPoint + ArrayIndex);
- VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_UNORDERED_ACCESS}, CachedUAV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
+ VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewD3D11.RawPtr(), {BUFFER_VIEW_UNORDERED_ACCESS},
+ CachedUAV.pView.RawPtr(), m_ParentResLayout.GetShaderName());
+ VerifyBufferViewModeD3D(pViewD3D11.RawPtr(), m_Attribs, m_ParentResLayout.GetShaderName());
}
#endif
ResourceCache.SetBufUAV(m_Attribs.BindPoint + ArrayIndex, std::move(pViewD3D11));
@@ -731,7 +732,7 @@ IShaderResourceVariable* ShaderResourceLayoutD3D11::GetShaderVariable(const Char
if (!m_pResources->IsUsingCombinedTextureSamplers())
{
- // Static samplers are never created in the resource layout
+ // Immutable samplers are never created in the resource layout
if (auto* pSampler = GetResourceByName<SamplerBindInfo>(Name))
return pSampler;
}
diff --git a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp
index 7a744b57..0e9b217b 100644
--- a/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp
+++ b/Graphics/GraphicsEngineD3D11/src/TextureBaseD3D11.cpp
@@ -51,8 +51,8 @@ TextureBaseD3D11::TextureBaseD3D11(IReferenceCounters* pRefCounters,
}
// clang-format on
{
- if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr))
- LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null");
+ if (m_Desc.Usage == USAGE_IMMUTABLE && (pInitData == nullptr || pInitData->pSubResources == nullptr))
+ LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time: pInitData can't be null");
SetState(RESOURCE_STATE_UNDEFINED);
}
diff --git a/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/PipelineStateD3D12Impl.hpp
index a53a625d..fa761fc7 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;
@@ -95,19 +97,19 @@ public:
const ShaderResourceLayoutD3D12& GetShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
return m_pShaderResourceLayouts[ShaderInd];
}
const ShaderResourceLayoutD3D12& GetStaticShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
- return m_pShaderResourceLayouts[m_NumShaders + ShaderInd];
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
+ return m_pShaderResourceLayouts[GetNumShaderStages() + ShaderInd];
}
ShaderResourceCacheD3D12& GetStaticShaderResCache(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
return m_pStaticResourceCaches[ShaderInd];
}
@@ -119,15 +121,34 @@ public:
}
private:
+ struct D3D12PipelineShaderStageInfo
+ {
+ const SHADER_TYPE Type;
+ ShaderD3D12Impl* const pShader;
+ D3D12PipelineShaderStageInfo(SHADER_TYPE _Type,
+ ShaderD3D12Impl* _pShader) :
+ Type{_Type},
+ pShader{_pShader}
+ {}
+ };
+
+ template <typename PSOCreateInfoType>
+ void InitInternalObjects(const PSOCreateInfoType& CreateInfo, std::vector<D3D12PipelineShaderStageInfo>& ShaderStages);
+
+ void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
+ std::vector<D3D12PipelineShaderStageInfo>& ShaderStages);
+
+ void Destruct();
+
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 4dfc86c7..7bdc7801 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,
@@ -174,6 +177,9 @@ public:
D3D_FEATURE_LEVEL GetD3DFeatureLevel() const;
private:
+ template <typename PSOCreateInfoType>
+ void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState);
+
virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final;
void FreeCommandContext(PooledCommandContext&& Ctx);
diff --git a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp
index 2bf6d0b3..232bce65 100644
--- a/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/RootSignature.hpp
@@ -302,7 +302,7 @@ class RootSignature
public:
RootSignature();
- void AllocateStaticSamplers(const PipelineResourceLayoutDesc& ResourceLayout);
+ void AllocateImmutableSamplers(const PipelineResourceLayoutDesc& ResourceLayout);
void Finalize(ID3D12Device* pd3d12Device);
@@ -312,10 +312,10 @@ public:
void InitResourceCache(class RenderDeviceD3D12Impl* pDeviceD3D12Impl, class ShaderResourceCacheD3D12& ResourceCache, IMemoryAllocator& CacheMemAllocator) const;
- void InitStaticSampler(SHADER_TYPE ShaderType,
- const char* SamplerName,
- const char* SamplerSuffix,
- const D3DShaderResourceAttribs& ShaderResAttribs);
+ void InitImmutableSampler(SHADER_TYPE ShaderType,
+ const char* SamplerName,
+ const char* SamplerSuffix,
+ const D3DShaderResourceAttribs& ShaderResAttribs);
void AllocateResourceSlot(SHADER_TYPE ShaderType,
PIPELINE_TYPE PipelineType,
@@ -481,22 +481,22 @@ private:
RootParamsManager m_RootParams;
- struct StaticSamplerAttribs
+ struct ImmutableSamplerAttribs
{
- StaticSamplerDesc SamplerDesc;
+ ImmutableSamplerDesc SamplerDesc;
UINT ShaderRegister = static_cast<UINT>(-1);
UINT ArraySize = 0;
UINT RegisterSpace = 0;
D3D12_SHADER_VISIBILITY ShaderVisibility = static_cast<D3D12_SHADER_VISIBILITY>(-1);
- StaticSamplerAttribs() noexcept {}
- StaticSamplerAttribs(const StaticSamplerDesc& SamDesc, D3D12_SHADER_VISIBILITY Visibility) noexcept :
+ ImmutableSamplerAttribs() noexcept {}
+ ImmutableSamplerAttribs(const ImmutableSamplerDesc& SamDesc, D3D12_SHADER_VISIBILITY Visibility) noexcept :
SamplerDesc(SamDesc),
ShaderVisibility(Visibility)
{}
};
- // Note: sizeof(m_StaticSamplers) == 56 (MS compiler, release x64)
- std::vector<StaticSamplerAttribs, STDAllocatorRawMem<StaticSamplerAttribs>> m_StaticSamplers;
+ // Note: sizeof(m_ImmutableSamplers) == 56 (MS compiler, release x64)
+ std::vector<ImmutableSamplerAttribs, STDAllocatorRawMem<ImmutableSamplerAttribs>> m_ImmutableSamplers;
IMemoryAllocator& m_MemAllocator;
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp
index 846cb329..7be3372d 100644
--- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceBindingD3D12Impl.hpp
@@ -78,6 +78,8 @@ public:
}
private:
+ void Destruct();
+
ShaderResourceCacheD3D12 m_ShaderResourceCache;
ShaderVariableManagerD3D12* m_pShaderVarMgrs = nullptr;
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp
index 1a0362ab..8a8f7b25 100644
--- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceCacheD3D12.hpp
@@ -110,7 +110,7 @@ public:
SRBResources
};
- ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType)
+ ShaderResourceCacheD3D12(DbgCacheContentType dbgContentType) noexcept
// clang-format off
#ifdef DILIGENT_DEBUG
: m_DbgContentType
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp
index e043cf4a..719345fc 100644
--- a/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderResourceLayoutD3D12.hpp
@@ -112,21 +112,24 @@ namespace Diligent
class ShaderResourceLayoutD3D12 final
{
public:
- // There are two modes a layout can be constructed:
+ explicit ShaderResourceLayoutD3D12(IObject& Owner) noexcept :
+ m_Owner{Owner}
+ {}
+
+ // There are two modes a layout can be initialized:
// - initialize static resource layout and initialize shader resource cache to hold static resources
// - initialize reference layouts that address all types of resources (static, mutable, dynamic).
// Root indices and descriptor table offsets are assigned during the initialization;
// no shader resource cache is provided
- ShaderResourceLayoutD3D12(IObject& Owner,
- ID3D12Device* pd3d12Device,
- PIPELINE_TYPE PipelineType,
- const PipelineResourceLayoutDesc& ResourceLayout,
- std::shared_ptr<const ShaderResourcesD3D12> pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheD3D12* pResourceCache,
- class RootSignature* pRootSig);
+ void Initialize(ID3D12Device* pd3d12Device,
+ PIPELINE_TYPE PipelineType,
+ const PipelineResourceLayoutDesc& ResourceLayout,
+ std::shared_ptr<const ShaderResourcesD3D12> pSrcResources,
+ IMemoryAllocator& LayoutDataAllocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* const VarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheD3D12* pResourceCache,
+ class RootSignature* pRootSig);
// clang-format off
ShaderResourceLayoutD3D12 (const ShaderResourceLayoutD3D12&) = delete;
@@ -273,6 +276,8 @@ public:
SHADER_TYPE GetShaderType() const { return m_pResources->GetShaderType(); }
+ const ShaderResourcesD3D12& GetResources() const { return *m_pResources; }
+
private:
const D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv) const;
D3D12Resource& GetAssignedSampler(const D3D12Resource& TexSrv);
diff --git a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp
index 213748d9..c30d8296 100644
--- a/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp
+++ b/Graphics/GraphicsEngineD3D12/include/ShaderVariableD3D12.hpp
@@ -76,12 +76,16 @@ class ShaderVariableD3D12Impl;
class ShaderVariableManagerD3D12
{
public:
- ShaderVariableManagerD3D12(IObject& Owner,
- const ShaderResourceLayoutD3D12& Layout,
- IMemoryAllocator& Allocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheD3D12& ResourceCache);
+ ShaderVariableManagerD3D12(IObject& Owner,
+ ShaderResourceCacheD3D12& ResourceCache) noexcept :
+ m_Owner{Owner},
+ m_ResourceCache{ResourceCache}
+ {}
+
+ void Initialize(const ShaderResourceLayoutD3D12& Layout,
+ IMemoryAllocator& Allocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes);
~ShaderVariableManagerD3D12();
void Destroy(IMemoryAllocator& Allocator);
@@ -120,7 +124,7 @@ private:
Uint32 m_NumVariables = 0;
#ifdef DILIGENT_DEBUG
- IMemoryAllocator& m_DbgAllocator;
+ IMemoryAllocator* m_pDbgAllocator = nullptr;
#endif
// clang-format on
};
diff --git a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
index c89a7423..d7cd54b6 100644
--- a/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/BufferD3D12Impl.cpp
@@ -68,8 +68,8 @@ BufferD3D12Impl::BufferD3D12Impl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Unified resources are not supported in Direct3D12");
}
- if (m_Desc.Usage == USAGE_STATIC)
- VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
+ if (m_Desc.Usage == USAGE_IMMUTABLE)
+ VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers");
if (m_Desc.Usage == USAGE_DYNAMIC)
VERIFY(pBuffData == nullptr || pBuffData->pData == nullptr, "Initial data must be null for dynamic buffers");
diff --git a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
index c833f68e..89c495b9 100644
--- a/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/D3D12TypeConversions.cpp
@@ -321,7 +321,7 @@ D3D12_STATIC_BORDER_COLOR BorderColorToD3D12StaticBorderColor(const Float32 Bord
StaticBorderColor = D3D12_STATIC_BORDER_COLOR_OPAQUE_WHITE;
else
{
- LOG_ERROR_MESSAGE("Static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors.");
+ LOG_ERROR_MESSAGE("D3D12 static samplers only allow transparent black (0,0,0,0), opaque black (0,0,0,1) or opaque white (1,1,1,1) as border colors.");
}
return StaticBorderColor;
}
diff --git a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
index af0b1113..b89b226c 100644
--- a/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/DeviceContextD3D12Impl.cpp
@@ -211,49 +211,60 @@ 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 +975,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 138b6b3d..2d31e70d 100644
--- a/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/PipelineStateD3D12Impl.cpp
@@ -98,155 +98,85 @@ private:
std::array<D3D12_PRIMITIVE_TOPOLOGY_TYPE, PRIMITIVE_TOPOLOGY_NUM_TOPOLOGIES> m_Map;
};
-PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters,
- RenderDeviceD3D12Impl* pDeviceD3D12,
- const PipelineStateCreateInfo& CreateInfo) :
- TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc},
- m_SRBMemAllocator{GetRawAllocator()}
+template <typename PSOCreateInfoType>
+void PipelineStateD3D12Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo,
+ std::vector<D3D12PipelineShaderStageInfo>& ShaderStages)
{
m_ResourceLayoutIndex.fill(-1);
- auto pd3d12Device = pDeviceD3D12->GetD3D12Device();
- const auto& ResourceLayout = m_Desc.ResourceLayout;
- m_RootSig.AllocateStaticSamplers(ResourceLayout);
-
- {
- auto& ShaderResLayoutAllocator = GetRawAllocator();
- m_pShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutD3D12", ShaderResourceLayoutD3D12, m_NumShaders * 2);
- }
-
- {
- auto& ShaderResCacheAllocator = GetRawAllocator();
- m_pStaticResourceCaches = ALLOCATE(ShaderResCacheAllocator, "Raw memory for ShaderResourceCacheD3D12", ShaderResourceCacheD3D12, m_NumShaders);
- }
-
- {
- auto& ShaderVarMgrAllocator = GetRawAllocator();
- m_pStaticVarManagers = ALLOCATE(ShaderVarMgrAllocator, "Raw memory for ShaderVariableManagerD3D12", ShaderVariableManagerD3D12, m_NumShaders);
- }
+ ExtractShaders<ShaderD3D12Impl>(CreateInfo, ShaderStages);
-#ifdef DILIGENT_DEVELOPMENT
- {
- const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- const auto* pShader = GetShader<const ShaderD3D12Impl>(s);
- pResources[s] = &(*pShader->GetShaderResources());
- }
- ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, m_NumShaders,
- (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
- (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0);
- }
-#endif
+ LinearAllocator MemPool{GetRawAllocator()};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- auto* pShaderD3D12 = GetShader<ShaderD3D12Impl>(s);
- auto ShaderType = pShaderD3D12->GetDesc().ShaderType;
- auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType);
+ const auto NumShaderStages = GetNumShaderStages();
+ VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size());
- m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
+ MemPool.AddSpace<ShaderResourceCacheD3D12>(NumShaderStages);
+ MemPool.AddSpace<ShaderResourceLayoutD3D12>(NumShaderStages * 2);
+ MemPool.AddSpace<ShaderVariableManagerD3D12>(NumShaderStages);
- new (m_pShaderResourceLayouts + s)
- ShaderResourceLayoutD3D12 //
- {
- *this,
- pDeviceD3D12->GetD3D12Device(),
- m_Desc.PipelineType,
- ResourceLayout,
- pShaderD3D12->GetShaderResources(),
- GetRawAllocator(),
- nullptr,
- 0,
- nullptr,
- &m_RootSig //
- };
+ ReserveSpaceForPipelineDesc(CreateInfo, MemPool);
- new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D12{ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources};
+ MemPool.Reserve();
- const SHADER_RESOURCE_VARIABLE_TYPE StaticVarType[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
- new (m_pShaderResourceLayouts + m_NumShaders + s)
- ShaderResourceLayoutD3D12 //
- {
- *this,
- pDeviceD3D12->GetD3D12Device(),
- m_Desc.PipelineType,
- ResourceLayout,
- pShaderD3D12->GetShaderResources(),
- GetRawAllocator(),
- StaticVarType,
- _countof(StaticVarType),
- m_pStaticResourceCaches + s,
- nullptr //
- };
+ m_pStaticResourceCaches = MemPool.ConstructArray<ShaderResourceCacheD3D12>(NumShaderStages, ShaderResourceCacheD3D12::DbgCacheContentType::StaticShaderResources);
- new (m_pStaticVarManagers + s)
- ShaderVariableManagerD3D12 //
- {
- *this,
- GetStaticShaderResLayout(s),
- GetRawAllocator(),
- nullptr,
- 0,
- GetStaticShaderResCache(s) //
- };
- }
- m_RootSig.Finalize(pd3d12Device);
+ // The memory is now owned by PipelineStateD3D12Impl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_pStaticResourceCaches);
+ (void)Ptr;
- switch (m_Desc.PipelineType)
- {
- case PIPELINE_TYPE_COMPUTE:
- {
- auto& ComputePipeline = m_Desc.ComputePipeline;
+ m_pShaderResourceLayouts = MemPool.ConstructArray<ShaderResourceLayoutD3D12>(NumShaderStages * 2, std::ref(*this));
- if (ComputePipeline.pCS == nullptr)
- LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc");
+ m_pStaticVarManagers = MemPool.Allocate<ShaderVariableManagerD3D12>(NumShaderStages);
+ for (Uint32 s = 0; s < NumShaderStages; ++s)
+ new (m_pStaticVarManagers + s) ShaderVariableManagerD3D12{*this, GetStaticShaderResCache(s)};
- D3D12_COMPUTE_PIPELINE_STATE_DESC d3d12PSODesc = {};
+ InitializePipelineDesc(CreateInfo, MemPool);
- auto* pByteCode = ValidatedCast<ShaderD3D12Impl>(ComputePipeline.pCS)->GetShaderByteCode();
- d3d12PSODesc.CS.pShaderBytecode = pByteCode->GetBufferPointer();
- d3d12PSODesc.CS.BytecodeLength = pByteCode->GetBufferSize();
+ m_RootSig.AllocateImmutableSamplers(CreateInfo.PSODesc.ResourceLayout);
- // 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;
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
- d3d12PSODesc.CachedPSO.pCachedBlob = nullptr;
- d3d12PSODesc.CachedPSO.CachedBlobSizeInBytes = 0;
+ InitResourceLayouts(CreateInfo, ShaderStages);
+}
- // 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();
+PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters,
+ RenderDeviceD3D12Impl* pDeviceD3D12,
+ const GraphicsPipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ try
+ {
+ std::vector<D3D12PipelineShaderStageInfo> ShaderStages;
- 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;
- }
+ InitInternalObjects(CreateInfo, ShaderStages);
- case PIPELINE_TYPE_GRAPHICS:
+ auto pd3d12Device = pDeviceD3D12->GetD3D12Device();
+ if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS)
{
- const auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
+ const auto& GraphicsPipeline = GetGraphicsPipelineDesc();
D3D12_GRAPHICS_PIPELINE_STATE_DESC d3d12PSODesc = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (const auto& Stage : ShaderStages)
{
- auto* pShaderD3D12 = GetShader<ShaderD3D12Impl>(s);
+ 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 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");
}
@@ -269,7 +199,7 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR
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;
+ const auto& InputLayout = GetGraphicsPipelineDesc().InputLayout;
if (InputLayout.NumElements > 0)
{
LayoutElements_To_D3D12_INPUT_ELEMENT_DESCs(InputLayout, d312InputElements);
@@ -310,13 +240,12 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR
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:
+ else if (m_Desc.PipelineType == PIPELINE_TYPE_MESH)
{
- const auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
+ const auto& GraphicsPipeline = GetGraphicsPipelineDesc();
struct MESH_SHADER_PIPELINE_STATE_DESC
{
@@ -337,18 +266,19 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR
};
MESH_SHADER_PIPELINE_STATE_DESC d3d12PSODesc = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (const auto& Stage : ShaderStages)
{
- auto* pShaderD3D12 = GetShader<ShaderD3D12Impl>(s);
+ 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 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");
}
@@ -394,27 +324,192 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR
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:
+ 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());
+ }
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
}
+}
- if (*m_Desc.Name != 0)
+PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pRefCounters,
+ RenderDeviceD3D12Impl* pDeviceD3D12,
+ const ComputePipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceD3D12, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ try
{
- 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());
+ std::vector<D3D12PipelineShaderStageInfo> ShaderStages;
+
+ InitInternalObjects(CreateInfo, ShaderStages);
+
+ auto pd3d12Device = pDeviceD3D12->GetD3D12Device();
+
+ 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());
+ }
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
+}
+
+PipelineStateD3D12Impl::~PipelineStateD3D12Impl()
+{
+ Destruct();
+}
+
+void PipelineStateD3D12Impl::Destruct()
+{
+ auto& ShaderResLayoutAllocator = GetRawAllocator();
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
+ {
+ if (m_pStaticVarManagers != nullptr)
+ {
+ m_pStaticVarManagers[s].Destroy(GetRawAllocator());
+ m_pStaticVarManagers[s].~ShaderVariableManagerD3D12();
+ }
+
+ if (m_pShaderResourceLayouts != nullptr)
+ {
+ m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12();
+ m_pShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutD3D12();
+ }
+
+ if (m_pStaticResourceCaches != nullptr)
+ {
+ m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12();
+ }
+ }
+ // All internal objects are allocated in contiguous chunks of memory.
+ if (auto* pRawMem = m_pStaticResourceCaches)
+ {
+ ShaderResLayoutAllocator.Free(pRawMem);
}
+ if (m_pd3d12PSO)
+ {
+ // D3D12 object can only be destroyed when it is no longer used by the GPU
+ m_pDevice->SafeReleaseDeviceObject(std::move(m_pd3d12PSO), m_Desc.CommandQueueMask);
+ }
+}
+
+IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D12Impl, IID_PipelineStateD3D12, TPipelineStateBase)
+
+
+void PipelineStateD3D12Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
+ std::vector<D3D12PipelineShaderStageInfo>& ShaderStages)
+{
+ auto pd3d12Device = GetDevice()->GetD3D12Device();
+ const auto& ResourceLayout = m_Desc.ResourceLayout;
+
+#ifdef DILIGENT_DEVELOPMENT
+ {
+ const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {};
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
+ {
+ const auto* pShader = ShaderStages[s].pShader;
+ pResources[s] = &(*pShader->GetShaderResources());
+ }
+ ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(),
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0);
+ }
+#endif
+
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
+ {
+ auto* pShaderD3D12 = ShaderStages[s].pShader;
+ auto ShaderType = pShaderD3D12->GetDesc().ShaderType;
+ auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType);
+
+ m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
+
+ m_pShaderResourceLayouts[s].Initialize(
+ pd3d12Device,
+ m_Desc.PipelineType,
+ ResourceLayout,
+ pShaderD3D12->GetShaderResources(),
+ GetRawAllocator(),
+ nullptr,
+ 0,
+ nullptr,
+ &m_RootSig //
+ );
+
+ const SHADER_RESOURCE_VARIABLE_TYPE StaticVarType[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
+ m_pShaderResourceLayouts[GetNumShaderStages() + s].Initialize(
+ pd3d12Device,
+ m_Desc.PipelineType,
+ ResourceLayout,
+ pShaderD3D12->GetShaderResources(),
+ GetRawAllocator(),
+ StaticVarType,
+ _countof(StaticVarType),
+ m_pStaticResourceCaches + s,
+ nullptr //
+ );
+
+ m_pStaticVarManagers[s].Initialize(
+ GetStaticShaderResLayout(static_cast<Uint32>(s)),
+ GetRawAllocator(),
+ nullptr,
+ 0 //
+ );
+ }
+ m_RootSig.Finalize(pd3d12Device);
+
if (m_Desc.SRBAllocationGranularity > 1)
{
std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderVarMgrDataSizes = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
std::array<SHADER_RESOURCE_VARIABLE_TYPE, 2> AllowedVarTypes =
{
@@ -427,34 +522,12 @@ PipelineStateD3D12Impl::PipelineStateD3D12Impl(IReferenceCounters* pR
}
auto CacheMemorySize = m_RootSig.GetResourceCacheRequiredMemSize();
- m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderVarMgrDataSizes.data(), 1, &CacheMemorySize);
+ m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderVarMgrDataSizes.data(), 1, &CacheMemorySize);
}
m_ShaderResourceLayoutHash = m_RootSig.GetHash();
}
-PipelineStateD3D12Impl::~PipelineStateD3D12Impl()
-{
- auto& ShaderResLayoutAllocator = GetRawAllocator();
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- m_pStaticVarManagers[s].Destroy(GetRawAllocator());
- m_pStaticVarManagers[s].~ShaderVariableManagerD3D12();
- m_pStaticResourceCaches[s].~ShaderResourceCacheD3D12();
- m_pShaderResourceLayouts[s].~ShaderResourceLayoutD3D12();
- m_pShaderResourceLayouts[m_NumShaders + s].~ShaderResourceLayoutD3D12();
- }
- ShaderResLayoutAllocator.Free(m_pStaticVarManagers);
- ShaderResLayoutAllocator.Free(m_pStaticResourceCaches);
- ShaderResLayoutAllocator.Free(m_pShaderResourceLayouts);
-
- // 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();
@@ -480,23 +553,22 @@ bool PipelineStateD3D12Impl::IsCompatibleWith(const IPipelineState* pPSO) const
#ifdef DILIGENT_DEBUG
{
bool IsCompatibleShaders = true;
- if (m_NumShaders != pPSOD3D12->m_NumShaders)
+ if (GetNumShaderStages() != pPSOD3D12->GetNumShaderStages())
IsCompatibleShaders = false;
if (IsCompatibleShaders)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- auto* pShader0 = GetShader<const ShaderD3D12Impl>(s);
- auto* pShader1 = pPSOD3D12->GetShader<const ShaderD3D12Impl>(s);
- if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType)
+ if (GetShaderStageType(s) != pPSOD3D12->GetShaderStageType(s))
{
IsCompatibleShaders = false;
break;
}
- const ShaderResourcesD3D12* pRes0 = pShader0->GetShaderResources().get();
- const ShaderResourcesD3D12* pRes1 = pShader1->GetShaderResources().get();
- if (!pRes0->IsCompatibleWith(*pRes1))
+
+ const auto& Res0 = GetShaderResLayout(s).GetResources();
+ const auto& Res1 = pPSOD3D12->GetShaderResLayout(s).GetResources();
+ if (!Res0.IsCompatibleWith(Res1))
{
IsCompatibleShaders = false;
break;
@@ -607,7 +679,7 @@ bool PipelineStateD3D12Impl::ContainsShaderResources() const
void PipelineStateD3D12Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
auto ShaderType = GetStaticShaderResLayout(s).GetShaderType();
if ((ShaderFlags & ShaderType) != 0)
@@ -621,7 +693,7 @@ Uint32 PipelineStateD3D12Impl::GetStaticVariableCount(SHADER_TYPE ShaderType) co
if (LayoutInd < 0)
return 0;
- VERIFY_EXPR(static_cast<Uint32>(LayoutInd) < m_NumShaders);
+ VERIFY_EXPR(static_cast<Uint32>(LayoutInd) < GetNumShaderStages());
return m_pStaticVarManagers[LayoutInd].GetVariableCount();
}
@@ -631,7 +703,7 @@ IShaderResourceVariable* PipelineStateD3D12Impl::GetStaticVariableByName(SHADER_
if (LayoutInd < 0)
return nullptr;
- VERIFY_EXPR(static_cast<Uint32>(LayoutInd) < m_NumShaders);
+ VERIFY_EXPR(static_cast<Uint32>(LayoutInd) < GetNumShaderStages());
return m_pStaticVarManagers[LayoutInd].GetVariable(Name);
}
@@ -641,7 +713,7 @@ IShaderResourceVariable* PipelineStateD3D12Impl::GetStaticVariableByIndex(SHADER
if (LayoutInd < 0)
return nullptr;
- VERIFY_EXPR(static_cast<Uint32>(LayoutInd) < m_NumShaders);
+ VERIFY_EXPR(static_cast<Uint32>(LayoutInd) < GetNumShaderStages());
return m_pStaticVarManagers[LayoutInd].GetVariable(Index);
}
diff --git a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
index 6e4b828e..61ad5871 100644
--- a/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RenderDeviceD3D12Impl.cpp
@@ -298,7 +298,7 @@ RenderDeviceD3D12Impl::RenderDeviceD3D12Impl(IReferenceCounters* pRefCo
#undef CHECK_REQUIRED_FEATURE
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
+ static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
#endif
auto& TexCaps = m_DeviceCaps.TexCaps;
@@ -535,23 +535,35 @@ void RenderDeviceD3D12Impl::TestTextureFormat(TEXTURE_FORMAT TexFormat)
IMPLEMENT_QUERY_INTERFACE(RenderDeviceD3D12Impl, IID_RenderDeviceD3D12, TRenderDeviceBase)
-void RenderDeviceD3D12Impl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+template <typename PSOCreateInfoType>
+void RenderDeviceD3D12Impl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState)
{
CreateDeviceObject("Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState,
[&]() //
{
- PipelineStateD3D12Impl* pPipelineStateD3D12(NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D12Impl instance", PipelineStateD3D12Impl)(this, PSOCreateInfo));
+ PipelineStateD3D12Impl* pPipelineStateD3D12{NEW_RC_OBJ(m_PSOAllocator, "PipelineStateD3D12Impl instance", PipelineStateD3D12Impl)(this, PSOCreateInfo)};
pPipelineStateD3D12->QueryInterface(IID_PipelineState, reinterpret_cast<IObject**>(ppPipelineState));
OnCreateDeviceObject(pPipelineStateD3D12);
});
}
+
+void RenderDeviceD3D12Impl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
+void RenderDeviceD3D12Impl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
void RenderDeviceD3D12Impl::CreateBufferFromD3DResource(ID3D12Resource* pd3d12Buffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer)
{
CreateDeviceObject("buffer", BuffDesc, ppBuffer,
[&]() //
{
- BufferD3D12Impl* pBufferD3D12(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d12Buffer));
+ BufferD3D12Impl* pBufferD3D12{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, InitialState, pd3d12Buffer)};
pBufferD3D12->QueryInterface(IID_Buffer, reinterpret_cast<IObject**>(ppBuffer));
pBufferD3D12->CreateDefaultViews();
OnCreateDeviceObject(pBufferD3D12);
@@ -563,7 +575,7 @@ void RenderDeviceD3D12Impl::CreateBuffer(const BufferDesc& BuffDesc, const Buffe
CreateDeviceObject("buffer", BuffDesc, ppBuffer,
[&]() //
{
- BufferD3D12Impl* pBufferD3D12(NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData));
+ BufferD3D12Impl* pBufferD3D12{NEW_RC_OBJ(m_BufObjAllocator, "BufferD3D12Impl instance", BufferD3D12Impl)(m_BuffViewObjAllocator, this, BuffDesc, pBuffData)};
pBufferD3D12->QueryInterface(IID_Buffer, reinterpret_cast<IObject**>(ppBuffer));
pBufferD3D12->CreateDefaultViews();
OnCreateDeviceObject(pBufferD3D12);
@@ -576,7 +588,7 @@ void RenderDeviceD3D12Impl::CreateShader(const ShaderCreateInfo& ShaderCI, IShad
CreateDeviceObject("shader", ShaderCI.Desc, ppShader,
[&]() //
{
- ShaderD3D12Impl* pShaderD3D12(NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D12Impl instance", ShaderD3D12Impl)(this, ShaderCI));
+ ShaderD3D12Impl* pShaderD3D12{NEW_RC_OBJ(m_ShaderObjAllocator, "ShaderD3D12Impl instance", ShaderD3D12Impl)(this, ShaderCI)};
pShaderD3D12->QueryInterface(IID_Shader, reinterpret_cast<IObject**>(ppShader));
OnCreateDeviceObject(pShaderD3D12);
@@ -590,7 +602,7 @@ void RenderDeviceD3D12Impl::CreateTextureFromD3DResource(ID3D12Resource* pd3d12T
CreateDeviceObject("texture", TexDesc, ppTexture,
[&]() //
{
- TextureD3D12Impl* pTextureD3D12 = NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture);
+ TextureD3D12Impl* pTextureD3D12{NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture)};
pTextureD3D12->QueryInterface(IID_Texture, reinterpret_cast<IObject**>(ppTexture));
pTextureD3D12->CreateDefaultViews();
@@ -603,7 +615,7 @@ void RenderDeviceD3D12Impl::CreateTexture(const TextureDesc& TexDesc, ID3D12Reso
CreateDeviceObject("texture", TexDesc, ppTexture,
[&]() //
{
- TextureD3D12Impl* pTextureD3D12 = NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture);
+ TextureD3D12Impl* pTextureD3D12{NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, InitialState, pd3d12Texture)};
pTextureD3D12->QueryInterface(IID_TextureD3D12, reinterpret_cast<IObject**>(ppTexture));
});
}
@@ -613,7 +625,7 @@ void RenderDeviceD3D12Impl::CreateTexture(const TextureDesc& TexDesc, const Text
CreateDeviceObject("texture", TexDesc, ppTexture,
[&]() //
{
- TextureD3D12Impl* pTextureD3D12 = NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, pData);
+ TextureD3D12Impl* pTextureD3D12{NEW_RC_OBJ(m_TexObjAllocator, "TextureD3D12Impl instance", TextureD3D12Impl)(m_TexViewObjAllocator, this, TexDesc, pData)};
pTextureD3D12->QueryInterface(IID_Texture, reinterpret_cast<IObject**>(ppTexture));
pTextureD3D12->CreateDefaultViews();
@@ -629,7 +641,7 @@ void RenderDeviceD3D12Impl::CreateSampler(const SamplerDesc& SamplerDesc, ISampl
m_SamplersRegistry.Find(SamplerDesc, reinterpret_cast<IDeviceObject**>(ppSampler));
if (*ppSampler == nullptr)
{
- SamplerD3D12Impl* pSamplerD3D12(NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D12Impl instance", SamplerD3D12Impl)(this, SamplerDesc));
+ SamplerD3D12Impl* pSamplerD3D12{NEW_RC_OBJ(m_SamplerObjAllocator, "SamplerD3D12Impl instance", SamplerD3D12Impl)(this, SamplerDesc)};
pSamplerD3D12->QueryInterface(IID_Sampler, reinterpret_cast<IObject**>(ppSampler));
OnCreateDeviceObject(pSamplerD3D12);
m_SamplersRegistry.Add(SamplerDesc, *ppSampler);
@@ -642,7 +654,7 @@ void RenderDeviceD3D12Impl::CreateFence(const FenceDesc& Desc, IFence** ppFence)
CreateDeviceObject("Fence", Desc, ppFence,
[&]() //
{
- FenceD3D12Impl* pFenceD3D12(NEW_RC_OBJ(m_FenceAllocator, "FenceD3D12Impl instance", FenceD3D12Impl)(this, Desc));
+ FenceD3D12Impl* pFenceD3D12{NEW_RC_OBJ(m_FenceAllocator, "FenceD3D12Impl instance", FenceD3D12Impl)(this, Desc)};
pFenceD3D12->QueryInterface(IID_Fence, reinterpret_cast<IObject**>(ppFence));
OnCreateDeviceObject(pFenceD3D12);
});
@@ -653,7 +665,7 @@ void RenderDeviceD3D12Impl::CreateQuery(const QueryDesc& Desc, IQuery** ppQuery)
CreateDeviceObject("Query", Desc, ppQuery,
[&]() //
{
- QueryD3D12Impl* pQueryD3D12(NEW_RC_OBJ(m_QueryAllocator, "QueryD3D12Impl instance", QueryD3D12Impl)(this, Desc));
+ QueryD3D12Impl* pQueryD3D12{NEW_RC_OBJ(m_QueryAllocator, "QueryD3D12Impl instance", QueryD3D12Impl)(this, Desc)};
pQueryD3D12->QueryInterface(IID_Query, reinterpret_cast<IObject**>(ppQuery));
OnCreateDeviceObject(pQueryD3D12);
});
@@ -664,7 +676,7 @@ void RenderDeviceD3D12Impl::CreateRenderPass(const RenderPassDesc& Desc, IRender
CreateDeviceObject("RenderPass", Desc, ppRenderPass,
[&]() //
{
- RenderPassD3D12Impl* pRenderPassD3D12(NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D12Impl instance", RenderPassD3D12Impl)(this, Desc));
+ RenderPassD3D12Impl* pRenderPassD3D12{NEW_RC_OBJ(m_RenderPassAllocator, "RenderPassD3D12Impl instance", RenderPassD3D12Impl)(this, Desc)};
pRenderPassD3D12->QueryInterface(IID_RenderPass, reinterpret_cast<IObject**>(ppRenderPass));
OnCreateDeviceObject(pRenderPassD3D12);
});
@@ -675,7 +687,7 @@ void RenderDeviceD3D12Impl::CreateFramebuffer(const FramebufferDesc& Desc, IFram
CreateDeviceObject("Framebuffer", Desc, ppFramebuffer,
[&]() //
{
- FramebufferD3D12Impl* pFramebufferD3D12(NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D12Impl instance", FramebufferD3D12Impl)(this, Desc));
+ FramebufferD3D12Impl* pFramebufferD3D12{NEW_RC_OBJ(m_FramebufferAllocator, "FramebufferD3D12Impl instance", FramebufferD3D12Impl)(this, Desc)};
pFramebufferD3D12->QueryInterface(IID_Framebuffer, reinterpret_cast<IObject**>(ppFramebuffer));
OnCreateDeviceObject(pFramebufferD3D12);
});
diff --git a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
index bba639f8..2afb9eb1 100644
--- a/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/RootSignature.cpp
@@ -166,7 +166,7 @@ size_t RootSignature::RootParamsManager::GetHash() const
RootSignature::RootSignature() :
m_RootParams{GetRawAllocator()},
m_MemAllocator{GetRawAllocator()},
- m_StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerAttribs, GetRawAllocator(), "Allocator for vector<StaticSamplerAttribs>"))
+ m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerAttribs, GetRawAllocator(), "Allocator for vector<ImmutableSamplerAttribs>"))
{
m_SrvCbvUavRootTablesMap.fill(InvalidRootTableIndex);
m_SamplerRootTablesMap.fill(InvalidRootTableIndex);
@@ -282,29 +282,30 @@ D3D12_DESCRIPTOR_HEAP_TYPE HeapTypeFromRangeType(D3D12_DESCRIPTOR_RANGE_TYPE Ran
}
-void RootSignature::InitStaticSampler(SHADER_TYPE ShaderType,
- const char* SamplerName,
- const char* SamplerSuffix,
- const D3DShaderResourceAttribs& SamplerAttribs)
+void RootSignature::InitImmutableSampler(SHADER_TYPE ShaderType,
+ const char* SamplerName,
+ const char* SamplerSuffix,
+ const D3DShaderResourceAttribs& SamplerAttribs)
{
auto ShaderVisibility = GetShaderVisibility(ShaderType);
auto SamplerFound = false;
- for (auto& StSmplr : m_StaticSamplers)
+ for (auto& ImtblSmplr : m_ImmutableSamplers)
{
- if (StSmplr.ShaderVisibility == ShaderVisibility &&
- StreqSuff(SamplerName, StSmplr.SamplerDesc.SamplerOrTextureName, SamplerSuffix))
+ if (ImtblSmplr.ShaderVisibility == ShaderVisibility &&
+ StreqSuff(SamplerName, ImtblSmplr.SamplerDesc.SamplerOrTextureName, SamplerSuffix))
{
- StSmplr.ShaderRegister = SamplerAttribs.BindPoint;
- StSmplr.ArraySize = SamplerAttribs.BindCount;
- StSmplr.RegisterSpace = 0;
- SamplerFound = true;
+ ImtblSmplr.ShaderRegister = SamplerAttribs.BindPoint;
+ ImtblSmplr.ArraySize = SamplerAttribs.BindCount;
+ ImtblSmplr.RegisterSpace = 0;
+
+ SamplerFound = true;
break;
}
}
if (!SamplerFound)
{
- LOG_ERROR("Unable to find static sampler \'", SamplerName, '\'');
+ LOG_ERROR("Unable to find immutable sampler \'", SamplerName, '\'');
}
}
@@ -446,19 +447,19 @@ void RootSignature::dbgVerifyRootParameters() const
}
#endif
-void RootSignature::AllocateStaticSamplers(const PipelineResourceLayoutDesc& ResourceLayout)
+void RootSignature::AllocateImmutableSamplers(const PipelineResourceLayoutDesc& ResourceLayout)
{
- if (ResourceLayout.NumStaticSamplers > 0)
+ if (ResourceLayout.NumImmutableSamplers > 0)
{
- m_StaticSamplers.reserve(ResourceLayout.NumStaticSamplers);
- for (Uint32 sam = 0; sam < ResourceLayout.NumStaticSamplers; ++sam)
+ m_ImmutableSamplers.reserve(ResourceLayout.NumImmutableSamplers);
+ for (Uint32 sam = 0; sam < ResourceLayout.NumImmutableSamplers; ++sam)
{
- const auto& StSamDesc = ResourceLayout.StaticSamplers[sam];
- Uint32 ShaderStages = StSamDesc.ShaderStages;
+ const auto& ImtblSamDesc = ResourceLayout.ImmutableSamplers[sam];
+ Uint32 ShaderStages = ImtblSamDesc.ShaderStages;
while (ShaderStages != 0)
{
auto Stage = ShaderStages & ~(ShaderStages - 1);
- m_StaticSamplers.emplace_back(StSamDesc, GetShaderVisibility(static_cast<SHADER_TYPE>(Stage)));
+ m_ImmutableSamplers.emplace_back(ImtblSamDesc, GetShaderVisibility(static_cast<SHADER_TYPE>(Stage)));
ShaderStages &= ~Stage;
}
}
@@ -516,19 +517,19 @@ void RootSignature::Finalize(ID3D12Device* pd3d12Device)
rootSignatureDesc.pParameters = D3D12Parameters.size() ? D3D12Parameters.data() : nullptr;
UINT TotalD3D12StaticSamplers = 0;
- for (const auto& StSam : m_StaticSamplers)
- TotalD3D12StaticSamplers += StSam.ArraySize;
+ for (const auto& ImtblSam : m_ImmutableSamplers)
+ TotalD3D12StaticSamplers += ImtblSam.ArraySize;
rootSignatureDesc.NumStaticSamplers = TotalD3D12StaticSamplers;
rootSignatureDesc.pStaticSamplers = nullptr;
std::vector<D3D12_STATIC_SAMPLER_DESC, STDAllocatorRawMem<D3D12_STATIC_SAMPLER_DESC>> D3D12StaticSamplers(STD_ALLOCATOR_RAW_MEM(D3D12_STATIC_SAMPLER_DESC, GetRawAllocator(), "Allocator for vector<D3D12_STATIC_SAMPLER_DESC>"));
D3D12StaticSamplers.reserve(TotalD3D12StaticSamplers);
- if (!m_StaticSamplers.empty())
+ if (!m_ImmutableSamplers.empty())
{
- for (size_t s = 0; s < m_StaticSamplers.size(); ++s)
+ for (size_t s = 0; s < m_ImmutableSamplers.size(); ++s)
{
- const auto& StSmplrDesc = m_StaticSamplers[s];
- const auto& SamDesc = StSmplrDesc.SamplerDesc.Desc;
- for (UINT ArrInd = 0; ArrInd < StSmplrDesc.ArraySize; ++ArrInd)
+ const auto& ImtblSmplrDesc = m_ImmutableSamplers[s];
+ const auto& SamDesc = ImtblSmplrDesc.SamplerDesc.Desc;
+ for (UINT ArrInd = 0; ArrInd < ImtblSmplrDesc.ArraySize; ++ArrInd)
{
D3D12StaticSamplers.emplace_back(
D3D12_STATIC_SAMPLER_DESC //
@@ -543,18 +544,18 @@ void RootSignature::Finalize(ID3D12Device* pd3d12Device)
BorderColorToD3D12StaticBorderColor(SamDesc.BorderColor),
SamDesc.MinLOD,
SamDesc.MaxLOD,
- StSmplrDesc.ShaderRegister + ArrInd,
- StSmplrDesc.RegisterSpace,
- StSmplrDesc.ShaderVisibility //
- } //
+ ImtblSmplrDesc.ShaderRegister + ArrInd,
+ ImtblSmplrDesc.RegisterSpace,
+ ImtblSmplrDesc.ShaderVisibility //
+ } //
);
}
}
rootSignatureDesc.pStaticSamplers = D3D12StaticSamplers.data();
- // Release static samplers array, we no longer need it
- std::vector<StaticSamplerAttribs, STDAllocatorRawMem<StaticSamplerAttribs>> EmptySamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerAttribs, GetRawAllocator(), "Allocator for vector<StaticSamplerAttribs>"));
- m_StaticSamplers.swap(EmptySamplers);
+ // Release immutable samplers array, we no longer need it
+ std::vector<ImmutableSamplerAttribs, STDAllocatorRawMem<ImmutableSamplerAttribs>> EmptySamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerAttribs, GetRawAllocator(), "Allocator for vector<ImmutableSamplerAttribs>"));
+ m_ImmutableSamplers.swap(EmptySamplers);
VERIFY_EXPR(D3D12StaticSamplers.size() == TotalD3D12StaticSamplers);
}
@@ -640,7 +641,7 @@ void RootSignature::InitResourceCache(RenderDeviceD3D12Impl* pDeviceD3D12Impl
DEV_CHECK_ERR(!SamplerHeapSpace.IsNull(),
"Failed to allocate ", TotalSamplerDescriptors, " GPU-visible Sampler descriptor",
(TotalSamplerDescriptors > 1 ? "s" : ""),
- ". Consider using static samplers in the Pipeline State Object or "
+ ". Consider using immutable samplers in the Pipeline State Object or "
"increasing GPUDescriptorHeapSize[1] in EngineD3D12CreateInfo.");
}
VERIFY_EXPR(TotalSamplerDescriptors == 0 && SamplerHeapSpace.IsNull() || SamplerHeapSpace.GetNumHandles() == TotalSamplerDescriptors);
@@ -965,7 +966,7 @@ void RootSignature::CommitDescriptorHandlesInternal_SMD(RenderDeviceD3D12Impl*
DEV_CHECK_ERR(DynamicSamplerDescriptors.GetDescriptorHeap() != nullptr,
"Failed to allocate ", NumDynamicSamplerDescriptors, " dynamic GPU-visible Sampler descriptor",
(NumDynamicSamplerDescriptors > 1 ? "s" : ""),
- ". Consider using static samplers in the Pipeline State Object, increasing GPUDescriptorHeapDynamicSize[1] in "
+ ". Consider using immutable samplers in the Pipeline State Object, increasing GPUDescriptorHeapDynamicSize[1] in "
"EngineD3D12CreateInfo, or optimizing dynamic resource utilization by using static or mutable shader resource variables instead.");
}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp
index 257a4688..1511bd01 100644
--- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceBindingD3D12Impl.cpp
@@ -30,6 +30,7 @@
#include "PipelineStateD3D12Impl.hpp"
#include "ShaderD3D12Impl.hpp"
#include "RenderDeviceD3D12Impl.hpp"
+#include "LinearAllocator.hpp"
namespace Diligent
{
@@ -45,56 +46,76 @@ ShaderResourceBindingD3D12Impl::ShaderResourceBindingD3D12Impl(IReferenceCounter
IsPSOInternal
},
m_ShaderResourceCache{ShaderResourceCacheD3D12::DbgCacheContentType::SRBResources},
- m_NumShaders {static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaders())}
+ m_NumShaders {static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaderStages())}
// clang-format on
{
- m_ResourceLayoutIndex.fill(-1);
- auto* ppShaders = pPSO->GetShaders();
+ try
+ {
+ m_ResourceLayoutIndex.fill(-1);
- auto* pRenderDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(pPSO->GetDevice());
- auto& ResCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0);
- pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, ResCacheDataAllocator);
+ LinearAllocator MemPool{GetRawAllocator()};
+ MemPool.AddSpace<ShaderVariableManagerD3D12>(m_NumShaders);
+ MemPool.Reserve();
+ m_pShaderVarMgrs = MemPool.ConstructArray<ShaderVariableManagerD3D12>(m_NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache));
- m_pShaderVarMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerD3D12", ShaderVariableManagerD3D12, m_NumShaders);
+ // The memory is now owned by ShaderResourceBindingD3D12Impl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_pShaderVarMgrs);
+ (void)Ptr;
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- auto* pShader = ppShaders[s];
- auto ShaderType = pShader->GetDesc().ShaderType;
- auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType);
-
- auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
-
- // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object
- const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
- const auto& SrcLayout = pPSO->GetShaderResLayout(s);
- // Create shader variable manager in place
- new (m_pShaderVarMgrs + s)
- ShaderVariableManagerD3D12 //
- {
- *this,
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
+
+ auto* pRenderDeviceD3D12Impl = ValidatedCast<RenderDeviceD3D12Impl>(pPSO->GetDevice());
+ auto& ResCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0);
+ pPSO->GetRootSignature().InitResourceCache(pRenderDeviceD3D12Impl, m_ShaderResourceCache, ResCacheDataAllocator);
+
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ const auto ShaderType = pPSO->GetShaderStageType(s);
+ const auto& SrcLayout = pPSO->GetShaderResLayout(s);
+ const auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType);
+
+ auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
+
+ // http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Resource-Layouts-in-a-Shader-Resource-Binding-Object
+ const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+ m_pShaderVarMgrs[s].Initialize(
SrcLayout,
VarDataAllocator,
AllowedVarTypes,
- _countof(AllowedVarTypes),
- m_ShaderResourceCache //
- };
+ _countof(AllowedVarTypes) //
+ );
- m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
+ m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
+ }
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
}
}
+
ShaderResourceBindingD3D12Impl::~ShaderResourceBindingD3D12Impl()
{
- auto* pPSO = ValidatedCast<PipelineStateD3D12Impl>(m_pPSO);
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ Destruct();
+}
+
+void ShaderResourceBindingD3D12Impl::Destruct()
+{
+ if (m_pShaderVarMgrs != nullptr)
{
- auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
- m_pShaderVarMgrs[s].Destroy(VarDataAllocator);
- m_pShaderVarMgrs[s].~ShaderVariableManagerD3D12();
+ auto& SRBMemAllocator = m_pPSO->GetSRBMemoryAllocator();
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);
+ m_pShaderVarMgrs[s].Destroy(VarDataAllocator);
+ m_pShaderVarMgrs[s].~ShaderVariableManagerD3D12();
+ }
+ GetRawAllocator().Free(m_pShaderVarMgrs);
}
-
- GetRawAllocator().Free(m_pShaderVarMgrs);
}
IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingD3D12Impl, IID_ShaderResourceBindingD3D12, TBase)
@@ -189,20 +210,20 @@ void ShaderResourceBindingD3D12Impl::InitializeStaticResources(const IPipelineSt
}
auto* pPSO12 = ValidatedCast<const PipelineStateD3D12Impl>(pPSO);
- auto NumShaders = pPSO12->GetNumShaders();
+ auto NumShaders = pPSO12->GetNumShaderStages();
// Copy static resources
for (Uint32 s = 0; s < NumShaders; ++s)
{
const auto& ShaderResLayout = pPSO12->GetShaderResLayout(s);
auto& StaticResLayout = pPSO12->GetStaticShaderResLayout(s);
auto& StaticResCache = pPSO12->GetStaticShaderResCache(s);
+
#ifdef DILIGENT_DEVELOPMENT
if (!StaticResLayout.dvpVerifyBindings(StaticResCache))
{
- auto* pShader = pPSO12->GetShader<ShaderD3D12Impl>(s);
LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", pPSO12->GetDesc().Name,
- "' will not be successfully initialized because not all static resource bindings in shader '",
- pShader->GetDesc().Name,
+ "' will not be successfully initialized because not all static resource bindings in shader type '",
+ GetShaderTypeLiteralName(pPSO12->GetShaderStageType(s)),
"' are valid. Please make sure you bind all static resources to PSO before calling InitializeStaticResources() "
"directly or indirectly by passing InitStaticResources=true to CreateShaderResourceBinding() method.");
}
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
index 6c313882..c0428e7e 100644
--- a/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderResourceLayoutD3D12.cpp
@@ -38,6 +38,7 @@
#include "RootSignature.hpp"
#include "PipelineStateD3D12Impl.hpp"
#include "ShaderResourceVariableBase.hpp"
+#include "ShaderVariableD3DBase.hpp"
namespace Diligent
{
@@ -112,22 +113,19 @@ void ShaderResourceLayoutD3D12::AllocateMemory(IMemoryAllocator&
// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-layout#Initializing-Shader-Resource-Layouts-and-Root-Signature-in-a-Pipeline-State-Object
// http://diligentgraphics.com/diligent-engine/architecture/d3d12/shader-resource-cache#Initializing-Shader-Resource-Layouts-in-a-Pipeline-State
-ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject& Owner,
- ID3D12Device* pd3d12Device,
- PIPELINE_TYPE PipelineType,
- const PipelineResourceLayoutDesc& ResourceLayout,
- std::shared_ptr<const ShaderResourcesD3D12> pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheD3D12* pResourceCache,
- RootSignature* pRootSig) :
- // clang-format off
- m_Owner {Owner},
- m_pd3d12Device {pd3d12Device},
- m_pResources {std::move(pSrcResources)}
-// clang-format on
+void ShaderResourceLayoutD3D12::Initialize(ID3D12Device* pd3d12Device,
+ PIPELINE_TYPE PipelineType,
+ const PipelineResourceLayoutDesc& ResourceLayout,
+ std::shared_ptr<const ShaderResourcesD3D12> pSrcResources,
+ IMemoryAllocator& LayoutDataAllocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* const AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ ShaderResourceCacheD3D12* pResourceCache,
+ RootSignature* pRootSig)
{
+ m_pd3d12Device = pd3d12Device;
+ m_pResources = std::move(pSrcResources);
+
VERIFY_EXPR((pResourceCache != nullptr) ^ (pRootSig != nullptr));
const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
@@ -148,10 +146,11 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject&
auto VarType = m_pResources->FindVariableType(Sam, ResourceLayout);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- constexpr bool LogStaticSamplerArrayError = true;
- auto StaticSamplerInd = m_pResources->FindStaticSampler(Sam, ResourceLayout, LogStaticSamplerArrayError);
- // Skip static samplers
- if (StaticSamplerInd < 0)
+ constexpr bool LogImtblSamplerArrayError = true;
+
+ auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError);
+ // Skip immutable samplers
+ if (ImtblSamplerInd < 0)
++SamplerCount[VarType];
}
},
@@ -236,7 +235,7 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject&
VERIFY(RootIndex != D3D12Resource::InvalidRootIndex, "Root index must be valid");
VERIFY(Offset != D3D12Resource::InvalidOffset, "Offset must be valid");
- // Static samplers are never copied, and SamplerId == InvalidSamplerId
+ // Immutable samplers are never copied, and SamplerId == InvalidSamplerId
auto& NewResource = (ResType == CachedResourceType::Sampler) ?
GetSampler(VarType, CurrSampler[VarType]++) :
GetSrvCbvUav(VarType, CurrCbvSrvUav[VarType]++);
@@ -257,12 +256,13 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject&
if (IsAllowedType(VarType, AllowedTypeBits))
{
// The error (if any) have already been logged when counting the resources
- constexpr bool LogStaticSamplerArrayError = false;
- auto StaticSamplerInd = m_pResources->FindStaticSampler(Sam, ResourceLayout, LogStaticSamplerArrayError);
- if (StaticSamplerInd >= 0)
+ constexpr bool LogImtblSamplerArrayError = false;
+
+ auto ImtblSamplerInd = m_pResources->FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError);
+ if (ImtblSamplerInd >= 0)
{
if (pRootSig != nullptr)
- pRootSig->InitStaticSampler(m_pResources->GetShaderType(), Sam.Name, m_pResources->GetCombinedSamplerSuffix(), Sam);
+ pRootSig->InitImmutableSampler(m_pResources->GetShaderType(), Sam.Name, m_pResources->GetCombinedSamplerSuffix(), Sam);
}
else
{
@@ -289,18 +289,19 @@ ShaderResourceLayoutD3D12::ShaderResourceLayoutD3D12(IObject&
") of the sampler '", SamplerAttribs.Name, "' that is assigned to it");
// The error (if any) have already been logged when counting the resources
- constexpr bool LogStaticSamplerArrayError = false;
- auto StaticSamplerInd = m_pResources->FindStaticSampler(SamplerAttribs, ResourceLayout, LogStaticSamplerArrayError);
- if (StaticSamplerInd >= 0)
+ constexpr bool LogImtblSamplerArrayError = false;
+
+ auto ImtblSamplerInd = m_pResources->FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError);
+ if (ImtblSamplerInd >= 0)
{
- // Static samplers are never copied, and SamplerId == InvalidSamplerId
+ // Immutable samplers are never copied, and SamplerId == InvalidSamplerId
#ifdef DILIGENT_DEBUG
auto SamplerCount = GetTotalSamplerCount();
for (Uint32 s = 0; s < SamplerCount; ++s)
{
const auto& Sampler = GetSampler(s);
if (strcmp(Sampler.Attribs.Name, SamplerAttribs.Name) == 0)
- LOG_ERROR("Static sampler '", Sampler.Attribs.Name, "' was found among resources. This seems to be a bug");
+ LOG_ERROR("Immutable sampler '", Sampler.Attribs.Name, "' was found among resources. This seems to be a bug");
}
#endif
}
@@ -429,6 +430,11 @@ template <>
struct ResourceViewTraits<ITextureViewD3D12>
{
static const INTERFACE_ID& IID;
+
+ static bool VerifyView(ITextureViewD3D12* pViewD3D12, const D3DShaderResourceAttribs& Attribs, const char* ShaderName)
+ {
+ return true;
+ }
};
const INTERFACE_ID& ResourceViewTraits<ITextureViewD3D12>::IID = IID_TextureViewD3D12;
@@ -436,6 +442,11 @@ template <>
struct ResourceViewTraits<IBufferViewD3D12>
{
static const INTERFACE_ID& IID;
+
+ static bool VerifyView(IBufferViewD3D12* pViewD3D12, const D3DShaderResourceAttribs& Attribs, const char* ShaderName)
+ {
+ return VerifyBufferViewModeD3D(pViewD3D12, Attribs, ShaderName);
+ }
};
const INTERFACE_ID& ResourceViewTraits<IBufferViewD3D12>::IID = IID_BufferViewD3D12;
@@ -451,9 +462,10 @@ void ShaderResourceLayoutD3D12::D3D12Resource::CacheResourceView(IDeviceObject*
{
// We cannot use ValidatedCast<> here as the resource retrieved from the
// resource mapping can be of wrong type
- RefCntAutoPtr<TResourceViewType> pViewD3D12(pView, ResourceViewTraits<TResourceViewType>::IID);
+ RefCntAutoPtr<TResourceViewType> pViewD3D12{pView, ResourceViewTraits<TResourceViewType>::IID};
#ifdef DILIGENT_DEVELOPMENT
VerifyResourceViewBinding(Attribs, GetVariableType(), ArrayIndex, pView, pViewD3D12.RawPtr(), {dbgExpectedViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ ResourceViewTraits<TResourceViewType>::VerifyView(pViewD3D12, Attribs, ParentResLayout.GetShaderName());
#endif
if (pViewD3D12)
{
@@ -607,7 +619,7 @@ void ShaderResourceLayoutD3D12::D3D12Resource::BindResource(IDeviceObject*
if (ValidSamplerAssigned())
{
auto& Sam = ParentResLayout.GetAssignedSampler(*this);
- //VERIFY( !Sam.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" );
+ //VERIFY( !Sam.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" );
VERIFY_EXPR(Attribs.BindCount == Sam.Attribs.BindCount || Sam.Attribs.BindCount == 1);
auto SamplerArrInd = Sam.Attribs.BindCount > 1 ? ArrayIndex : 0;
@@ -781,7 +793,7 @@ void ShaderResourceLayoutD3D12::CopyStaticResourceDesriptorHandles(const ShaderR
{
const auto& SamInfo = DstLayout.GetAssignedSampler(res);
- //VERIFY(!SamInfo.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache");
+ //VERIFY(!SamInfo.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache");
VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid");
VERIFY_EXPR(SamInfo.Attribs.BindCount == res.Attribs.BindCount || SamInfo.Attribs.BindCount == 1);
@@ -908,7 +920,7 @@ bool ShaderResourceLayoutD3D12::dvpVerifyBindings(const ShaderResourceCacheD3D12
{
VERIFY(res.GetResType() == CachedResourceType::TexSRV, "Sampler can only be assigned to a texture SRV");
const auto& SamInfo = GetAssignedSampler(res);
- //VERIFY(!SamInfo.Attribs.IsStaticSampler(), "Static samplers should never be assigned space in the cache" );
+ //VERIFY(!SamInfo.Attribs.IsImmutableSampler(), "Immutable samplers should never be assigned space in the cache" );
VERIFY(SamInfo.Attribs.IsValidBindPoint(), "Sampler bind point must be valid");
for (Uint32 ArrInd = 0; ArrInd < SamInfo.Attribs.BindCount; ++ArrInd)
diff --git a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp
index f7c23096..fd58eacf 100644
--- a/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/ShaderVariableD3D12.cpp
@@ -54,20 +54,15 @@ size_t ShaderVariableManagerD3D12::GetRequiredMemorySize(const ShaderResourceLay
}
// Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes
-ShaderVariableManagerD3D12::ShaderVariableManagerD3D12(IObject& Owner,
- const ShaderResourceLayoutD3D12& SrcLayout,
- IMemoryAllocator& Allocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheD3D12& ResourceCache) :
- // clang-format off
- m_Owner {Owner},
- m_ResourceCache {ResourceCache}
+void ShaderVariableManagerD3D12::Initialize(const ShaderResourceLayoutD3D12& SrcLayout,
+ IMemoryAllocator& Allocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes)
+{
#ifdef DILIGENT_DEBUG
- , m_DbgAllocator {Allocator}
+ m_pDbgAllocator = &Allocator;
#endif
-// clang-format on
-{
+
const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
VERIFY_EXPR(m_NumVariables == 0);
auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables);
@@ -113,10 +108,10 @@ ShaderVariableManagerD3D12::~ShaderVariableManagerD3D12()
void ShaderVariableManagerD3D12::Destroy(IMemoryAllocator& Allocator)
{
- VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor");
-
if (m_pVariables != nullptr)
{
+ VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor");
+
for (Uint32 v = 0; v < m_NumVariables; ++v)
m_pVariables[v].~ShaderVariableD3D12Impl();
Allocator.Free(m_pVariables);
diff --git a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp
index a4033f51..22829770 100644
--- a/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp
+++ b/Graphics/GraphicsEngineD3D12/src/TextureD3D12Impl.cpp
@@ -135,8 +135,8 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters,
const TextureData* pInitData /*= nullptr*/) :
TTextureBase{pRefCounters, TexViewObjAllocator, pRenderDeviceD3D12, TexDesc}
{
- if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr))
- LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null");
+ if (m_Desc.Usage == USAGE_IMMUTABLE && (pInitData == nullptr || pInitData->pSubResources == nullptr))
+ LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time: pInitData can't be null");
if ((m_Desc.MiscFlags & MISC_TEXTURE_FLAG_GENERATE_MIPS) != 0)
{
@@ -149,7 +149,7 @@ TextureD3D12Impl::TextureD3D12Impl(IReferenceCounters* pRefCounters,
D3D12_RESOURCE_DESC Desc = GetD3D12TextureDesc();
auto* pd3d12Device = pRenderDeviceD3D12->GetD3D12Device();
- if (m_Desc.Usage == USAGE_STATIC || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC)
+ if (m_Desc.Usage == USAGE_IMMUTABLE || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC)
{
D3D12_CLEAR_VALUE ClearValue = {};
D3D12_CLEAR_VALUE* pClearValue = nullptr;
diff --git a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp
index 104533c9..ea4a43bb 100644
--- a/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp
+++ b/Graphics/GraphicsEngineD3DBase/include/RenderDeviceD3DBase.hpp
@@ -160,6 +160,7 @@ public:
auto& Features = this->m_DeviceCaps.Features;
Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED;
+ Features.ShaderResourceQueries = DEVICE_FEATURE_STATE_ENABLED;
Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED;
Features.WireframeFill = DEVICE_FEATURE_STATE_ENABLED;
Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_ENABLED;
diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp
index b5446ec3..efbff703 100644
--- a/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp
+++ b/Graphics/GraphicsEngineD3DBase/include/ShaderResources.hpp
@@ -192,6 +192,10 @@ public:
return static_cast<D3D_SRV_DIMENSION>(SRVDimension);
}
+ RESOURCE_DIMENSION GetResourceDimension() const;
+
+ bool IsMultisample() const;
+
bool IsCombinedWithSampler() const
{
return GetCombinedSamplerId() != InvalidSamplerId;
@@ -368,20 +372,20 @@ public:
SHADER_RESOURCE_VARIABLE_TYPE FindVariableType(const D3DShaderResourceAttribs& ResourceAttribs,
const PipelineResourceLayoutDesc& ResourceLayout) const;
- Int32 FindStaticSampler(const D3DShaderResourceAttribs& ResourceAttribs,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- bool LogStaticSamplerArrayError) const;
+ Int32 FindImmutableSampler(const D3DShaderResourceAttribs& ResourceAttribs,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool LogImmutableSamplerArrayError) const;
D3DShaderResourceCounters CountResources(const PipelineResourceLayoutDesc& ResourceLayout,
const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
Uint32 NumAllowedTypes,
- bool CountStaticSamplers) const noexcept;
+ bool CountImmutableSamplers) const noexcept;
#ifdef DILIGENT_DEVELOPMENT
static void DvpVerifyResourceLayout(const PipelineResourceLayoutDesc& ResourceLayout,
const ShaderResources* const pShaderResources[],
Uint32 NumShaders,
bool VerifyVariables,
- bool VerifyStaticSamplers);
+ bool VerifyImmutableSamplers) noexcept;
#endif
void GetShaderModel(Uint32& Major, Uint32& Minor) const
diff --git a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp
index 0ea6e397..2497b17d 100644
--- a/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp
+++ b/Graphics/GraphicsEngineD3DBase/include/ShaderVariableD3DBase.hpp
@@ -86,4 +86,53 @@ protected:
const SHADER_RESOURCE_VARIABLE_TYPE m_VariableType;
};
+
+template <typename BufferViewImplType>
+bool VerifyBufferViewModeD3D(BufferViewImplType* pViewD3D11, const D3DShaderResourceAttribs& Attribs, const char* ShaderName)
+{
+ if (pViewD3D11 == nullptr)
+ return true;
+
+ const auto& ViewDesc = pViewD3D11->GetDesc();
+ const auto& BuffDesc = pViewD3D11->GetBuffer()->GetDesc();
+
+ auto LogBufferBindingError = [&](const char* Msg) //
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name,
+ "' to shader variable '", Attribs.Name, "' in shader '", ShaderName, "': ", Msg);
+ };
+
+ switch (Attribs.GetInputType())
+ {
+ case D3D_SIT_TEXTURE:
+ case D3D_SIT_UAV_RWTYPED:
+ if (BuffDesc.Mode != BUFFER_MODE_FORMATTED || ViewDesc.Format.ValueType == VT_UNDEFINED)
+ {
+ LogBufferBindingError("formatted buffer view is expected.");
+ return false;
+ }
+ break;
+
+ case D3D_SIT_STRUCTURED:
+ case D3D_SIT_UAV_RWSTRUCTURED:
+ if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED)
+ {
+ LogBufferBindingError("structured buffer view is expected.");
+ return false;
+ }
+ break;
+
+ case D3D_SIT_BYTEADDRESS:
+ case D3D_SIT_UAV_RWBYTEADDRESS:
+ if (BuffDesc.Mode != BUFFER_MODE_RAW)
+ {
+ LogBufferBindingError("raw buffer view is expected.");
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp
index 75ec17ea..b975b506 100644
--- a/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp
+++ b/Graphics/GraphicsEngineD3DBase/src/ShaderResources.cpp
@@ -122,44 +122,44 @@ SHADER_RESOURCE_VARIABLE_TYPE ShaderResources::FindVariableType(const D3DShaderR
}
}
-Int32 ShaderResources::FindStaticSampler(const D3DShaderResourceAttribs& ResourceAttribs,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- bool LogStaticSamplerArrayError) const
+Int32 ShaderResources::FindImmutableSampler(const D3DShaderResourceAttribs& ResourceAttribs,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool LogImmutableSamplerArrayError) const
{
VERIFY(ResourceAttribs.GetInputType() == D3D_SIT_SAMPLER, "Sampler is expected");
- auto StaticSamplerInd =
- Diligent::FindStaticSampler(ResourceLayoutDesc.StaticSamplers,
- ResourceLayoutDesc.NumStaticSamplers,
- m_ShaderType,
- ResourceAttribs.Name,
- m_SamplerSuffix);
+ auto ImtblSamplerInd =
+ Diligent::FindImmutableSampler(ResourceLayoutDesc.ImmutableSamplers,
+ ResourceLayoutDesc.NumImmutableSamplers,
+ m_ShaderType,
+ ResourceAttribs.Name,
+ m_SamplerSuffix);
- if (StaticSamplerInd >= 0 && ResourceAttribs.BindCount > 1)
+ if (ImtblSamplerInd >= 0 && ResourceAttribs.BindCount > 1)
{
Uint32 ShaderMajorVersion = 0;
Uint32 ShaderMinorVersion = 0;
GetShaderModel(ShaderMajorVersion, ShaderMinorVersion);
if (ShaderMajorVersion >= 6 || ShaderMajorVersion >= 5 && ShaderMinorVersion >= 1)
{
- if (LogStaticSamplerArrayError)
+ if (LogImmutableSamplerArrayError)
{
- LOG_ERROR_MESSAGE("Static sampler '", ResourceAttribs.Name, '[', ResourceAttribs.BindCount,
+ LOG_ERROR_MESSAGE("Immutable sampler '", ResourceAttribs.Name, '[', ResourceAttribs.BindCount,
"]' will be ignored because static sampler arrays are not allowed in shader model 5.1 and above. "
"Compile the shader using shader model 5.0 or use non-array sampler variable.");
}
- StaticSamplerInd = -1;
+ ImtblSamplerInd = -1;
}
}
- return StaticSamplerInd;
+ return ImtblSamplerInd;
}
D3DShaderResourceCounters ShaderResources::CountResources(const PipelineResourceLayoutDesc& ResourceLayout,
const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
Uint32 NumAllowedTypes,
- bool CountStaticSamplers) const noexcept
+ bool CountImmutableSamplers) const noexcept
{
auto AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
@@ -176,11 +176,11 @@ D3DShaderResourceCounters ShaderResources::CountResources(const PipelineResource
auto VarType = FindVariableType(Sam, ResourceLayout);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- if (!CountStaticSamplers)
+ if (!CountImmutableSamplers)
{
- constexpr bool LogStaticSamplerArrayError = false;
- if (FindStaticSampler(Sam, ResourceLayout, LogStaticSamplerArrayError) >= 0)
- return; // Skip static sampler if requested
+ constexpr bool LogImtblSamplerArrayError = false;
+ if (FindImmutableSampler(Sam, ResourceLayout, LogImtblSamplerArrayError) >= 0)
+ return; // Skip immutable sampler if requested
}
++Counters.NumSamplers;
}
@@ -219,7 +219,7 @@ void ShaderResources::DvpVerifyResourceLayout(const PipelineResourceLayoutDesc&
const ShaderResources* const pShaderResources[],
Uint32 NumShaders,
bool VerifyVariables,
- bool VerifyStaticSamplers)
+ bool VerifyImmutableSamplers) noexcept
{
auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) //
{
@@ -300,40 +300,40 @@ void ShaderResources::DvpVerifyResourceLayout(const PipelineResourceLayoutDesc&
}
}
- if (VerifyStaticSamplers)
+ if (VerifyImmutableSamplers)
{
- for (Uint32 sam = 0; sam < ResourceLayout.NumStaticSamplers; ++sam)
+ for (Uint32 sam = 0; sam < ResourceLayout.NumImmutableSamplers; ++sam)
{
- const auto& StSamDesc = ResourceLayout.StaticSamplers[sam];
+ const auto& StSamDesc = ResourceLayout.ImmutableSamplers[sam];
if (StSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN)
{
- LOG_WARNING_MESSAGE("No allowed shader stages are specified for static sampler '", StSamDesc.SamplerOrTextureName, "'.");
+ LOG_WARNING_MESSAGE("No allowed shader stages are specified for immutable sampler '", StSamDesc.SamplerOrTextureName, "'.");
continue;
}
const auto* TexOrSamName = StSamDesc.SamplerOrTextureName;
- bool StaticSamplerFound = false;
- for (Uint32 s = 0; s < NumShaders && !StaticSamplerFound; ++s)
+ bool ImtblSamplerFound = false;
+ for (Uint32 s = 0; s < NumShaders && !ImtblSamplerFound; ++s)
{
const auto& Resources = *pShaderResources[s];
if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
continue;
- // Look for static sampler.
+ // Look for immutable sampler.
// In case HLSL-style combined image samplers are used, the condition is Sampler.Name == "g_Texture" + "_sampler".
// Otherwise the condition is Sampler.Name == "g_Texture_sampler" + "".
const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix();
- for (Uint32 n = 0; n < Resources.GetNumSamplers() && !StaticSamplerFound; ++n)
+ for (Uint32 n = 0; n < Resources.GetNumSamplers() && !ImtblSamplerFound; ++n)
{
const auto& Sampler = Resources.GetSampler(n);
- StaticSamplerFound = StreqSuff(Sampler.Name, TexOrSamName, CombinedSamplerSuffix);
+ ImtblSamplerFound = StreqSuff(Sampler.Name, TexOrSamName, CombinedSamplerSuffix);
}
}
- if (!StaticSamplerFound)
+ if (!ImtblSamplerFound)
{
- LOG_WARNING_MESSAGE("Static sampler '", TexOrSamName, "' is not found in any of the designated shader stages: ",
+ LOG_WARNING_MESSAGE("Immutable sampler '", TexOrSamName, "' is not found in any of the designated shader stages: ",
GetAllowedShadersString(StSamDesc.ShaderStages));
}
}
@@ -454,6 +454,39 @@ HLSLShaderResourceDesc D3DShaderResourceAttribs::GetHLSLResourceDesc() const
return ResourceDesc;
}
+RESOURCE_DIMENSION D3DShaderResourceAttribs::GetResourceDimension() const
+{
+ switch (GetSRVDimension())
+ {
+ // clang-format off
+ case D3D_SRV_DIMENSION_BUFFER: return RESOURCE_DIM_BUFFER;
+ case D3D_SRV_DIMENSION_TEXTURE1D: return RESOURCE_DIM_TEX_1D;
+ case D3D_SRV_DIMENSION_TEXTURE1DARRAY: return RESOURCE_DIM_TEX_1D_ARRAY;
+ case D3D_SRV_DIMENSION_TEXTURE2D: return RESOURCE_DIM_TEX_2D;
+ case D3D_SRV_DIMENSION_TEXTURE2DARRAY: return RESOURCE_DIM_TEX_2D_ARRAY;
+ case D3D_SRV_DIMENSION_TEXTURE2DMS: return RESOURCE_DIM_TEX_2D;
+ case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY: return RESOURCE_DIM_TEX_2D_ARRAY;
+ case D3D_SRV_DIMENSION_TEXTURE3D: return RESOURCE_DIM_TEX_3D;
+ case D3D_SRV_DIMENSION_TEXTURECUBE: return RESOURCE_DIM_TEX_CUBE;
+ case D3D_SRV_DIMENSION_TEXTURECUBEARRAY: return RESOURCE_DIM_TEX_CUBE_ARRAY;
+ // clang-format on
+ default:
+ return RESOURCE_DIM_BUFFER;
+ }
+}
+
+bool D3DShaderResourceAttribs::IsMultisample() const
+{
+ switch (GetSRVDimension())
+ {
+ case D3D_SRV_DIMENSION_TEXTURE2DMS:
+ case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY:
+ return true;
+ default:
+ return false;
+ }
+}
+
HLSLShaderResourceDesc ShaderResources::GetHLSLShaderResourceDesc(Uint32 Index) const
{
DEV_CHECK_ERR(Index < m_TotalResources, "Resource index (", Index, ") is out of range");
diff --git a/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h b/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h
index 97b36dbc..d5561b58 100644
--- a/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h
+++ b/Graphics/GraphicsEngineMetal/interface/BufferViewMtl.h
@@ -41,6 +41,7 @@ static const INTERFACE_ID IID_BufferViewMtl =
class IBufferViewMtl : public IBufferView
{
public:
+ virtual id<MTLTexture> GetMtlTextureView() const = 0;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h b/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h
index 51057dad..a8290e07 100644
--- a/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h
+++ b/Graphics/GraphicsEngineMetal/interface/SamplerMtl.h
@@ -41,6 +41,7 @@ static const INTERFACE_ID IID_SamplerMtl =
class ISamplerMtl : public ISampler
{
public:
+ virtual id<MTLSamplerState> GetMtlSampler() = 0;
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp b/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp
index 80f622c9..24e88004 100644
--- a/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/GLPipelineResourceLayout.hpp
@@ -118,15 +118,15 @@ public:
GLVariableBase(const GLProgramResources::GLResourceAttribs& ResourceAttribs,
GLPipelineResourceLayout& ParentLayout,
SHADER_RESOURCE_VARIABLE_TYPE VariableType,
- Int32 StaticSamplerIdx) :
+ Int32 ImtblSamplerIdx) :
// clang-format off
TBase {ParentLayout},
m_Attribs {ResourceAttribs },
m_VariableType {VariableType },
- m_StaticSamplerIdx{StaticSamplerIdx}
+ m_ImtblSamplerIdx {ImtblSamplerIdx}
// clang-format on
{
- VERIFY_EXPR(StaticSamplerIdx < 0 || ResourceAttribs.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV);
+ VERIFY_EXPR(ImtblSamplerIdx < 0 || ResourceAttribs.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV);
}
virtual SHADER_RESOURCE_VARIABLE_TYPE DILIGENT_CALL_TYPE GetType() const override final
@@ -146,7 +146,7 @@ public:
const GLProgramResources::GLResourceAttribs& m_Attribs;
const SHADER_RESOURCE_VARIABLE_TYPE m_VariableType;
- const Int32 m_StaticSamplerIdx;
+ const Int32 m_ImtblSamplerIdx;
};
@@ -188,8 +188,8 @@ public:
SamplerBindInfo(const GLProgramResources::GLResourceAttribs& ResourceAttribs,
GLPipelineResourceLayout& ParentResLayout,
SHADER_RESOURCE_VARIABLE_TYPE VariableType,
- Int32 StaticSamplerIdx) :
- GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, StaticSamplerIdx}
+ Int32 ImtblSamplerIdx) :
+ GLVariableBase{ResourceAttribs, ParentResLayout, VariableType, ImtblSamplerIdx}
{}
// Non-virtual function
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp
index 3fbc550e..07c8f39e 100644
--- a/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/GLProgramResourceCache.hpp
@@ -45,7 +45,7 @@ namespace Diligent
class GLProgramResourceCache
{
public:
- GLProgramResourceCache()
+ GLProgramResourceCache() noexcept
{}
~GLProgramResourceCache();
@@ -128,9 +128,9 @@ public:
GetSampler(Binding).Set(std::move(pTexView), SetSampler);
}
- void SetStaticSampler(Uint32 Binding, ISampler* pStaticSampler)
+ void SetImmutableSampler(Uint32 Binding, ISampler* pImtblSampler)
{
- GetSampler(Binding).pSampler = ValidatedCast<SamplerGLImpl>(pStaticSampler);
+ GetSampler(Binding).pSampler = ValidatedCast<SamplerGLImpl>(pImtblSampler);
}
void CopySampler(Uint32 Binding, const CachedResourceView& SrcSam)
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp b/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp
index a3b13b6d..091d0e31 100644
--- a/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/GLProgramResources.hpp
@@ -147,6 +147,16 @@ public:
ResourceDesc.Type = ResourceType;
return ResourceDesc;
}
+
+ RESOURCE_DIMENSION GetResourceDimension() const
+ {
+ return RESOURCE_DIM_UNDEFINED;
+ }
+
+ bool IsMultisample() const
+ {
+ return false;
+ }
};
struct UniformBufferInfo final : GLResourceAttribs
diff --git a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp
index a93528ec..4c57652f 100644
--- a/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/GLTypeConversions.hpp
@@ -82,7 +82,7 @@ inline GLenum UsageToGLUsage(const BufferDesc& Desc)
// DYNAMIC: The data store contents will be modified repeatedly and used many times.
// clang-format off
- case USAGE_STATIC: return GL_STATIC_DRAW;
+ case USAGE_IMMUTABLE: return GL_STATIC_DRAW;
case USAGE_DEFAULT: return GL_STATIC_DRAW;
case USAGE_UNIFIED: return GL_STATIC_DRAW;
case USAGE_DYNAMIC: return GL_DYNAMIC_DRAW;
diff --git a/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/PipelineStateGLImpl.hpp
index dea1d6c8..93180774 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
@@ -90,12 +95,32 @@ public:
private:
GLObjectWrappers::GLPipelineObj& GetGLProgramPipeline(GLContext::NativeGLContextType Context);
- void InitStaticSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const;
+ void InitImmutableSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const;
+
+ struct GLPipelineShaderStageInfo
+ {
+ const SHADER_TYPE Type;
+ ShaderGLImpl* const pShader;
+ GLPipelineShaderStageInfo(SHADER_TYPE _Type,
+ ShaderGLImpl* _pShader) :
+ Type{_Type},
+ pShader{_pShader}
+ {}
+ };
+
+ template <typename PSOCreateInfoType>
+ void Initialize(const PSOCreateInfoType& CreateInfo, const std::vector<GLPipelineShaderStageInfo>& ShaderStages);
+
+ void InitResourceLayouts(const std::vector<GLPipelineShaderStageInfo>& ShaderStages,
+ LinearAllocator& MemPool);
+
+ void Destruct();
// Linked GL programs for every shader stage. Every pipeline needs to have its own programs
// because resource bindings assigned by GLProgramResources::LoadUniforms depend on other
// shader stages.
- std::vector<GLObjectWrappers::GLProgramObj> m_GLPrograms;
+ using GLProgramObj = GLObjectWrappers::GLProgramObj;
+ GLProgramObj* m_GLPrograms = nullptr; // [m_NumShaderStages]
ThreadingTools::LockFlag m_ProgPipelineLockFlag;
@@ -113,14 +138,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_ImmutableSamplers = nullptr; // [m_Desc.ResourceLayout.NumImmutableSamplers]
};
} // namespace Diligent
diff --git a/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/RenderDeviceGLImpl.hpp
index be2b4ddc..3c34b483 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 DILIGENT_CALL_TYPE CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo,
+ IPipelineState** ppPipelineState) override final;
+
+ /// Implementation of IRenderDevice::CreateComputePipelineState() in OpenGL backend.
+ virtual void DILIGENT_CALL_TYPE 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;
@@ -179,6 +187,9 @@ protected:
std::unique_ptr<TexRegionRender> m_pTexRegionRender;
private:
+ template <typename PSOCreateInfoType>
+ void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal);
+
virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final;
bool CheckExtension(const Char* ExtensionString);
void FlagSupportedTexFormats();
diff --git a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp
index bc0f32e6..d4c4b87e 100644
--- a/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp
+++ b/Graphics/GraphicsEngineOpenGL/include/ShaderGLImpl.hpp
@@ -92,7 +92,7 @@ public:
/// Implementation of IShader::GetResource() in OpenGL backend.
virtual void DILIGENT_CALL_TYPE GetResourceDesc(Uint32 Index, ShaderResourceDesc& ResourceDesc) const override final;
- static GLObjectWrappers::GLProgramObj LinkProgram(IShader** ppShaders, Uint32 NumShaders, bool IsSeparableProgram);
+ static GLObjectWrappers::GLProgramObj LinkProgram(ShaderGLImpl** ppShaders, Uint32 NumShaders, bool IsSeparableProgram);
private:
GLObjectWrappers::GLShaderObj m_GLShaderObj;
diff --git a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
index 4bba7d46..ac99cfa0 100644
--- a/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/BufferGLImpl.cpp
@@ -96,8 +96,8 @@ BufferGLImpl::BufferGLImpl(IReferenceCounters* pRefCounters,
LOG_ERROR_AND_THROW("Unified resources are not supported in OpenGL/GLES");
}
- if (m_Desc.Usage == USAGE_STATIC)
- VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
+ if (m_Desc.Usage == USAGE_IMMUTABLE)
+ VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers");
// TODO: find out if it affects performance if the buffer is originally bound to one target
// and then bound to another (such as first to GL_ARRAY_BUFFER and then to GL_UNIFORM_BUFFER)
diff --git a/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/DeviceContextGLImpl.cpp
index deea5ade..7b09f9ce 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/GLPipelineResourceLayout.cpp b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp
index 0955a54f..d2f9cddc 100644
--- a/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/GLPipelineResourceLayout.cpp
@@ -147,11 +147,11 @@ void GLPipelineResourceLayout::Initialize(GLProgramResources* P
{
auto VarType = GetShaderVariableType(ShaderStages, Sam.Name, ResourceLayout);
VERIFY_EXPR(IsAllowedType(VarType, DbgAllowedTypeBits));
- Int32 StaticSamplerIdx = -1;
+ Int32 ImtblSamplerIdx = -1;
if (Sam.ResourceType == SHADER_RESOURCE_TYPE_TEXTURE_SRV)
{
- StaticSamplerIdx = FindStaticSampler(ResourceLayout.StaticSamplers, ResourceLayout.NumStaticSamplers, ShaderStages,
- Sam.Name, nullptr);
+ ImtblSamplerIdx = FindImmutableSampler(ResourceLayout.ImmutableSamplers, ResourceLayout.NumImmutableSamplers, ShaderStages,
+ Sam.Name, nullptr);
}
auto* pSamVar = new (&GetResource<SamplerBindInfo>(VarCounters.NumSamplers++))
SamplerBindInfo //
@@ -159,7 +159,7 @@ void GLPipelineResourceLayout::Initialize(GLProgramResources* P
Sam,
*this,
VarType,
- StaticSamplerIdx //
+ ImtblSamplerIdx //
};
SamplerBindingSlots = std::max(SamplerBindingSlots, pSamVar->m_Attribs.Binding + pSamVar->m_Attribs.ArraySize);
},
@@ -290,13 +290,13 @@ void GLPipelineResourceLayout::SamplerBindInfo::BindResource(IDeviceObject* pVie
{
auto& CachedTexSampler = ResourceCache.GetConstSampler(m_Attribs.Binding + ArrayIndex);
VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {TEXTURE_VIEW_SHADER_RESOURCE}, CachedTexSampler.pView.RawPtr());
- if (m_StaticSamplerIdx >= 0)
+ if (m_ImtblSamplerIdx >= 0)
{
- VERIFY(CachedTexSampler.pSampler != nullptr, "Static samplers must be initialized by PipelineStateGLImpl::InitializeSRBResourceCache!");
+ VERIFY(CachedTexSampler.pSampler != nullptr, "Immutable samplers must be initialized by PipelineStateGLImpl::InitializeSRBResourceCache!");
}
}
#endif
- ResourceCache.SetTexSampler(m_Attribs.Binding + ArrayIndex, std::move(pViewGL), m_StaticSamplerIdx < 0);
+ ResourceCache.SetTexSampler(m_Attribs.Binding + ArrayIndex, std::move(pViewGL), m_ImtblSamplerIdx < 0);
}
else if (m_Attribs.ResourceType == SHADER_RESOURCE_TYPE_BUFFER_SRV)
{
@@ -307,6 +307,16 @@ void GLPipelineResourceLayout::SamplerBindInfo::BindResource(IDeviceObject* pVie
{
auto& CachedBuffSampler = ResourceCache.GetConstSampler(m_Attribs.Binding + ArrayIndex);
VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE}, CachedBuffSampler.pView.RawPtr());
+ if (pViewGL != nullptr)
+ {
+ const auto& ViewDesc = pViewGL->GetDesc();
+ const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc();
+ if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW))
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ m_Attribs.Name, ": formatted buffer view is expected.");
+ }
+ }
}
#endif
ResourceCache.SetBufSampler(m_Attribs.Binding + ArrayIndex, std::move(pViewGL));
@@ -347,6 +357,16 @@ void GLPipelineResourceLayout::ImageBindInfo::BindResource(IDeviceObject* pView,
{
auto& CachedUAV = ResourceCache.GetConstImage(m_Attribs.Binding + ArrayIndex);
VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {BUFFER_VIEW_UNORDERED_ACCESS}, CachedUAV.pView.RawPtr());
+ if (pViewGL != nullptr)
+ {
+ const auto& ViewDesc = pViewGL->GetDesc();
+ const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc();
+ if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW))
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ m_Attribs.Name, ": formatted buffer view is expected.");
+ }
+ }
}
#endif
ResourceCache.SetBufImage(m_Attribs.Binding + ArrayIndex, std::move(pViewGL));
@@ -375,6 +395,16 @@ void GLPipelineResourceLayout::StorageBufferBindInfo::BindResource(IDeviceObject
auto& CachedSSBO = ResourceCache.GetConstSSBO(m_Attribs.Binding + ArrayIndex);
// HLSL structured buffers are mapped to SSBOs in GLSL
VerifyResourceViewBinding(m_Attribs, GetType(), ArrayIndex, pView, pViewGL.RawPtr(), {BUFFER_VIEW_SHADER_RESOURCE, BUFFER_VIEW_UNORDERED_ACCESS}, CachedSSBO.pBufferView.RawPtr());
+ if (pViewGL != nullptr)
+ {
+ const auto& ViewDesc = pViewGL->GetDesc();
+ const auto& BuffDesc = pViewGL->GetBuffer()->GetDesc();
+ if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW)
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ m_Attribs.Name, ": structured buffer view is expected.");
+ }
+ }
}
#endif
ResourceCache.SetSSBO(m_Attribs.Binding + ArrayIndex, std::move(pViewGL));
@@ -764,9 +794,9 @@ bool GLPipelineResourceLayout::dvpVerifyBindings(const GLProgramResourceCache& R
else
{
const auto& CachedSampler = ResourceCache.GetConstSampler(BindPoint);
- if (sam.m_StaticSamplerIdx >= 0 && CachedSampler.pSampler == nullptr)
+ if (sam.m_ImtblSamplerIdx >= 0 && CachedSampler.pSampler == nullptr)
{
- LOG_ERROR_MESSAGE("Static sampler is not initialized for texture '", sam.m_Attribs.Name, "'");
+ LOG_ERROR_MESSAGE("Immutable sampler is not initialized for texture '", sam.m_Attribs.Name, "'");
BindingsOK = false;
}
}
diff --git a/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp b/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp
index 95557557..84cdc46e 100644
--- a/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/GLProgramResourceCache.cpp
@@ -92,7 +92,9 @@ GLProgramResourceCache::~GLProgramResourceCache()
void GLProgramResourceCache::Destroy(IMemoryAllocator& MemAllocator)
{
- VERIFY(IsInitialized(), "Resource cache is not initialized");
+ if (!IsInitialized())
+ return;
+
VERIFY(m_pdbgMemoryAllocator == &MemAllocator, "The allocator does not match the one used to create resources");
for (Uint32 cb = 0; cb < GetUBCount(); ++cb)
diff --git a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
index 399983c9..8b429094 100644
--- a/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/PipelineStateGLImpl.cpp
@@ -36,10 +36,47 @@
namespace Diligent
{
-PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters,
- RenderDeviceGLImpl* pDeviceGL,
- const PipelineStateCreateInfo& CreateInfo,
- bool bIsDeviceInternal) :
+
+template <typename PSOCreateInfoType>
+void PipelineStateGLImpl::Initialize(const PSOCreateInfoType& CreateInfo, const std::vector<GLPipelineShaderStageInfo>& ShaderStages)
+{
+ LinearAllocator MemPool{GetRawAllocator()};
+ VERIFY_EXPR(m_NumShaderStages > 0 && m_NumShaderStages == ShaderStages.size());
+ if (!GetDevice()->GetDeviceCaps().Features.SeparablePrograms)
+ m_NumShaderStages = 1;
+
+ const auto NumPrograms = GetNumShaderStages();
+
+ MemPool.AddSpace<GLProgramObj>(NumPrograms);
+ MemPool.AddSpace<GLProgramResources>(NumPrograms);
+ MemPool.AddSpace<SamplerPtr>(m_Desc.ResourceLayout.NumImmutableSamplers);
+
+ ReserveSpaceForPipelineDesc(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ m_GLPrograms = MemPool.ConstructArray<GLProgramObj>(NumPrograms, false);
+
+ // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_GLPrograms);
+ (void)Ptr;
+
+ m_ProgramResources = MemPool.ConstructArray<GLProgramResources>(NumPrograms);
+
+ m_ImmutableSamplers = MemPool.ConstructArray<SamplerPtr>(m_Desc.ResourceLayout.NumImmutableSamplers);
+
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
+
+ InitResourceLayouts(ShaderStages, MemPool);
+ InitializePipelineDesc(CreateInfo, MemPool);
+}
+
+PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceGLImpl* pDeviceGL,
+ const GraphicsPipelineStateCreateInfo& CreateInfo,
+ bool bIsDeviceInternal) :
// clang-format off
TPipelineStateBase
{
@@ -52,22 +89,110 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun
m_StaticResourceLayout{*this}
// clang-format on
{
- if (m_Desc.IsAnyGraphicsPipeline() && m_pPS == nullptr)
+ try
+ {
+ std::vector<GLPipelineShaderStageInfo> ShaderStages;
+ ExtractShaders<ShaderGLImpl>(CreateInfo, ShaderStages);
+
+ RefCntAutoPtr<ShaderGLImpl> pTempPS;
+ if (CreateInfo.pPS == nullptr)
+ {
+ // Some OpenGL implementations fail if fragment shader is not present, so
+ // create a dummy one.
+ ShaderCreateInfo ShaderCI;
+ ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL;
+ ShaderCI.Source = "void main(){}";
+ ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
+ ShaderCI.Desc.Name = "Dummy fragment shader";
+ pDeviceGL->CreateShader(ShaderCI, reinterpret_cast<IShader**>(static_cast<ShaderGLImpl**>(&pTempPS)));
+
+ ShaderStages.emplace_back(SHADER_TYPE_PIXEL, pTempPS);
+ m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_PIXEL;
+ }
+
+ Initialize(CreateInfo, ShaderStages);
+ }
+ catch (...)
{
- // Some OpenGL implementations fail if fragment shader is not present, so
- // create a dummy one.
- ShaderCreateInfo ShaderCI;
- ShaderCI.SourceLanguage = SHADER_SOURCE_LANGUAGE_GLSL;
- ShaderCI.Source = "void main(){}";
- ShaderCI.Desc.ShaderType = SHADER_TYPE_PIXEL;
- ShaderCI.Desc.Name = "Dummy fragment shader";
- pDeviceGL->CreateShader(ShaderCI, &m_pPS);
- m_Desc.GraphicsPipeline.pPS = m_pPS;
- m_ppShaders[m_NumShaders++] = m_pPS;
+ Destruct();
}
+}
+
+PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceGLImpl* pDeviceGL,
+ const ComputePipelineStateCreateInfo& CreateInfo,
+ bool bIsDeviceInternal) :
+ // clang-format off
+ TPipelineStateBase
+ {
+ pRefCounters,
+ pDeviceGL,
+ CreateInfo.PSODesc,
+ bIsDeviceInternal
+ },
+ m_ResourceLayout {*this},
+ m_StaticResourceLayout{*this}
+// clang-format on
+{
+ try
+ {
+ std::vector<GLPipelineShaderStageInfo> ShaderStages;
+ ExtractShaders<ShaderGLImpl>(CreateInfo, ShaderStages);
- auto& DeviceCaps = pDeviceGL->GetDeviceCaps();
- VERIFY(DeviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized");
+ Initialize(CreateInfo, ShaderStages);
+ }
+ catch (...)
+ {
+ Destruct();
+ }
+}
+
+PipelineStateGLImpl::~PipelineStateGLImpl()
+{
+ Destruct();
+}
+
+void PipelineStateGLImpl::Destruct()
+{
+ auto& RawAllocator = GetRawAllocator();
+ m_StaticResourceCache.Destroy(RawAllocator);
+ GetDevice()->OnDestroyPSO(this);
+
+ if (m_ImmutableSamplers != nullptr)
+ {
+ for (Uint32 i = 0; i < m_Desc.ResourceLayout.NumImmutableSamplers; ++i)
+ {
+ m_ImmutableSamplers[i].~SamplerPtr();
+ }
+ }
+
+ for (Uint32 i = 0; i < GetNumShaderStages(); ++i)
+ {
+ if (m_GLPrograms != nullptr)
+ {
+ m_GLPrograms[i].~GLProgramObj();
+ }
+ if (m_ProgramResources != nullptr)
+ {
+ m_ProgramResources[i].~GLProgramResources();
+ }
+ }
+
+ if (void* pRawMem = m_GLPrograms)
+ {
+ RawAllocator.Free(pRawMem);
+ }
+}
+
+IMPLEMENT_QUERY_INTERFACE(PipelineStateGLImpl, IID_PipelineStateGL, TPipelineStateBase)
+
+
+void PipelineStateGLImpl::InitResourceLayouts(const std::vector<GLPipelineShaderStageInfo>& ShaderStages,
+ LinearAllocator& MemPool)
+{
+ auto* const pDeviceGL = GetDevice();
+ const auto& deviceCaps = pDeviceGL->GetDeviceCaps();
+ VERIFY(deviceCaps.DevType != RENDER_DEVICE_TYPE_UNDEFINED, "Device caps are not initialized");
auto pImmediateCtx = m_pDevice->GetImmediateContext();
VERIFY_EXPR(pImmediateCtx);
@@ -78,18 +203,16 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun
m_TotalSamplerBindings = 0;
m_TotalImageBindings = 0;
m_TotalStorageBufferBindings = 0;
- if (DeviceCaps.Features.SeparablePrograms)
+ if (deviceCaps.Features.SeparablePrograms)
{
// Program pipelines are not shared between GL contexts, so we cannot create
// it now
m_ShaderResourceLayoutHash = 0;
- m_ProgramResources.resize(m_NumShaders);
- m_GLPrograms.reserve(m_NumShaders);
- for (Uint32 i = 0; i < m_NumShaders; ++i)
+ for (size_t i = 0; i < ShaderStages.size(); ++i)
{
- auto* pShaderGL = GetShader<ShaderGLImpl>(i);
+ auto* pShaderGL = ShaderStages[i].pShader;
const auto& ShaderDesc = pShaderGL->GetDesc();
- m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(&m_ppShaders[i], 1, true));
+ m_GLPrograms[i] = GLProgramObj{ShaderGLImpl::LinkProgram(&pShaderGL, 1, true)};
// Load uniforms and assign bindings
m_ProgramResources[i].LoadUniforms(ShaderDesc.ShaderType, m_GLPrograms[i], GLState,
m_TotalUniformBufferBindings,
@@ -102,15 +225,19 @@ PipelineStateGLImpl::PipelineStateGLImpl(IReferenceCounters* pRefCoun
}
else
{
- m_GLPrograms.emplace_back(ShaderGLImpl::LinkProgram(m_ppShaders.data(), m_NumShaders, false));
- m_ProgramResources.resize(1);
- SHADER_TYPE ShaderStages = SHADER_TYPE_UNKNOWN;
- for (Uint32 i = 0; i < m_NumShaders; ++i)
+ std::vector<ShaderGLImpl*> Shaders;
+
+ SHADER_TYPE ActiveStages = SHADER_TYPE_UNKNOWN;
+ for (const auto& Stage : ShaderStages)
{
- const auto& ShaderDesc = m_ppShaders[i]->GetDesc();
- ShaderStages |= ShaderDesc.ShaderType;
+ Shaders.push_back(Stage.pShader);
+ VERIFY((ActiveStages & Stage.Type) == 0, "Shader stage ", GetShaderTypeLiteralName(Stage.Type), " is already active");
+ ActiveStages |= Stage.Type;
}
- m_ProgramResources[0].LoadUniforms(ShaderStages, m_GLPrograms[0], GLState,
+
+ m_GLPrograms[0] = ShaderGLImpl::LinkProgram(Shaders.data(), static_cast<Uint32>(Shaders.size()), false);
+
+ m_ProgramResources[0].LoadUniforms(ActiveStages, m_GLPrograms[0], GLState,
m_TotalUniformBufferBindings,
m_TotalSamplerBindings,
m_TotalImageBindings,
@@ -120,38 +247,27 @@ 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, GetNumShaderStages(), m_Desc.PipelineType, m_Desc.ResourceLayout, nullptr, 0, nullptr);
}
- m_StaticSamplers.resize(m_Desc.ResourceLayout.NumStaticSamplers);
- for (Uint32 s = 0; s < m_Desc.ResourceLayout.NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < m_Desc.ResourceLayout.NumImmutableSamplers; ++s)
{
- pDeviceGL->CreateSampler(m_Desc.ResourceLayout.StaticSamplers[s].Desc, &m_StaticSamplers[s]);
+ pDeviceGL->CreateSampler(m_Desc.ResourceLayout.ImmutableSamplers[s].Desc, &m_ImmutableSamplers[s]);
}
{
// Clone only static variables into static resource layout, assign and initialize static resource cache
const SHADER_RESOURCE_VARIABLE_TYPE StaticVars[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
- m_StaticResourceLayout.Initialize(m_ProgramResources.data(), static_cast<Uint32>(m_GLPrograms.size()), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache);
- InitStaticSamplersInResourceCache(m_StaticResourceLayout, m_StaticResourceCache);
+ m_StaticResourceLayout.Initialize(m_ProgramResources, GetNumShaderStages(), m_Desc.PipelineType, m_Desc.ResourceLayout, StaticVars, _countof(StaticVars), &m_StaticResourceCache);
+ InitImmutableSamplersInResourceCache(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));
@@ -168,10 +284,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;
@@ -196,7 +312,7 @@ void PipelineStateGLImpl::CommitProgram(GLContextState& State)
}
else
{
- VERIFY_EXPR(m_GLPrograms.size() == 1);
+ VERIFY_EXPR(m_GLPrograms != nullptr);
State.SetProgram(m_GLPrograms[0]);
}
}
@@ -214,10 +330,9 @@ GLObjectWrappers::GLPipelineObj& PipelineStateGLImpl::GetGLProgramPipeline(GLCon
m_GLProgPipelines.emplace_back(Context, true);
auto& ctx_pipeline = m_GLProgPipelines.back();
GLuint Pipeline = ctx_pipeline.second;
- for (Uint32 i = 0; i < m_NumShaders; ++i)
+ for (Uint32 i = 0; i < GetNumShaderStages(); ++i)
{
- auto* pCurrShader = GetShader<ShaderGLImpl>(i);
- auto GLShaderBit = ShaderTypeToGLShaderBit(pCurrShader->GetDesc().ShaderType);
+ auto GLShaderBit = ShaderTypeToGLShaderBit(GetShaderStageType(i));
// If the program has an active code for each stage mentioned in set flags,
// then that code will be used by the pipeline. If program is 0, then the given
// stages are cleared from the pipeline.
@@ -230,19 +345,19 @@ GLObjectWrappers::GLPipelineObj& PipelineStateGLImpl::GetGLProgramPipeline(GLCon
void PipelineStateGLImpl::InitializeSRBResourceCache(GLProgramResourceCache& ResourceCache) const
{
ResourceCache.Initialize(m_TotalUniformBufferBindings, m_TotalSamplerBindings, m_TotalImageBindings, m_TotalStorageBufferBindings, GetRawAllocator());
- InitStaticSamplersInResourceCache(m_ResourceLayout, ResourceCache);
+ InitImmutableSamplersInResourceCache(m_ResourceLayout, ResourceCache);
}
-void PipelineStateGLImpl::InitStaticSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const
+void PipelineStateGLImpl::InitImmutableSamplersInResourceCache(const GLPipelineResourceLayout& ResourceLayout, GLProgramResourceCache& Cache) const
{
for (Uint32 s = 0; s < ResourceLayout.GetNumResources<GLPipelineResourceLayout::SamplerBindInfo>(); ++s)
{
const auto& Sam = ResourceLayout.GetConstResource<GLPipelineResourceLayout::SamplerBindInfo>(s);
- if (Sam.m_StaticSamplerIdx >= 0)
+ if (Sam.m_ImtblSamplerIdx >= 0)
{
- ISampler* pSampler = m_StaticSamplers[Sam.m_StaticSamplerIdx].RawPtr<ISampler>();
+ ISampler* pSampler = m_ImmutableSamplers[Sam.m_ImtblSamplerIdx].RawPtr<ISampler>();
for (Uint32 binding = Sam.m_Attribs.Binding; binding < Sam.m_Attribs.Binding + Sam.m_Attribs.ArraySize; ++binding)
- Cache.SetStaticSampler(binding, pSampler);
+ Cache.SetImmutableSampler(binding, pSampler);
}
}
}
diff --git a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp
index b7bdf993..ca75a9ca 100644
--- a/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/RenderDeviceGLImpl.cpp
@@ -330,6 +330,9 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters,
SET_FEATURE_STATE(WireframeFill, WireframeFillSupported, "Wireframe fill is");
}
+ if (InitAttribs.ForceNonSeparablePrograms)
+ LOG_INFO_MESSAGE("Forcing non-separable shader programs");
+
if (m_DeviceCaps.DevType == RENDER_DEVICE_TYPE_GL)
{
const bool IsGL46OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 6);
@@ -337,7 +340,8 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters,
const bool IsGL42OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 2);
const bool IsGL41OrAbove = (MajorVersion >= 5) || (MajorVersion == 4 && MinorVersion >= 1);
- Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED;
+ SET_FEATURE_STATE(SeparablePrograms, !InitAttribs.ForceNonSeparablePrograms, "Separable programs are");
+ SET_FEATURE_STATE(ShaderResourceQueries, Features.SeparablePrograms != DEVICE_FEATURE_STATE_DISABLED, "Shader resource queries are");
Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED;
Features.WireframeFill = DEVICE_FEATURE_STATE_ENABLED;
// clang-format off
@@ -396,7 +400,8 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters,
bool IsGLES32OrAbove = (MajorVersion >= 4) || (MajorVersion == 3 && MinorVersion >= 2);
// clang-format off
- SET_FEATURE_STATE(SeparablePrograms, IsGLES31OrAbove || strstr(Extensions, "separate_shader_objects"), "Separable programs are");
+ SET_FEATURE_STATE(SeparablePrograms, (IsGLES31OrAbove || strstr(Extensions, "separate_shader_objects")) && !InitAttribs.ForceNonSeparablePrograms, "Separable programs are");
+ SET_FEATURE_STATE(ShaderResourceQueries, Features.SeparablePrograms != DEVICE_FEATURE_STATE_DISABLED, "Shader resource queries are");
SET_FEATURE_STATE(IndirectRendering, IsGLES31OrAbove || strstr(Extensions, "draw_indirect"), "Indirect rendering is");
SET_FEATURE_STATE(WireframeFill, false, "Wireframe fill is");
SET_FEATURE_STATE(MultithreadedResourceCreation, false, "Multithreaded resource creation is");
@@ -457,7 +462,7 @@ RenderDeviceGLImpl::RenderDeviceGLImpl(IReferenceCounters* pRefCounters,
#undef SET_FEATURE_STATE
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
+ static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
#endif
}
@@ -697,13 +702,8 @@ void RenderDeviceGLImpl::CreateSampler(const SamplerDesc& SamplerDesc, ISampler*
CreateSampler(SamplerDesc, ppSampler, false);
}
-
-void RenderDeviceGLImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
-{
- CreatePipelineState(PSOCreateInfo, ppPipelineState, false);
-}
-
-void RenderDeviceGLImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal)
+template <typename PSOCreateInfoType>
+void RenderDeviceGLImpl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal)
{
CreateDeviceObject(
"Pipeline state", PSOCreateInfo.PSODesc, ppPipelineState,
@@ -716,6 +716,26 @@ void RenderDeviceGLImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOC
);
}
+void RenderDeviceGLImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState, bIsDeviceInternal);
+}
+
+void RenderDeviceGLImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState, bool bIsDeviceInternal)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState, bIsDeviceInternal);
+}
+
+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/ShaderGLImpl.cpp b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp
index c7a493cd..e27a8a4c 100644
--- a/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/ShaderGLImpl.cpp
@@ -158,7 +158,7 @@ ShaderGLImpl::ShaderGLImpl(IReferenceCounters* pRefCounters,
if (deviceCaps.Features.SeparablePrograms)
{
- IShader* ThisShader[] = {this};
+ ShaderGLImpl* ThisShader[] = {this};
GLObjectWrappers::GLProgramObj Program = LinkProgram(ThisShader, 1, true);
Uint32 UniformBufferBinding = 0;
Uint32 SamplerBinding = 0;
@@ -178,7 +178,7 @@ ShaderGLImpl::~ShaderGLImpl()
IMPLEMENT_QUERY_INTERFACE(ShaderGLImpl, IID_ShaderGL, TShaderBase)
-GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(IShader** ppShaders, Uint32 NumShaders, bool IsSeparableProgram)
+GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(ShaderGLImpl** ppShaders, Uint32 NumShaders, bool IsSeparableProgram)
{
VERIFY(!IsSeparableProgram || NumShaders == 1, "Number of shaders must be 1 when separable program is created");
@@ -190,7 +190,7 @@ GLObjectWrappers::GLProgramObj ShaderGLImpl::LinkProgram(IShader** ppShaders, Ui
for (Uint32 i = 0; i < NumShaders; ++i)
{
- auto* pCurrShader = ValidatedCast<ShaderGLImpl>(ppShaders[i]);
+ auto* pCurrShader = ppShaders[i];
glAttachShader(GLProg, pCurrShader->m_GLShaderObj);
CHECK_GL_ERROR("glAttachShader() failed");
}
diff --git a/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp b/Graphics/GraphicsEngineOpenGL/src/TexRegionRender.cpp
index bd47e4ac..5861005e 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,19 @@ 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;
+ auto& ResourceLayout = PSOCreateInfo.PSODesc.ResourceLayout;
+
+ 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;
+ ResourceLayout.NumVariables = _countof(Vars);
+ 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/TextureBaseGL.cpp b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
index 564d16cb..243ab1c9 100644
--- a/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
+++ b/Graphics/GraphicsEngineOpenGL/src/TextureBaseGL.cpp
@@ -63,8 +63,8 @@ TextureBaseGL::TextureBaseGL(IReferenceCounters* pRefCounters,
// clang-format on
{
VERIFY(m_GLTexFormat != 0, "Unsupported texture format");
- if (TexDesc.Usage == USAGE_STATIC && pInitData == nullptr)
- LOG_ERROR_AND_THROW("Static Texture must be initialized with data at creation time");
+ if (TexDesc.Usage == USAGE_IMMUTABLE && pInitData == nullptr)
+ LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time");
if (TexDesc.Usage == USAGE_STAGING)
{
diff --git a/Graphics/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 d1732211..d4f2fc36 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;
@@ -104,7 +105,7 @@ public:
const ShaderResourceLayoutVk& GetShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
return m_ShaderResourceLayouts[ShaderInd];
}
@@ -125,33 +126,43 @@ public:
void InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const;
private:
+ using TShaderStages = ShaderResourceLayoutVk::TShaderStages;
+
+ template <typename PSOCreateInfoType>
+ void InitInternalObjects(const PSOCreateInfoType& CreateInfo,
+ std::vector<VkPipelineShaderStageCreateInfo>& vkShaderStages,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules);
+
+ void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
+ TShaderStages& ShaderStages);
+
+ void Destruct();
+
const ShaderResourceLayoutVk& GetStaticShaderResLayout(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
- return m_ShaderResourceLayouts[m_NumShaders + ShaderInd];
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
+ return m_ShaderResourceLayouts[GetNumShaderStages() + ShaderInd];
}
const ShaderResourceCacheVk& GetStaticResCache(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
return m_StaticResCaches[ShaderInd];
}
- ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const
+ const ShaderVariableManagerVk& GetStaticVarMgr(Uint32 ShaderInd) const
{
- VERIFY_EXPR(ShaderInd < m_NumShaders);
+ VERIFY_EXPR(ShaderInd < GetNumShaderStages());
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;
- std::array<VulkanUtilities::ShaderModuleWrapper, MAX_SHADERS_IN_PIPELINE> m_ShaderModules = {};
-
VulkanUtilities::PipelineWrapper m_Pipeline;
PipelineLayout m_PipelineLayout;
diff --git a/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/RenderDeviceVkImpl.hpp
index 94b91cae..d85e9ff3 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,
@@ -192,6 +195,9 @@ public:
IDXCompiler* GetDxCompiler() const { return m_pDxCompiler.get(); }
private:
+ template <typename PSOCreateInfoType>
+ void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState);
+
virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final;
// Submits command buffer for execution to the command queue
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
index 026bb9da..00f2c33a 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceBindingVkImpl.hpp
@@ -76,6 +76,8 @@ public:
bool StaticResourcesInitialized() const { return m_bStaticResourcesInitialized; }
private:
+ void Destruct();
+
ShaderResourceCacheVk m_ShaderResourceCache;
ShaderVariableManagerVk* m_pShaderVarMgrs = nullptr;
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
index a5278cb7..7d77ff48 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceCacheVk.hpp
@@ -75,7 +75,7 @@ public:
};
// clang-format off
- ShaderResourceCacheVk(DbgCacheContentType dbgContentType)
+ ShaderResourceCacheVk(DbgCacheContentType dbgContentType) noexcept
#ifdef DILIGENT_DEBUG
: m_DbgContentType{dbgContentType}
#endif
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
index a6d20641..9452a390 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderResourceLayoutVk.hpp
@@ -110,12 +110,25 @@
namespace Diligent
{
+class ShaderVkImpl;
+
/// Diligent::ShaderResourceLayoutVk class
// sizeof(ShaderResourceLayoutVk)==56 (MS compiler, x64)
class ShaderResourceLayoutVk
{
public:
- ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) :
+ struct ShaderStageInfo
+ {
+ ShaderStageInfo(SHADER_TYPE _Type,
+ const ShaderVkImpl* _pShader);
+
+ const SHADER_TYPE Type;
+ const ShaderVkImpl* const pShader;
+ std::vector<uint32_t> SPIRV;
+ };
+ using TShaderStages = std::vector<ShaderStageInfo>;
+
+ ShaderResourceLayoutVk(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice) noexcept :
m_LogicalDevice{LogicalDevice}
{
}
@@ -131,23 +144,21 @@ public:
// This method is called by PipelineStateVkImpl class instance to initialize static
// shader resource layout and the cache
- void InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- ShaderResourceCacheVk& StaticResourceCache);
+ void InitializeStaticResourceLayout(const ShaderVkImpl* pShader,
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderResourceCacheVk& StaticResourceCache);
// This method is called by PipelineStateVkImpl class instance to initialize resource
// layouts for all shader stages in the pipeline.
- static void Initialize(IRenderDevice* pRenderDevice,
- Uint32 NumShaders,
- ShaderResourceLayoutVk Layouts[],
- std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- std::vector<uint32_t> SPIRVs[],
- class PipelineLayout& PipelineLayout,
- bool VerifyVariables,
- bool VerifyStaticSamplers);
+ static void Initialize(IRenderDevice* pRenderDevice,
+ TShaderStages& ShaderStages,
+ ShaderResourceLayoutVk Layouts[],
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ class PipelineLayout& PipelineLayout,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers);
// sizeof(VkResource) == 24 (x64)
struct VkResource
@@ -279,11 +290,10 @@ public:
#ifdef DILIGENT_DEVELOPMENT
bool dvpVerifyBindings(const ShaderResourceCacheVk& ResourceCache) const;
- static void dvpVerifyResourceLayoutDesc(Uint32 NumShaders,
- const std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- bool VerifyVariables,
- bool VerifyStaticSamplers);
+ static void dvpVerifyResourceLayoutDesc(const TShaderStages& ShaderStages,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers);
#endif
Uint32 GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE VarType) const
@@ -308,6 +318,8 @@ public:
return m_pResources->GetShaderType();
}
+ const SPIRVShaderResources& GetResources() const { return *m_pResources; }
+
const VkResource& GetResource(SHADER_RESOURCE_VARIABLE_TYPE VarType, Uint32 r) const
{
VERIFY_EXPR(r < m_NumResources[VarType]);
@@ -346,16 +358,12 @@ private:
return m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES];
}
- void AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& Allocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- bool AllocateImmutableSamplers);
-
- Uint32 FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg,
- Uint32 CurrResourceCount,
- SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const;
+ void AllocateMemory(const ShaderVkImpl* pShader,
+ IMemoryAllocator& Allocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ bool AllocateImmutableSamplers);
using ImmutableSamplerPtrType = RefCntAutoPtr<ISampler>;
ImmutableSamplerPtrType& GetImmutableSampler(Uint32 n) noexcept
diff --git a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
index 9039e04e..27689c1e 100644
--- a/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/ShaderVariableVk.hpp
@@ -73,21 +73,25 @@ class ShaderVariableVkImpl;
class ShaderVariableManagerVk
{
public:
- ShaderVariableManagerVk(IObject& Owner,
- const ShaderResourceLayoutVk& SrcLayout,
- IMemoryAllocator& Allocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk& ResourceCache);
+ ShaderVariableManagerVk(IObject& Owner,
+ ShaderResourceCacheVk& ResourceCache) noexcept :
+ m_Owner{Owner},
+ m_ResourceCache{ResourceCache}
+ {}
+
+ void Initialize(const ShaderResourceLayoutVk& SrcLayout,
+ IMemoryAllocator& Allocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes);
~ShaderVariableManagerVk();
void DestroyVariables(IMemoryAllocator& Allocator);
- ShaderVariableVkImpl* GetVariable(const Char* Name);
- ShaderVariableVkImpl* GetVariable(Uint32 Index);
+ ShaderVariableVkImpl* GetVariable(const Char* Name) const;
+ ShaderVariableVkImpl* GetVariable(Uint32 Index) const;
- void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags);
+ void BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const;
static size_t GetRequiredMemorySize(const ShaderResourceLayoutVk& Layout,
const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
@@ -115,7 +119,7 @@ private:
Uint32 m_NumVariables = 0;
#ifdef DILIGENT_DEBUG
- IMemoryAllocator& m_DbgAllocator;
+ IMemoryAllocator* m_pDbgAllocator = nullptr;
#endif
};
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
index 51083968..e88c93d2 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanTypeConversions.hpp
@@ -83,6 +83,9 @@ ATTACHMENT_STORE_OP VkAttachmentStoreOpToAttachmentStoreOp(VkAttachmentStoreOp V
VkPipelineStageFlags PipelineStageFlagsToVkPipelineStageFlags(PIPELINE_STAGE_FLAGS PipelineStageFlags);
VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags);
+
+VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType);
+
VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags);
VkGeometryFlagsKHR GeometryFlagsToVkGeometryFlags(RAYTRACING_GEOMETRY_FLAGS Flags);
VkGeometryInstanceFlagsKHR InstanceFlagsToVkGeometryInstanceFlags(RAYTRACING_INSTANCE_FLAGS Flags);
diff --git a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
index 7085765c..6b29af25 100644
--- a/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/BufferVkImpl.cpp
@@ -59,8 +59,8 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
{
ValidateBufferInitData(BuffDesc, pBuffData);
- if (m_Desc.Usage == USAGE_STATIC)
- VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
+ if (m_Desc.Usage == USAGE_IMMUTABLE)
+ VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers");
if (m_Desc.Usage == USAGE_DYNAMIC)
VERIFY(pBuffData == nullptr || pBuffData->pData == nullptr, "Initial data must be null for dynamic buffers");
@@ -218,7 +218,7 @@ BufferVkImpl::BufferVkImpl(IReferenceCounters* pRefCounters,
VkMemoryPropertyFlags vkMemoryFlags = 0;
switch (m_Desc.Usage)
{
- case USAGE_STATIC:
+ case USAGE_IMMUTABLE:
case USAGE_DEFAULT:
case USAGE_DYNAMIC: // Dynamic buffer with SRV or UAV bind flag
vkMemoryFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
diff --git a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
index ba36ff7c..99050318 100644
--- a/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/DeviceContextVkImpl.cpp
@@ -260,39 +260,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();
@@ -384,8 +394,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 ("
@@ -414,7 +427,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;
@@ -475,7 +487,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)
@@ -1129,7 +1141,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
@@ -1155,14 +1167,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/EngineFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
index 7a7d8a07..d37655a5 100644
--- a/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/EngineFactoryVk.cpp
@@ -238,7 +238,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
VK_KHR_MAINTENANCE1_EXTENSION_NAME // To allow negative viewport height
};
- const auto& DeiceExtFeatures = PhysicalDevice->GetExtFeatures();
+ const auto& DeviceExtFeatures = PhysicalDevice->GetExtFeatures();
#define ENABLE_FEATURE(IsFeatureSupported, Feature, FeatureName) \
do \
@@ -248,32 +248,32 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
} while (false)
- auto MeshShaderFeats = DeiceExtFeatures.MeshShader;
+ auto MeshShaderFeats = DeviceExtFeatures.MeshShader;
ENABLE_FEATURE(MeshShaderFeats.taskShader != VK_FALSE && MeshShaderFeats.meshShader != VK_FALSE, MeshShaders, "Mesh shaders are");
- auto ShaderFloat16Int8 = DeiceExtFeatures.ShaderFloat16Int8;
+ auto ShaderFloat16Int8 = DeviceExtFeatures.ShaderFloat16Int8;
// clang-format off
ENABLE_FEATURE(ShaderFloat16Int8.shaderFloat16 != VK_FALSE, ShaderFloat16, "16-bit float shader operations are");
ENABLE_FEATURE(ShaderFloat16Int8.shaderInt8 != VK_FALSE, ShaderInt8, "8-bit int shader operations are");
// clang-format on
- auto Storage16BitFeats = DeiceExtFeatures.Storage16Bit;
+ auto Storage16BitFeats = DeviceExtFeatures.Storage16Bit;
// clang-format off
ENABLE_FEATURE(Storage16BitFeats.storageBuffer16BitAccess != VK_FALSE, ResourceBuffer16BitAccess, "16-bit resoure buffer access is");
ENABLE_FEATURE(Storage16BitFeats.uniformAndStorageBuffer16BitAccess != VK_FALSE, UniformBuffer16BitAccess, "16-bit uniform buffer access is");
ENABLE_FEATURE(Storage16BitFeats.storageInputOutput16 != VK_FALSE, ShaderInputOutput16, "16-bit shader inputs/outputs are");
// clang-format on
- auto Storage8BitFeats = DeiceExtFeatures.Storage8Bit;
+ auto Storage8BitFeats = DeviceExtFeatures.Storage8Bit;
// clang-format off
ENABLE_FEATURE(Storage8BitFeats.storageBuffer8BitAccess != VK_FALSE, ResourceBuffer8BitAccess, "8-bit resoure buffer access is");
ENABLE_FEATURE(Storage8BitFeats.uniformAndStorageBuffer8BitAccess != VK_FALSE, UniformBuffer8BitAccess, "8-bit uniform buffer access is");
// clang-format on
- auto RayTracingFeats = DeiceExtFeatures.RayTracing;
- auto BufferDeviceAddressFeats = DeiceExtFeatures.BufferDeviceAddress;
- auto DescriptorIndexingFeats = DeiceExtFeatures.DescriptorIndexing;
- ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeiceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is");
+ auto RayTracingFeats = DeviceExtFeatures.RayTracing;
+ auto BufferDeviceAddressFeats = DeviceExtFeatures.BufferDeviceAddress;
+ auto DescriptorIndexingFeats = DeviceExtFeatures.DescriptorIndexing;
+ ENABLE_FEATURE(RayTracingFeats.rayTracing != VK_FALSE || DeviceExtFeatures.RayTracingNV, RayTracing, "Ray tracing is");
#undef FeatureSupport
@@ -396,7 +396,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
// Ray tracing
if (EngineCI.Features.RayTracing != DEVICE_FEATURE_STATE_DISABLED)
{
- if (DeiceExtFeatures.RayTracingNV)
+ if (DeviceExtFeatures.RayTracingNV)
{
DeviceExtensions.push_back(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME);
DeviceExtensions.push_back(VK_NV_RAY_TRACING_EXTENSION_NAME);
@@ -429,7 +429,7 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk(const EngineVkCreateInfo& _E
}
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
+ static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here.");
#endif
DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
diff --git a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
index 5110c873..e7ab95b1 100644
--- a/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/GenerateMipsVkHelper.cpp
@@ -154,23 +154,23 @@ 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};
PSODesc.ResourceLayout.Variables = &VarDesc;
PSODesc.ResourceLayout.NumVariables = 1;
- const StaticSamplerDesc StaticSampler(SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp);
- PSODesc.ResourceLayout.StaticSamplers = &StaticSampler;
- PSODesc.ResourceLayout.NumStaticSamplers = 1;
+ const ImmutableSamplerDesc ImtblSampler{SHADER_TYPE_COMPUTE, "SrcMip", Sam_LinearClamp};
+ PSODesc.ResourceLayout.ImmutableSamplers = &ImtblSampler;
+ PSODesc.ResourceLayout.NumImmutableSamplers = 1;
- m_DeviceVkImpl.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/PipelineLayout.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
index b7d2b1f4..b221659a 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineLayout.cpp
@@ -40,34 +40,6 @@
namespace Diligent
{
-
-static VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType)
-{
- static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
- switch (ShaderType)
- {
- // clang-format off
- case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
- case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
- case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
- case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT;
- case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
- case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT;
- case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV;
- case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV;
- case SHADER_TYPE_RAY_GEN: return VK_SHADER_STAGE_RAYGEN_BIT_KHR;
- case SHADER_TYPE_RAY_MISS: return VK_SHADER_STAGE_MISS_BIT_KHR;
- case SHADER_TYPE_RAY_CLOSEST_HIT: return VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
- case SHADER_TYPE_RAY_ANY_HIT: return VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
- case SHADER_TYPE_RAY_INTERSECTION: return VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
- case SHADER_TYPE_CALLABLE: return VK_SHADER_STAGE_CALLABLE_BIT_KHR;
- // clang-format on
- default:
- UNEXPECTED("Unknown shader type");
- return VK_SHADER_STAGE_VERTEX_BIT;
- }
-}
-
class ResourceTypeToVkDescriptorType
{
public:
@@ -241,7 +213,7 @@ bool PipelineLayout::DescriptorSetLayoutManager::DescriptorSetLayout::operator==
if ((B0.pImmutableSamplers != nullptr && B1.pImmutableSamplers == nullptr) ||
(B0.pImmutableSamplers == nullptr && B1.pImmutableSamplers != nullptr))
return false;
- // Static samplers themselves should not affect compatibility
+ // Immutable samplers themselves should not affect compatibility
// clang-format on
}
return true;
diff --git a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
index 5c165e32..83512870 100644
--- a/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/PipelineStateVkImpl.cpp
@@ -129,346 +129,324 @@ RenderPassDesc PipelineStateVkImpl::GetImplicitRenderPassDesc(
return RPDesc;
}
-static std::vector<uint32_t> StripReflection(const std::vector<uint32_t>& OriginalSPIRV)
+static bool StripReflection(std::vector<uint32_t>& SPIRV)
{
#if DILIGENT_NO_HLSL
- return OriginalSPIRV;
+ return false;
#else
std::vector<uint32_t> StrippedSPIRV;
spvtools::Optimizer SpirvOptimizer(SPV_ENV_VULKAN_1_0);
// Decorations defined in SPV_GOOGLE_hlsl_functionality1 are the only instructions
// removed by strip-reflect-info pass. SPIRV offsets become INVALID after this operation.
SpirvOptimizer.RegisterPass(spvtools::CreateStripReflectInfoPass());
- auto res = SpirvOptimizer.Run(OriginalSPIRV.data(), OriginalSPIRV.size(), &StrippedSPIRV);
- if (!res)
+ if (SpirvOptimizer.Run(SPIRV.data(), SPIRV.size(), &StrippedSPIRV))
{
- // Optimized SPIRV may be invalid
- StrippedSPIRV.clear();
+ SPIRV = std::move(StrippedSPIRV);
+ return true;
}
- return StrippedSPIRV;
+ else
+ return false;
#endif
}
-PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
- RenderDeviceVkImpl* pDeviceVk,
- const PipelineStateCreateInfo& CreateInfo) :
- TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
- m_SRBMemAllocator{GetRawAllocator()}
+static void InitPipelineShaderStages(const VulkanUtilities::VulkanLogicalDevice& LogicalDevice,
+ ShaderResourceLayoutVk::TShaderStages& ShaderStages,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& vkShaderModules,
+ std::vector<VkPipelineShaderStageCreateInfo>& vkPipelineShaderStages)
{
- m_ResourceLayoutIndex.fill(-1);
-
- const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
-
- // Initialize shader resource layouts
- auto& ShaderResLayoutAllocator = GetRawAllocator();
-
- std::array<std::shared_ptr<const SPIRVShaderResources>, MAX_SHADERS_IN_PIPELINE> ShaderResources;
- std::array<std::vector<uint32_t>, MAX_SHADERS_IN_PIPELINE> ShaderSPIRVs;
-
- m_ShaderResourceLayouts = ALLOCATE(ShaderResLayoutAllocator, "Raw memory for ShaderResourceLayoutVk", ShaderResourceLayoutVk, m_NumShaders * 2);
- m_StaticResCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheVk", ShaderResourceCacheVk, m_NumShaders);
- m_StaticVarsMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
-
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- new (m_ShaderResourceLayouts + s) ShaderResourceLayoutVk{LogicalDevice};
- auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
- ShaderResources[s] = pShaderVk->GetShaderResources();
- ShaderSPIRVs[s] = pShaderVk->GetSPIRV();
-
- const auto ShaderType = pShaderVk->GetDesc().ShaderType;
- const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType);
- m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s);
-
- auto* pStaticResLayout = new (m_ShaderResourceLayouts + m_NumShaders + s) ShaderResourceLayoutVk{LogicalDevice};
- auto* pStaticResCache = new (m_StaticResCaches + s) ShaderResourceCacheVk{ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources};
- pStaticResLayout->InitializeStaticResourceLayout(ShaderResources[s], ShaderResLayoutAllocator, m_Desc.ResourceLayout, m_StaticResCaches[s]);
-
- new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, *pStaticResLayout, GetRawAllocator(), nullptr, 0, *pStaticResCache};
- }
- ShaderResourceLayoutVk::Initialize(pDeviceVk, m_NumShaders, m_ShaderResourceLayouts, ShaderResources.data(), GetRawAllocator(),
- m_Desc.ResourceLayout, ShaderSPIRVs.data(), m_PipelineLayout,
- (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
- (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0);
- m_PipelineLayout.Finalize(LogicalDevice);
-
- if (m_Desc.SRBAllocationGranularity > 1)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderVariableDataSizes = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+ auto& StageInfo = ShaderStages[s];
- Uint32 UnusedNumVars = 0;
- ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars);
- }
-
- Uint32 NumSets = 0;
- auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets);
- auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data());
+ VkPipelineShaderStageCreateInfo StageCI = {};
- m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderVariableDataSizes.data(), 1, &CacheMemorySize);
- }
-
- // Create shader modules and initialize shader stages
- std::array<VkPipelineShaderStageCreateInfo, MAX_SHADERS_IN_PIPELINE> ShaderStages = {};
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
- auto ShaderType = pShaderVk->GetDesc().ShaderType;
-
- auto& StageCI = ShaderStages[s];
StageCI.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
StageCI.pNext = nullptr;
StageCI.flags = 0; // reserved for future use
- switch (ShaderType)
- {
- // clang-format off
- case SHADER_TYPE_VERTEX: StageCI.stage = VK_SHADER_STAGE_VERTEX_BIT; break;
- case SHADER_TYPE_HULL: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT; break;
- case SHADER_TYPE_DOMAIN: StageCI.stage = VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT; break;
- case SHADER_TYPE_GEOMETRY: StageCI.stage = VK_SHADER_STAGE_GEOMETRY_BIT; break;
- case SHADER_TYPE_PIXEL: StageCI.stage = VK_SHADER_STAGE_FRAGMENT_BIT; break;
- case SHADER_TYPE_COMPUTE: StageCI.stage = VK_SHADER_STAGE_COMPUTE_BIT; break;
- case SHADER_TYPE_AMPLIFICATION: StageCI.stage = VK_SHADER_STAGE_TASK_BIT_NV; break;
- case SHADER_TYPE_MESH: StageCI.stage = VK_SHADER_STAGE_MESH_BIT_NV; break;
- default: UNEXPECTED("Unknown shader type");
- // clang-format on
- }
+ StageCI.stage = ShaderTypeToVkShaderStageFlagBit(StageInfo.Type);
VkShaderModuleCreateInfo ShaderModuleCI = {};
ShaderModuleCI.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
ShaderModuleCI.pNext = nullptr;
ShaderModuleCI.flags = 0;
- const auto& SPIRV = ShaderSPIRVs[s];
// We have to strip reflection instructions to fix the follownig validation error:
// SPIR-V module not valid: DecorateStringGOOGLE requires one of the following extensions: SPV_GOOGLE_decorate_string
// Optimizer also performs validation and may catch problems with the byte code.
- auto StrippedSPIRV = StripReflection(SPIRV);
- if (!StrippedSPIRV.empty())
- {
- ShaderModuleCI.codeSize = StrippedSPIRV.size() * sizeof(uint32_t);
- ShaderModuleCI.pCode = StrippedSPIRV.data();
- }
- else
- {
- LOG_ERROR("Failed to strip reflection information from shader '", pShaderVk->GetDesc().Name, "'. This may indicate a problem with the byte code.");
- ShaderModuleCI.codeSize = SPIRV.size() * sizeof(uint32_t);
- ShaderModuleCI.pCode = SPIRV.data();
- }
+ if (!StripReflection(StageInfo.SPIRV))
+ LOG_ERROR("Failed to strip reflection information from shader '", StageInfo.pShader->GetDesc().Name, "'. This may indicate a problem with the byte code.");
+
+ ShaderModuleCI.codeSize = StageInfo.SPIRV.size() * sizeof(uint32_t);
+ ShaderModuleCI.pCode = StageInfo.SPIRV.data();
- m_ShaderModules[s] = LogicalDevice.CreateShaderModule(ShaderModuleCI, pShaderVk->GetDesc().Name);
+ vkShaderModules.push_back(LogicalDevice.CreateShaderModule(ShaderModuleCI, StageInfo.pShader->GetDesc().Name));
- StageCI.module = m_ShaderModules[s];
- StageCI.pName = pShaderVk->GetEntryPoint();
+ StageCI.module = vkShaderModules.back();
+ StageCI.pName = StageInfo.pShader->GetEntryPoint();
StageCI.pSpecializationInfo = nullptr;
+
+ vkPipelineShaderStages.push_back(StageCI);
}
- // Create pipeline
- if (m_Desc.IsComputePipeline())
- {
- auto& ComputePipeline = m_Desc.ComputePipeline;
+ VERIFY_EXPR(vkShaderModules.size() == vkPipelineShaderStages.size());
+}
- if (ComputePipeline.pCS == nullptr)
- LOG_ERROR_AND_THROW("Compute shader is not set in the pipeline desc");
- VkComputePipelineCreateInfo PipelineCI = {};
+static void CreateComputePipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& PSODesc,
+ VulkanUtilities::PipelineWrapper& Pipeline)
+{
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+
+ VkComputePipelineCreateInfo PipelineCI = {};
- PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
- PipelineCI.pNext = nullptr;
+ PipelineCI.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO;
+ PipelineCI.pNext = nullptr;
#ifdef DILIGENT_DEBUG
- PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
+ PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
#endif
- PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
- PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
+ PipelineCI.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
- PipelineCI.stage = ShaderStages[0];
- PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
+ PipelineCI.stage = Stages[0];
+ PipelineCI.layout = Layout.GetVkPipelineLayout();
- m_Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
- }
- else
- {
- const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
- auto& GraphicsPipeline = m_Desc.GraphicsPipeline;
- auto& RPCache = pDeviceVk->GetImplicitRenderPassCache();
+ Pipeline = LogicalDevice.CreateComputePipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name);
+}
- if (m_pRenderPass == nullptr)
- {
- RenderPassCache::RenderPassCacheKey Key{
- GraphicsPipeline.NumRenderTargets,
- GraphicsPipeline.SmplDesc.Count,
- GraphicsPipeline.RTVFormats,
- GraphicsPipeline.DSVFormat};
- m_pRenderPass = RPCache.GetRenderPass(Key);
- }
- VkGraphicsPipelineCreateInfo PipelineCI = {};
+static void CreateGraphicsPipeline(RenderDeviceVkImpl* pDeviceVk,
+ std::vector<VkPipelineShaderStageCreateInfo>& Stages,
+ const PipelineLayout& Layout,
+ const PipelineStateDesc& PSODesc,
+ const GraphicsPipelineDesc& GraphicsPipeline,
+ VulkanUtilities::PipelineWrapper& Pipeline,
+ RefCntAutoPtr<IRenderPass>& pRenderPass)
+{
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+ const auto& PhysicalDevice = pDeviceVk->GetPhysicalDevice();
+ auto& RPCache = pDeviceVk->GetImplicitRenderPassCache();
+
+ if (pRenderPass == nullptr)
+ {
+ RenderPassCache::RenderPassCacheKey Key{
+ GraphicsPipeline.NumRenderTargets,
+ GraphicsPipeline.SmplDesc.Count,
+ GraphicsPipeline.RTVFormats,
+ GraphicsPipeline.DSVFormat};
+ pRenderPass = RPCache.GetRenderPass(Key);
+ }
+
+ VkGraphicsPipelineCreateInfo PipelineCI = {};
- PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
- PipelineCI.pNext = nullptr;
+ PipelineCI.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
+ PipelineCI.pNext = nullptr;
#ifdef DILIGENT_DEBUG
- PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
+ PipelineCI.flags = VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT;
#endif
- PipelineCI.stageCount = m_NumShaders;
- PipelineCI.pStages = ShaderStages.data();
- PipelineCI.layout = m_PipelineLayout.GetVkPipelineLayout();
+ PipelineCI.stageCount = static_cast<Uint32>(Stages.size());
+ PipelineCI.pStages = Stages.data();
+ PipelineCI.layout = Layout.GetVkPipelineLayout();
- VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
+ VkPipelineVertexInputStateCreateInfo VertexInputStateCI = {};
- std::array<VkVertexInputBindingDescription, MAX_LAYOUT_ELEMENTS> BindingDescriptions;
- std::array<VkVertexInputAttributeDescription, MAX_LAYOUT_ELEMENTS> AttributeDescription;
- InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription);
- PipelineCI.pVertexInputState = &VertexInputStateCI;
+ std::array<VkVertexInputBindingDescription, MAX_LAYOUT_ELEMENTS> BindingDescriptions;
+ std::array<VkVertexInputAttributeDescription, MAX_LAYOUT_ELEMENTS> AttributeDescription;
+ InputLayoutDesc_To_VkVertexInputStateCI(GraphicsPipeline.InputLayout, VertexInputStateCI, BindingDescriptions, AttributeDescription);
+ PipelineCI.pVertexInputState = &VertexInputStateCI;
- VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {};
+ VkPipelineInputAssemblyStateCreateInfo InputAssemblyCI = {};
- InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
- InputAssemblyCI.pNext = nullptr;
- InputAssemblyCI.flags = 0; // reserved for future use
- InputAssemblyCI.primitiveRestartEnable = VK_FALSE;
- PipelineCI.pInputAssemblyState = &InputAssemblyCI;
+ InputAssemblyCI.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
+ InputAssemblyCI.pNext = nullptr;
+ InputAssemblyCI.flags = 0; // reserved for future use
+ InputAssemblyCI.primitiveRestartEnable = VK_FALSE;
+ PipelineCI.pInputAssemblyState = &InputAssemblyCI;
- VkPipelineTessellationStateCreateInfo TessStateCI = {};
+ VkPipelineTessellationStateCreateInfo TessStateCI = {};
- TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
- TessStateCI.pNext = nullptr;
- TessStateCI.flags = 0; // reserved for future use
- PipelineCI.pTessellationState = &TessStateCI;
+ TessStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
+ TessStateCI.pNext = nullptr;
+ TessStateCI.flags = 0; // reserved for future use
+ PipelineCI.pTessellationState = &TessStateCI;
- if (m_Desc.PipelineType == PIPELINE_TYPE_MESH)
- {
- // Input assembly is not used in the mesh pipeline, so topology may contain any value.
- // Validation layers may generate a warning if point_list topology is used, so use MAX_ENUM value.
- InputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
+ 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.
+ InputAssemblyCI.topology = VK_PRIMITIVE_TOPOLOGY_MAX_ENUM;
- // Vertex input state and tessellation state are ignored in a mesh pipeline and should be null.
- PipelineCI.pVertexInputState = nullptr;
- PipelineCI.pTessellationState = nullptr;
- }
- else
- {
- PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints);
- }
+ // Vertex input state and tessellation state are ignored in a mesh pipeline and should be null.
+ PipelineCI.pVertexInputState = nullptr;
+ PipelineCI.pTessellationState = nullptr;
+ }
+ else
+ {
+ PrimitiveTopology_To_VkPrimitiveTopologyAndPatchCPCount(GraphicsPipeline.PrimitiveTopology, InputAssemblyCI.topology, TessStateCI.patchControlPoints);
+ }
- VkPipelineViewportStateCreateInfo ViewPortStateCI = {};
-
- ViewPortStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
- ViewPortStateCI.pNext = nullptr;
- ViewPortStateCI.flags = 0; // reserved for future use
- ViewPortStateCI.viewportCount =
- GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used
- // by the pipeline is still specified by the viewportCount member (23.5)
- ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states
- ViewPortStateCI.scissorCount = ViewPortStateCI.viewportCount; // the number of scissors must match the number of viewports (23.5)
- // (why the hell it is in the struct then?)
- VkRect2D ScissorRect = {};
- if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
- {
- ViewPortStateCI.pScissors = nullptr; // Ignored if the scissor state is dynamic
- }
- else
+ VkPipelineViewportStateCreateInfo ViewPortStateCI = {};
+
+ ViewPortStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
+ ViewPortStateCI.pNext = nullptr;
+ ViewPortStateCI.flags = 0; // reserved for future use
+ ViewPortStateCI.viewportCount =
+ GraphicsPipeline.NumViewports; // Even though we use dynamic viewports, the number of viewports used
+ // by the pipeline is still specified by the viewportCount member (23.5)
+ ViewPortStateCI.pViewports = nullptr; // We will be using dynamic viewport & scissor states
+ ViewPortStateCI.scissorCount = ViewPortStateCI.viewportCount; // the number of scissors must match the number of viewports (23.5)
+ // (why the hell it is in the struct then?)
+ VkRect2D ScissorRect = {};
+ if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ {
+ ViewPortStateCI.pScissors = nullptr; // Ignored if the scissor state is dynamic
+ }
+ else
+ {
+ const auto& Props = PhysicalDevice.GetProperties();
+ // There are limitiations on the viewport width and height (23.5), but
+ // it is not clear if there are limitations on the scissor rect width and
+ // height
+ ScissorRect.extent.width = Props.limits.maxViewportDimensions[0];
+ ScissorRect.extent.height = Props.limits.maxViewportDimensions[1];
+ ViewPortStateCI.pScissors = &ScissorRect;
+ }
+ PipelineCI.pViewportState = &ViewPortStateCI;
+
+ VkPipelineRasterizationStateCreateInfo RasterizerStateCI =
+ RasterizerStateDesc_To_VkRasterizationStateCI(GraphicsPipeline.RasterizerDesc);
+ PipelineCI.pRasterizationState = &RasterizerStateCI;
+
+ // Multisample state (24)
+ VkPipelineMultisampleStateCreateInfo MSStateCI = {};
+
+ MSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
+ MSStateCI.pNext = nullptr;
+ MSStateCI.flags = 0; // reserved for future use
+ // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of
+ // pMultisampleState must be the same as the sample count for those subpass attachments
+ MSStateCI.rasterizationSamples = static_cast<VkSampleCountFlagBits>(GraphicsPipeline.SmplDesc.Count);
+ MSStateCI.sampleShadingEnable = VK_FALSE;
+ MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE.
+ uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples
+ MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with
+ // the coverage information generated during rasterization (25.3)
+ MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on
+ // the alpha component of the fragment's first color output
+ MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one
+ PipelineCI.pMultisampleState = &MSStateCI;
+
+ VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI =
+ DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc);
+ PipelineCI.pDepthStencilState = &DepthStencilStateCI;
+
+ const auto& RPDesc = pRenderPass->GetDesc();
+ const auto NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount;
+ VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments);
+ std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(NumRTAttachments);
+
+ VkPipelineColorBlendStateCreateInfo BlendStateCI = {};
+
+ BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr;
+ BlendStateCI.attachmentCount = NumRTAttachments; // must equal the colorAttachmentCount for the subpass
+ // in which this pipeline is used.
+ BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates);
+ PipelineCI.pColorBlendState = &BlendStateCI;
+
+
+ VkPipelineDynamicStateCreateInfo DynamicStateCI = {};
+
+ DynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
+ DynamicStateCI.pNext = nullptr;
+ DynamicStateCI.flags = 0; // reserved for future use
+ std::vector<VkDynamicState> DynamicStates =
{
- const auto& Props = PhysicalDevice.GetProperties();
- // There are limitiations on the viewport width and height (23.5), but
- // it is not clear if there are limitations on the scissor rect width and
- // height
- ScissorRect.extent.width = Props.limits.maxViewportDimensions[0];
- ScissorRect.extent.height = Props.limits.maxViewportDimensions[1];
- ViewPortStateCI.pScissors = &ScissorRect;
- }
- PipelineCI.pViewportState = &ViewPortStateCI;
-
- VkPipelineRasterizationStateCreateInfo RasterizerStateCI =
- RasterizerStateDesc_To_VkRasterizationStateCI(GraphicsPipeline.RasterizerDesc);
- PipelineCI.pRasterizationState = &RasterizerStateCI;
-
- // Multisample state (24)
- VkPipelineMultisampleStateCreateInfo MSStateCI = {};
-
- MSStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
- MSStateCI.pNext = nullptr;
- MSStateCI.flags = 0; // reserved for future use
- // If subpass uses color and/or depth/stencil attachments, then the rasterizationSamples member of
- // pMultisampleState must be the same as the sample count for those subpass attachments
- MSStateCI.rasterizationSamples = static_cast<VkSampleCountFlagBits>(GraphicsPipeline.SmplDesc.Count);
- MSStateCI.sampleShadingEnable = VK_FALSE;
- MSStateCI.minSampleShading = 0; // a minimum fraction of sample shading if sampleShadingEnable is set to VK_TRUE.
- uint32_t SampleMask[] = {GraphicsPipeline.SampleMask, 0}; // Vulkan spec allows up to 64 samples
- MSStateCI.pSampleMask = SampleMask; // an array of static coverage information that is ANDed with
- // the coverage information generated during rasterization (25.3)
- MSStateCI.alphaToCoverageEnable = VK_FALSE; // whether a temporary coverage value is generated based on
- // the alpha component of the fragment's first color output
- MSStateCI.alphaToOneEnable = VK_FALSE; // whether the alpha component of the fragment's first color output is replaced with one
- PipelineCI.pMultisampleState = &MSStateCI;
-
- VkPipelineDepthStencilStateCreateInfo DepthStencilStateCI =
- DepthStencilStateDesc_To_VkDepthStencilStateCI(GraphicsPipeline.DepthStencilDesc);
- PipelineCI.pDepthStencilState = &DepthStencilStateCI;
-
- const auto& RPDesc = m_pRenderPass->GetDesc();
- const auto NumRTAttachments = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex].RenderTargetAttachmentCount;
- VERIFY_EXPR(GraphicsPipeline.pRenderPass != nullptr || GraphicsPipeline.NumRenderTargets == NumRTAttachments);
- std::vector<VkPipelineColorBlendAttachmentState> ColorBlendAttachmentStates(NumRTAttachments);
-
- VkPipelineColorBlendStateCreateInfo BlendStateCI = {};
-
- BlendStateCI.pAttachments = !ColorBlendAttachmentStates.empty() ? ColorBlendAttachmentStates.data() : nullptr;
- BlendStateCI.attachmentCount = NumRTAttachments; // must equal the colorAttachmentCount for the subpass
- // in which this pipeline is used.
- BlendStateDesc_To_VkBlendStateCI(GraphicsPipeline.BlendDesc, BlendStateCI, ColorBlendAttachmentStates);
- PipelineCI.pColorBlendState = &BlendStateCI;
-
-
- VkPipelineDynamicStateCreateInfo DynamicStateCI = {};
-
- DynamicStateCI.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
- DynamicStateCI.pNext = nullptr;
- DynamicStateCI.flags = 0; // reserved for future use
- std::vector<VkDynamicState> DynamicStates =
- {
- VK_DYNAMIC_STATE_VIEWPORT, // pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be
- // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports
- // used by a pipeline is still specified by the viewportCount member of
- // VkPipelineViewportStateCreateInfo.
+ VK_DYNAMIC_STATE_VIEWPORT, // pViewports state in VkPipelineViewportStateCreateInfo will be ignored and must be
+ // set dynamically with vkCmdSetViewport before any draw commands. The number of viewports
+ // used by a pipeline is still specified by the viewportCount member of
+ // VkPipelineViewportStateCreateInfo.
+
+ VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
+ // and must be set dynamically with vkCmdSetBlendConstants
+
+ VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo
+ // for both front and back will be ignored and must be set dynamically
+ // with vkCmdSetStencilReference
+ };
+
+ if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ {
+ // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set
+ // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles
+ // used by a pipeline is still specified by the scissorCount member of
+ // VkPipelineViewportStateCreateInfo.
+ DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
+ }
+ DynamicStateCI.dynamicStateCount = static_cast<uint32_t>(DynamicStates.size());
+ DynamicStateCI.pDynamicStates = DynamicStates.data();
+ PipelineCI.pDynamicState = &DynamicStateCI;
- VK_DYNAMIC_STATE_BLEND_CONSTANTS, // blendConstants state in VkPipelineColorBlendStateCreateInfo will be ignored
- // and must be set dynamically with vkCmdSetBlendConstants
- VK_DYNAMIC_STATE_STENCIL_REFERENCE // pecifies that the reference state in VkPipelineDepthStencilStateCreateInfo
- // for both front and back will be ignored and must be set dynamically
- // with vkCmdSetStencilReference
- };
+ PipelineCI.renderPass = pRenderPass.RawPtr<IRenderPassVk>()->GetVkRenderPass();
+ 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
- if (GraphicsPipeline.RasterizerDesc.ScissorEnable)
+ Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, PSODesc.Name);
+}
+
+void PipelineStateVkImpl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
+ TShaderStages& ShaderStages)
+{
+ auto* const pDeviceVk = GetDevice();
+ const auto& LogicalDevice = pDeviceVk->GetLogicalDevice();
+
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
+ {
+ auto& StageInfo = ShaderStages[s];
+ const auto ShaderType = StageInfo.Type;
+ const auto ShaderTypeInd = GetShaderTypePipelineIndex(ShaderType, m_Desc.PipelineType);
+
+ m_ResourceLayoutIndex[ShaderTypeInd] = static_cast<Int8>(s);
+
+ auto& StaticResLayout = m_ShaderResourceLayouts[GetNumShaderStages() + s];
+ StaticResLayout.InitializeStaticResourceLayout(StageInfo.pShader, GetRawAllocator(), m_Desc.ResourceLayout, m_StaticResCaches[s]);
+
+ m_StaticVarsMgrs[s].Initialize(StaticResLayout, GetRawAllocator(), nullptr, 0);
+ }
+ ShaderResourceLayoutVk::Initialize(pDeviceVk, ShaderStages, m_ShaderResourceLayouts, GetRawAllocator(),
+ m_Desc.ResourceLayout, m_PipelineLayout,
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
+ (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0);
+ m_PipelineLayout.Finalize(LogicalDevice);
+
+ if (m_Desc.SRBAllocationGranularity > 1)
+ {
+ std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderVariableDataSizes = {};
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- // pScissors state in VkPipelineViewportStateCreateInfo will be ignored and must be set
- // dynamically with vkCmdSetScissor before any draw commands. The number of scissor rectangles
- // used by a pipeline is still specified by the scissorCount member of
- // VkPipelineViewportStateCreateInfo.
- DynamicStates.push_back(VK_DYNAMIC_STATE_SCISSOR);
- }
- DynamicStateCI.dynamicStateCount = static_cast<uint32_t>(DynamicStates.size());
- DynamicStateCI.pDynamicStates = DynamicStates.data();
- PipelineCI.pDynamicState = &DynamicStateCI;
+ const SHADER_RESOURCE_VARIABLE_TYPE AllowedVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+ Uint32 UnusedNumVars = 0;
+ ShaderVariableDataSizes[s] = ShaderVariableManagerVk::GetRequiredMemorySize(m_ShaderResourceLayouts[s], AllowedVarTypes, _countof(AllowedVarTypes), UnusedNumVars);
+ }
- PipelineCI.renderPass = GetRenderPass()->GetVkRenderPass();
- PipelineCI.subpass = m_Desc.GraphicsPipeline.SubpassIndex;
- PipelineCI.basePipelineHandle = VK_NULL_HANDLE; // a pipeline to derive from
- PipelineCI.basePipelineIndex = 0; // an index into the pCreateInfos parameter to use as a pipeline to derive from
+ Uint32 NumSets = 0;
+ auto DescriptorSetSizes = m_PipelineLayout.GetDescriptorSetSizes(NumSets);
+ auto CacheMemorySize = ShaderResourceCacheVk::GetRequiredMemorySize(NumSets, DescriptorSetSizes.data());
- m_Pipeline = LogicalDevice.CreateGraphicsPipeline(PipelineCI, VK_NULL_HANDLE, m_Desc.Name);
+ m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderVariableDataSizes.data(), 1, &CacheMemorySize);
}
m_HasStaticResources = false;
m_HasNonStaticResources = false;
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_STATIC) != 0)
@@ -482,34 +460,137 @@ PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCoun
m_ShaderResourceLayoutHash = m_PipelineLayout.GetHash();
}
+template <typename PSOCreateInfoType>
+void PipelineStateVkImpl::InitInternalObjects(const PSOCreateInfoType& CreateInfo,
+ std::vector<VkPipelineShaderStageCreateInfo>& vkShaderStages,
+ std::vector<VulkanUtilities::ShaderModuleWrapper>& ShaderModules)
+{
+ m_ResourceLayoutIndex.fill(-1);
+
+ TShaderStages ShaderStages;
+ ExtractShaders<ShaderVkImpl>(CreateInfo, ShaderStages);
+
+ LinearAllocator MemPool{GetRawAllocator()};
+
+ const auto NumShaderStages = GetNumShaderStages();
+ VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size());
+
+ MemPool.AddSpace<ShaderResourceCacheVk>(NumShaderStages);
+ MemPool.AddSpace<ShaderResourceLayoutVk>(NumShaderStages * 2);
+ MemPool.AddSpace<ShaderVariableManagerVk>(NumShaderStages);
+
+ ReserveSpaceForPipelineDesc(CreateInfo, MemPool);
+
+ MemPool.Reserve();
+
+ const auto& LogicalDevice = GetDevice()->GetLogicalDevice();
+
+ m_StaticResCaches = MemPool.ConstructArray<ShaderResourceCacheVk>(NumShaderStages, ShaderResourceCacheVk::DbgCacheContentType::StaticShaderResources);
+
+ // The memory is now owned by PipelineStateVkImpl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_StaticResCaches);
+ (void)Ptr;
+
+ m_ShaderResourceLayouts = MemPool.ConstructArray<ShaderResourceLayoutVk>(NumShaderStages * 2, LogicalDevice);
+
+ m_StaticVarsMgrs = MemPool.Allocate<ShaderVariableManagerVk>(NumShaderStages);
+ for (Uint32 s = 0; s < NumShaderStages; ++s)
+ new (m_StaticVarsMgrs + s) ShaderVariableManagerVk{*this, m_StaticResCaches[s]};
+
+ InitializePipelineDesc(CreateInfo, MemPool);
+
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
+
+ InitResourceLayouts(CreateInfo, ShaderStages);
+
+ // Create shader modules and initialize shader stages
+ InitPipelineShaderStages(GetDevice()->GetLogicalDevice(), ShaderStages, ShaderModules, vkShaderStages);
+}
+
+PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVk,
+ const GraphicsPipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ try
+ {
+ std::vector<VkPipelineShaderStageCreateInfo> vkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> ShaderModules;
+
+ InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules);
+
+ CreateGraphicsPipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, GetGraphicsPipelineDesc(), m_Pipeline, m_pRenderPass);
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
+}
+
+
+PipelineStateVkImpl::PipelineStateVkImpl(IReferenceCounters* pRefCounters,
+ RenderDeviceVkImpl* pDeviceVk,
+ const ComputePipelineStateCreateInfo& CreateInfo) :
+ TPipelineStateBase{pRefCounters, pDeviceVk, CreateInfo.PSODesc},
+ m_SRBMemAllocator{GetRawAllocator()}
+{
+ try
+ {
+ std::vector<VkPipelineShaderStageCreateInfo> vkShaderStages;
+ std::vector<VulkanUtilities::ShaderModuleWrapper> ShaderModules;
+
+ InitInternalObjects(CreateInfo, vkShaderStages, ShaderModules);
+
+ CreateComputePipeline(pDeviceVk, vkShaderStages, m_PipelineLayout, m_Desc, m_Pipeline);
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
+}
+
+
PipelineStateVkImpl::~PipelineStateVkImpl()
{
+ Destruct();
+}
+
+void PipelineStateVkImpl::Destruct()
+{
m_pDevice->SafeReleaseDeviceObject(std::move(m_Pipeline), m_Desc.CommandQueueMask);
m_PipelineLayout.Release(m_pDevice, m_Desc.CommandQueueMask);
- for (auto& ShaderModule : m_ShaderModules)
+ auto& RawAllocator = GetRawAllocator();
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- if (ShaderModule != VK_NULL_HANDLE)
+ if (m_StaticVarsMgrs != nullptr)
{
- m_pDevice->SafeReleaseDeviceObject(std::move(ShaderModule), m_Desc.CommandQueueMask);
+ m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator());
+ m_StaticVarsMgrs[s].~ShaderVariableManagerVk();
}
- }
- auto& RawAllocator = GetRawAllocator();
- for (Uint32 s = 0; s < m_NumShaders * 2; ++s)
- {
- m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk();
+ if (m_ShaderResourceLayouts != nullptr)
+ {
+ m_ShaderResourceLayouts[s].~ShaderResourceLayoutVk();
+ m_ShaderResourceLayouts[GetNumShaderStages() + s].~ShaderResourceLayoutVk();
+ }
+
+ if (m_StaticResCaches != nullptr)
+ {
+ m_StaticResCaches[s].~ShaderResourceCacheVk();
+ }
}
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ // All internal objects are allocted in contiguous chunks of memory.
+ if (void* pRawMem = m_StaticResCaches)
{
- m_StaticResCaches[s].~ShaderResourceCacheVk();
- m_StaticVarsMgrs[s].DestroyVariables(GetRawAllocator());
- m_StaticVarsMgrs[s].~ShaderVariableManagerVk();
+ RawAllocator.Free(pRawMem);
}
- RawAllocator.Free(m_ShaderResourceLayouts);
- RawAllocator.Free(m_StaticResCaches);
- RawAllocator.Free(m_StaticVarsMgrs);
}
IMPLEMENT_QUERY_INTERFACE(PipelineStateVkImpl, IID_PipelineStateVk, TPipelineStateBase)
@@ -540,23 +621,22 @@ bool PipelineStateVkImpl::IsCompatibleWith(const IPipelineState* pPSO) const
#ifdef DILIGENT_DEBUG
{
bool IsCompatibleShaders = true;
- if (m_NumShaders != pPSOVk->m_NumShaders)
+ if (GetNumShaderStages() != pPSOVk->GetNumShaderStages())
IsCompatibleShaders = false;
if (IsCompatibleShaders)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
- auto* pShader0 = GetShader<const ShaderVkImpl>(s);
- auto* pShader1 = pPSOVk->GetShader<const ShaderVkImpl>(s);
- if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType)
+ if (GetShaderStageType(s) != pPSOVk->GetShaderStageType(s))
{
IsCompatibleShaders = false;
break;
}
- const auto* pRes0 = pShader0->GetShaderResources().get();
- const auto* pRes1 = pShader1->GetShaderResources().get();
- if (!pRes0->IsCompatibleWith(*pRes1))
+
+ const auto& Res0 = GetShaderResLayout(s).GetResources();
+ const auto& Res1 = pPSOVk->GetShaderResLayout(s).GetResources();
+ if (!Res0.IsCompatibleWith(Res1))
{
IsCompatibleShaders = false;
break;
@@ -614,7 +694,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
auto& ResourceCache = pResBindingVkImpl->GetResourceCache();
#ifdef DILIGENT_DEVELOPMENT
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
m_ShaderResourceLayouts[s].dvpVerifyBindings(ResourceCache);
}
@@ -649,7 +729,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
// Allocate vulkan descriptor set for dynamic resources
DynamicDescrSet = pCtxVkImpl->AllocateDynamicDescriptorSet(DynamicDescriptorSetVkLayout, DynamicDescrSetName);
// Commit all dynamic resource descriptors
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
const auto& Layout = m_ShaderResourceLayouts[s];
if (Layout.GetResourceCount(SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC) != 0)
@@ -666,7 +746,7 @@ void PipelineStateVkImpl::CommitAndTransitionShaderResources(IShaderResourceBind
void PipelineStateVkImpl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags)
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
auto ShaderType = GetStaticShaderResLayout(s).GetShaderType();
if ((ShaderType & ShaderFlags) != 0)
@@ -703,24 +783,24 @@ IShaderResourceVariable* PipelineStateVkImpl::GetStaticVariableByIndex(SHADER_TY
if (LayoutInd < 0)
return nullptr;
- auto& StaticVarMgr = GetStaticVarMgr(LayoutInd);
+ const auto& StaticVarMgr = GetStaticVarMgr(LayoutInd);
return StaticVarMgr.GetVariable(Index);
}
void PipelineStateVkImpl::InitializeStaticSRBResources(ShaderResourceCacheVk& ResourceCache) const
{
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
{
const auto& StaticResLayout = GetStaticShaderResLayout(s);
const auto& StaticResCache = GetStaticResCache(s);
+
#ifdef DILIGENT_DEVELOPMENT
if (!StaticResLayout.dvpVerifyBindings(StaticResCache))
{
- const auto* pShaderVk = GetShader<const ShaderVkImpl>(s);
LOG_ERROR_MESSAGE("Static resources in SRB of PSO '", GetDesc().Name,
"' will not be successfully initialized because not all static resource bindings in shader '",
- pShaderVk->GetDesc().Name,
+ GetShaderTypeLiteralName(GetShaderStageType(s)),
"' are valid. Please make sure you bind all static resources to PSO before calling InitializeStaticResources() "
"directly or indirectly by passing InitStaticResources=true to CreateShaderResourceBinding() method.");
}
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
index 6e5ec710..cdcac036 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceVkImpl.cpp
@@ -106,6 +106,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
//{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumUniformBufferDescriptors},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.MainDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
},
EngineCI.MainDescriptorPoolSize.MaxDescriptorSets,
true
@@ -126,6 +127,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
//{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumUniformBufferDescriptors},
{VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, EngineCI.DynamicDescriptorPoolSize.NumStorageBufferDescriptors},
+ {VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, EngineCI.MainDescriptorPoolSize.NumInputAttachmentDescriptors},
},
EngineCI.DynamicDescriptorPoolSize.MaxDescriptorSets,
false // Pools can only be reset
@@ -217,6 +219,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
// The following features are always enabled
Features.SeparablePrograms = DEVICE_FEATURE_STATE_ENABLED;
+ Features.ShaderResourceQueries = DEVICE_FEATURE_STATE_ENABLED;
Features.IndirectRendering = DEVICE_FEATURE_STATE_ENABLED;
Features.MultithreadedResourceCreation = DEVICE_FEATURE_STATE_ENABLED;
Features.ComputeShaders = DEVICE_FEATURE_STATE_ENABLED;
@@ -226,7 +229,7 @@ RenderDeviceVkImpl::RenderDeviceVkImpl(IReferenceCounters*
Features.DurationQueries = DEVICE_FEATURE_STATE_ENABLED;
#if defined(_MSC_VER) && defined(_WIN64)
- static_assert(sizeof(DeviceFeatures) == 31, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
+ static_assert(sizeof(DeviceFeatures) == 32, "Did you add a new feature to DeviceFeatures? Please handle its satus here (if necessary).");
#endif
const auto& vkDeviceLimits = m_PhysicalDevice->GetProperties().limits;
@@ -545,7 +548,8 @@ void RenderDeviceVkImpl::TestTextureFormat(TEXTURE_FORMAT TexFormat)
IMPLEMENT_QUERY_INTERFACE(RenderDeviceVkImpl, IID_RenderDeviceVk, TRenderDeviceBase)
-void RenderDeviceVkImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+template <typename PSOCreateInfoType>
+void RenderDeviceVkImpl::CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState)
{
CreateDeviceObject(
"Pipeline State", PSOCreateInfo.PSODesc, ppPipelineState,
@@ -558,6 +562,17 @@ void RenderDeviceVkImpl::CreatePipelineState(const PipelineStateCreateInfo& PSOC
);
}
+void RenderDeviceVkImpl::CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
+
+void RenderDeviceVkImpl::CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo, IPipelineState** ppPipelineState)
+{
+ CreatePipelineState(PSOCreateInfo, ppPipelineState);
+}
+
void RenderDeviceVkImpl::CreateBufferFromVulkanResource(VkBuffer vkBuffer, const BufferDesc& BuffDesc, RESOURCE_STATE InitialState, IBuffer** ppBuffer)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
index 6e6c142f..3e4a65cf 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceBindingVkImpl.cpp
@@ -30,6 +30,7 @@
#include "PipelineStateVkImpl.hpp"
#include "ShaderVkImpl.hpp"
#include "RenderDeviceVkImpl.hpp"
+#include "LinearAllocator.hpp"
namespace Diligent
{
@@ -47,55 +48,79 @@ ShaderResourceBindingVkImpl::ShaderResourceBindingVkImpl(IReferenceCounters* pR
m_ShaderResourceCache{ShaderResourceCacheVk::DbgCacheContentType::SRBResources}
// clang-format on
{
- m_ResourceLayoutIndex.fill(-1);
+ try
+ {
+ m_ResourceLayoutIndex.fill(-1);
- auto* ppShaders = pPSO->GetShaders();
- m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaders());
+ m_NumShaders = static_cast<decltype(m_NumShaders)>(pPSO->GetNumShaderStages());
- auto* pRenderDeviceVkImpl = pPSO->GetDevice();
- // This will only allocate memory and initialize descriptor sets in the resource cache
- // Resources will be initialized by InitializeResourceMemoryInCache()
- auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0);
- pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name);
+ LinearAllocator MemPool{GetRawAllocator()};
+ MemPool.AddSpace<ShaderVariableManagerVk>(m_NumShaders);
+ MemPool.Reserve();
+ m_pShaderVarMgrs = MemPool.ConstructArray<ShaderVariableManagerVk>(m_NumShaders, std::ref(*this), std::ref(m_ShaderResourceCache));
- m_pShaderVarMgrs = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderVariableManagerVk", ShaderVariableManagerVk, m_NumShaders);
+ // The memory is now owned by ShaderResourceBindingVkImpl and will be freed by Destruct().
+ auto* Ptr = MemPool.ReleaseOwnership();
+ VERIFY_EXPR(Ptr == m_pShaderVarMgrs);
+ (void)Ptr;
- for (Uint32 s = 0; s < m_NumShaders; ++s)
- {
- auto* pShader = ppShaders[s];
- auto ShaderType = pShader->GetDesc().ShaderType;
- auto ShaderInd = GetShaderTypePipelineIndex(ShaderType, pPSO->GetDesc().PipelineType);
+ // It is important to construct all objects before initializing them because if an exception is thrown,
+ // destructors will be called for all objects
- m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
+ auto* pRenderDeviceVkImpl = pPSO->GetDevice();
+ // This will only allocate memory and initialize descriptor sets in the resource cache
+ // Resources will be initialized by InitializeResourceMemoryInCache()
+ auto& ResourceCacheDataAllocator = pPSO->GetSRBMemoryAllocator().GetResourceCacheDataAllocator(0);
+ pPSO->GetPipelineLayout().InitResourceCache(pRenderDeviceVkImpl, m_ShaderResourceCache, ResourceCacheDataAllocator, pPSO->GetDesc().Name);
- auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto ShaderInd = GetShaderTypePipelineIndex(pPSO->GetShaderStageType(s), pPSO->GetDesc().PipelineType);
- const auto& SrcLayout = pPSO->GetShaderResLayout(s);
- // Use source layout to initialize resource memory in the cache
- SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache);
+ m_ResourceLayoutIndex[ShaderInd] = static_cast<Int8>(s);
- // Create shader variable manager in place
- // Initialize vars manager to reference mutable and dynamic variables
- // Note that the cache has space for all variable types
- const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
- new (m_pShaderVarMgrs + s) ShaderVariableManagerVk{*this, SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes), m_ShaderResourceCache};
- }
+ auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
+
+ const auto& SrcLayout = pPSO->GetShaderResLayout(s);
+ // Use source layout to initialize resource memory in the cache
+ SrcLayout.InitializeResourceMemoryInCache(m_ShaderResourceCache);
+
+ // Create shader variable manager in place
+ // Initialize vars manager to reference mutable and dynamic variables
+ // Note that the cache has space for all variable types
+ const SHADER_RESOURCE_VARIABLE_TYPE VarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE, SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC};
+ m_pShaderVarMgrs[s].Initialize(SrcLayout, VarDataAllocator, VarTypes, _countof(VarTypes));
+ }
#ifdef DILIGENT_DEBUG
- m_ShaderResourceCache.DbgVerifyResourceInitialization();
+ m_ShaderResourceCache.DbgVerifyResourceInitialization();
#endif
+ }
+ catch (...)
+ {
+ Destruct();
+ throw;
+ }
}
ShaderResourceBindingVkImpl::~ShaderResourceBindingVkImpl()
{
- PipelineStateVkImpl* pPSO = ValidatedCast<PipelineStateVkImpl>(m_pPSO);
- for (Uint32 s = 0; s < m_NumShaders; ++s)
+ Destruct();
+}
+
+void ShaderResourceBindingVkImpl::Destruct()
+{
+ if (m_pShaderVarMgrs != nullptr)
{
- auto& VarDataAllocator = pPSO->GetSRBMemoryAllocator().GetShaderVariableDataAllocator(s);
- m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator);
- m_pShaderVarMgrs[s].~ShaderVariableManagerVk();
- }
+ auto& SRBMemAllocator = m_pPSO->GetSRBMemoryAllocator();
+ for (Uint32 s = 0; s < m_NumShaders; ++s)
+ {
+ auto& VarDataAllocator = SRBMemAllocator.GetShaderVariableDataAllocator(s);
+ m_pShaderVarMgrs[s].DestroyVariables(VarDataAllocator);
+ m_pShaderVarMgrs[s].~ShaderVariableManagerVk();
+ }
- GetRawAllocator().Free(m_pShaderVarMgrs);
+ GetRawAllocator().Free(m_pShaderVarMgrs);
+ }
}
IMPLEMENT_QUERY_INTERFACE(ShaderResourceBindingVkImpl, IID_ShaderResourceBindingVk, TBase)
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
index 4f28af80..e73ee9aa 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderResourceLayoutVk.cpp
@@ -63,10 +63,10 @@ static Int32 FindImmutableSampler(SHADER_TYPE ShaderType,
return -1;
}
- for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s)
{
- const auto& StSam = ResourceLayoutDesc.StaticSamplers[s];
- if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, StSam.SamplerOrTextureName, SamplerSuffix))
+ const auto& ImtblSam = ResourceLayoutDesc.ImmutableSamplers[s];
+ if (((ImtblSam.ShaderStages & ShaderType) != 0) && StreqSuff(Attribs.Name, ImtblSam.SamplerOrTextureName, SamplerSuffix))
return s;
}
@@ -93,6 +93,14 @@ static SHADER_RESOURCE_VARIABLE_TYPE FindShaderVariableType(SHADER_TYPE
}
}
+ShaderResourceLayoutVk::ShaderStageInfo::ShaderStageInfo(SHADER_TYPE _Type,
+ const ShaderVkImpl* _pShader) :
+ Type{_Type},
+ pShader{_pShader},
+ SPIRV{pShader->GetSPIRV()}
+{
+}
+
ShaderResourceLayoutVk::~ShaderResourceLayoutVk()
{
@@ -103,36 +111,37 @@ ShaderResourceLayoutVk::~ShaderResourceLayoutVk()
GetImmutableSampler(s).~ImmutableSamplerPtrType();
}
-void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& Allocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- bool AllocateImmutableSamplers)
+void ShaderResourceLayoutVk::AllocateMemory(const ShaderVkImpl* pShader,
+ IMemoryAllocator& Allocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes,
+ bool AllocateImmutableSamplers)
{
VERIFY(!m_ResourceBuffer, "Memory has already been initialized");
VERIFY_EXPR(!m_pResources);
- VERIFY_EXPR(pSrcResources);
+ m_pResources = pShader->GetShaderResources();
- m_pResources = std::move(pSrcResources);
-
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
- const auto ShaderType = m_pResources->GetShaderType();
- const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
+ const auto ShaderType = pShader->GetDesc().ShaderType;
+ VERIFY_EXPR(m_pResources->GetShaderType() == ShaderType);
// Count the number of resources to allocate all needed memory
- m_pResources->ProcessResources(
- [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) //
- {
- auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix);
- if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
+ m_pResources->ProcessResources(
+ [&](const SPIRVShaderResourceAttribs& ResAttribs, Uint32) //
{
- // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app
+ auto VarType = FindShaderVariableType(ShaderType, ResAttribs, ResourceLayoutDesc, CombinedSamplerSuffix);
+ if (IsAllowedType(VarType, AllowedTypeBits))
+ {
+ // For immutable separate samplers we still allocate VkResource instances, but they are never exposed to the app
- VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
- ++m_NumResources[VarType];
- }
- } //
- );
+ VERIFY(Uint32{m_NumResources[VarType]} + 1 <= Uint32{std::numeric_limits<Uint16>::max()}, "Number of resources exceeds Uint16 maximum representable value");
+ ++m_NumResources[VarType];
+ }
+ } //
+ );
+ }
Uint32 TotalResources = 0;
for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
@@ -145,10 +154,10 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
m_NumImmutableSamplers = 0;
if (AllocateImmutableSamplers)
{
- for (Uint32 s = 0; s < ResourceLayoutDesc.NumStaticSamplers; ++s)
+ for (Uint32 s = 0; s < ResourceLayoutDesc.NumImmutableSamplers; ++s)
{
- const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[s];
- if ((StSamDesc.ShaderStages & ShaderType) != 0)
+ const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[s];
+ if ((ImtblSamDesc.ShaderStages & ShaderType) != 0)
++m_NumImmutableSamplers;
}
}
@@ -169,24 +178,63 @@ void ShaderResourceLayoutVk::AllocateMemory(std::shared_ptr<const SPIRVShaderRes
}
-void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<const SPIRVShaderResources> pSrcResources,
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- ShaderResourceCacheVk& StaticResourceCache)
+static Uint32 FindAssignedSampler(const ShaderResourceLayoutVk& Layout,
+ const SPIRVShaderResources& Resources,
+ const SPIRVShaderResourceAttribs& SepImg,
+ Uint32 CurrResourceCount,
+ SHADER_RESOURCE_VARIABLE_TYPE ImgVarType)
+{
+ using VkResource = ShaderResourceLayoutVk::VkResource;
+ VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
+
+ Uint32 SamplerInd = VkResource::InvalidSamplerInd;
+ if (Resources.IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned())
+ {
+ const auto& SepSampler = Resources.GetAssignedSepSampler(SepImg);
+ for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd)
+ {
+ const auto& Res = Layout.GetResource(ImgVarType, SamplerInd);
+ if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
+ strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0)
+ {
+ VERIFY(ImgVarType == Res.GetVariableType(),
+ "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name,
+ "' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()),
+ ") of the separate sampler '", SepSampler.Name,
+ "' that is assigned to it. "
+ "This should never happen as when HLSL-style combined texture samplers are used, the type of the sampler "
+ "is derived from the type of the corresponding separate image.");
+ break;
+ }
+ }
+ if (SamplerInd == CurrResourceCount)
+ {
+ LOG_ERROR("Unable to find separate sampler '", SepSampler.Name, "' assigned to separate image '", SepImg.Name, "' in the list of already created resources. This seems to be a bug.");
+ SamplerInd = VkResource::InvalidSamplerInd;
+ }
+ }
+ return SamplerInd;
+}
+
+
+void ShaderResourceLayoutVk::InitializeStaticResourceLayout(const ShaderVkImpl* pShader,
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ ShaderResourceCacheVk& StaticResourceCache)
{
const auto AllowedVarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC;
// We do not need immutable samplers in static shader resource layout as they
// are relevant only when the main layout is initialized
constexpr bool AllocateImmutableSamplers = false;
- AllocateMemory(std::move(pSrcResources), LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers);
+ AllocateMemory(pShader, LayoutDataAllocator, ResourceLayoutDesc, &AllowedVarType, 1, AllocateImmutableSamplers);
std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES> CurrResInd = {};
Uint32 StaticResCacheSize = 0;
const Uint32 AllowedTypeBits = GetAllowedTypeBits(&AllowedVarType, 1);
- const auto ShaderType = m_pResources->GetShaderType();
const auto* CombinedSamplerSuffix = m_pResources->GetCombinedSamplerSuffix();
+ const auto ShaderType = pShader->GetDesc().ShaderType;
m_pResources->ProcessResources(
[&](const SPIRVShaderResourceAttribs& Attribs, Uint32) //
@@ -214,7 +262,7 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
{
// Separate samplers are enumerated before separate images, so the sampler
// assigned to this separate image must have already been created.
- SamplerInd = FindAssignedSampler(Attribs, CurrResInd[VarType], VarType);
+ SamplerInd = FindAssignedSampler(*this, *m_pResources, Attribs, CurrResInd[VarType], VarType);
}
::new (&GetResource(VarType, CurrResInd[VarType]++)) VkResource(*this, Attribs, VarType, Binding, DescriptorSet, CacheOffset, SamplerInd, SrcImmutableSamplerInd >= 0);
} //
@@ -235,25 +283,24 @@ void ShaderResourceLayoutVk::InitializeStaticResourceLayout(std::shared_ptr<cons
}
#ifdef DILIGENT_DEVELOPMENT
-void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32 NumShaders,
- const std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- bool VerifyVariables,
- bool VerifyStaticSamplers)
+void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(const TShaderStages& ShaderStages,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers)
{
- auto GetAllowedShadersString = [&](SHADER_TYPE ShaderStages) //
+ auto GetAllowedShadersString = [&](SHADER_TYPE Stages) //
{
std::string ShadersStr;
- while (ShaderStages != SHADER_TYPE_UNKNOWN)
+ while (Stages != SHADER_TYPE_UNKNOWN)
{
- const auto ShaderType = ShaderStages & static_cast<SHADER_TYPE>(~(static_cast<Uint32>(ShaderStages) - 1));
+ const auto ShaderType = Stages & static_cast<SHADER_TYPE>(~(static_cast<Uint32>(Stages) - 1));
const char* ShaderName = nullptr;
- for (Uint32 s = 0; s < NumShaders; ++s)
+
+ for (const auto& StageInfo : ShaderStages)
{
- const auto& Resources = *pShaderResources[s];
- if ((ShaderStages & Resources.GetShaderType()) != 0)
+ if ((Stages & StageInfo.Type) != 0)
{
- ShaderName = Resources.GetShaderName();
+ ShaderName = StageInfo.pShader->GetDesc().Name;
break;
}
}
@@ -274,7 +321,7 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
ShadersStr.append(")");
- ShaderStages &= ~ShaderType;
+ Stages &= ~ShaderType;
}
return ShadersStr;
};
@@ -291,9 +338,9 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
bool VariableFound = false;
- for (Uint32 s = 0; s < NumShaders && !VariableFound; ++s)
+ for (size_t s = 0; s < ShaderStages.size() && !VariableFound; ++s)
{
- const auto& Resources = *pShaderResources[s];
+ const auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
if ((VarDesc.ShaderStages & Resources.GetShaderType()) != 0)
{
for (Uint32 res = 0; res < Resources.GetTotalResources() && !VariableFound; ++res)
@@ -312,83 +359,82 @@ void ShaderResourceLayoutVk::dvpVerifyResourceLayoutDesc(Uint32
}
}
- if (VerifyStaticSamplers)
+ if (VerifyImmutableSamplers)
{
- for (Uint32 sam = 0; sam < ResourceLayoutDesc.NumStaticSamplers; ++sam)
+ for (Uint32 sam = 0; sam < ResourceLayoutDesc.NumImmutableSamplers; ++sam)
{
- const auto& StSamDesc = ResourceLayoutDesc.StaticSamplers[sam];
- if (StSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN)
+ const auto& ImtblSamDesc = ResourceLayoutDesc.ImmutableSamplers[sam];
+ if (ImtblSamDesc.ShaderStages == SHADER_TYPE_UNKNOWN)
{
- LOG_WARNING_MESSAGE("No allowed shader stages are specified for static sampler '", StSamDesc.SamplerOrTextureName, "'.");
+ LOG_WARNING_MESSAGE("No allowed shader stages are specified for immutable sampler '", ImtblSamDesc.SamplerOrTextureName, "'.");
continue;
}
bool SamplerFound = false;
- for (Uint32 s = 0; s < NumShaders && !SamplerFound; ++s)
+ for (size_t s = 0; s < ShaderStages.size() && !SamplerFound; ++s)
{
- const auto& Resources = *pShaderResources[s];
- if ((StSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
+ const auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
+ if ((ImtblSamDesc.ShaderStages & Resources.GetShaderType()) == 0)
continue;
// Irrespective of whether HLSL-style combined image samplers are used,
- // a static sampler can be assigned to GLSL sampled image (i.e. sampler2D g_tex)
+ // an immutable sampler can be assigned to a GLSL sampled image (i.e. sampler2D g_tex)
for (Uint32 i = 0; i < Resources.GetNumSmpldImgs() && !SamplerFound; ++i)
{
const auto& SmplImg = Resources.GetSmpldImg(i);
- SamplerFound = (strcmp(SmplImg.Name, StSamDesc.SamplerOrTextureName) == 0);
+ SamplerFound = (strcmp(SmplImg.Name, ImtblSamDesc.SamplerOrTextureName) == 0);
}
if (!SamplerFound)
{
- // Check if static sampler is assigned to a separate sampler.
+ // Check if an immutable sampler is assigned to a separate sampler.
// In case HLSL-style combined image samplers are used, the condition is SepSmpl.Name == "g_Texture" + "_sampler".
// Otherwise the condition is SepSmpl.Name == "g_Texture_sampler" + "".
const auto* CombinedSamplerSuffix = Resources.GetCombinedSamplerSuffix();
for (Uint32 i = 0; i < Resources.GetNumSepSmplrs() && !SamplerFound; ++i)
{
const auto& SepSmpl = Resources.GetSepSmplr(i);
- SamplerFound = StreqSuff(SepSmpl.Name, StSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
+ SamplerFound = StreqSuff(SepSmpl.Name, ImtblSamDesc.SamplerOrTextureName, CombinedSamplerSuffix);
}
}
}
if (!SamplerFound)
{
- LOG_WARNING_MESSAGE("Static sampler '", StSamDesc.SamplerOrTextureName,
+ LOG_WARNING_MESSAGE("Immutable sampler '", ImtblSamDesc.SamplerOrTextureName,
"' is not found in any of the designated shader stages: ",
- GetAllowedShadersString(StSamDesc.ShaderStages));
+ GetAllowedShadersString(ImtblSamDesc.ShaderStages));
}
}
}
}
#endif
-void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
- Uint32 NumShaders,
- ShaderResourceLayoutVk Layouts[],
- std::shared_ptr<const SPIRVShaderResources> pShaderResources[],
- IMemoryAllocator& LayoutDataAllocator,
- const PipelineResourceLayoutDesc& ResourceLayoutDesc,
- std::vector<uint32_t> SPIRVs[],
- class PipelineLayout& PipelineLayout,
- bool VerifyVariables,
- bool VerifyStaticSamplers)
+void ShaderResourceLayoutVk::Initialize(IRenderDevice* pRenderDevice,
+ TShaderStages& ShaderStages,
+ ShaderResourceLayoutVk Layouts[],
+ IMemoryAllocator& LayoutDataAllocator,
+ const PipelineResourceLayoutDesc& ResourceLayoutDesc,
+ class PipelineLayout& PipelineLayout,
+ bool VerifyVariables,
+ bool VerifyImmutableSamplers)
{
#ifdef DILIGENT_DEVELOPMENT
- dvpVerifyResourceLayoutDesc(NumShaders, pShaderResources, ResourceLayoutDesc, VerifyVariables, VerifyStaticSamplers);
+ dvpVerifyResourceLayoutDesc(ShaderStages, ResourceLayoutDesc, VerifyVariables, VerifyImmutableSamplers);
#endif
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr;
- const Uint32 NumAllowedTypes = 0;
- const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes = nullptr;
+ const Uint32 NumAllowedTypes = 0;
+ const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
+ constexpr bool AllocateImmutableSamplers = true;
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- constexpr bool AllocateImmutableSamplers = true;
- Layouts[s].AllocateMemory(std::move(pShaderResources[s]), LayoutDataAllocator, ResourceLayoutDesc, AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers);
+ Layouts[s].AllocateMemory(ShaderStages[s].pShader, LayoutDataAllocator, ResourceLayoutDesc,
+ AllowedVarTypes, NumAllowedTypes, AllocateImmutableSamplers);
}
- VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE);
+ //VERIFY_EXPR(NumShaders <= MAX_SHADERS_IN_PIPELINE);
std::array<std::array<Uint32, SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES>, MAX_SHADERS_IN_PIPELINE> CurrResInd = {};
std::array<Uint32, MAX_SHADERS_IN_PIPELINE> CurrImmutableSamplerInd = {};
#ifdef DILIGENT_DEBUG
@@ -414,7 +460,7 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
{
// Separate samplers are enumerated before separate images, so the sampler
// assigned to this separate image must have already been created.
- SamplerInd = ResLayout.FindAssignedSampler(Attribs, CurrResInd[ShaderInd][VarType], VarType);
+ SamplerInd = FindAssignedSampler(ResLayout, Resources, Attribs, CurrResInd[ShaderInd][VarType], VarType);
}
VkSampler vkImmutableSampler = VK_NULL_HANDLE;
@@ -427,13 +473,13 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
{
auto& ImmutableSampler = ResLayout.GetImmutableSampler(CurrImmutableSamplerInd[ShaderInd]++);
VERIFY(!ImmutableSampler, "Immutable sampler has already been initialized!");
- const auto& ImmutableSamplerDesc = ResourceLayoutDesc.StaticSamplers[SrcImmutableSamplerInd].Desc;
+ const auto& ImmutableSamplerDesc = ResourceLayoutDesc.ImmutableSamplers[SrcImmutableSamplerInd].Desc;
pRenderDevice->CreateSampler(ImmutableSamplerDesc, &ImmutableSampler);
vkImmutableSampler = ImmutableSampler.RawPtr<SamplerVkImpl>()->GetVkSampler();
}
}
- auto& ShaderSPIRV = SPIRVs[ShaderInd];
+ auto& ShaderSPIRV = ShaderStages[ShaderInd].SPIRV;
PipelineLayout.AllocateResourceSlot(Attribs, VarType, vkImmutableSampler, Resources.GetShaderType(), DescriptorSet, Binding, CacheOffset, ShaderSPIRV);
VERIFY(DescriptorSet <= std::numeric_limits<decltype(VkResource::DescriptorSet)>::max(), "Descriptor set (", DescriptorSet, ") excceeds maximum representable value");
VERIFY(Binding <= std::numeric_limits<decltype(VkResource::Binding)>::max(), "Binding (", Binding, ") excceeds maximum representable value");
@@ -454,42 +500,43 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
};
// First process uniform buffers for all shader stages to make sure all UBs go first in every descriptor set
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- auto& Layout = Layouts[s];
- const auto& Resources = *Layout.m_pResources;
+ auto& Layout = Layouts[s];
+ auto* pShaderVk = ShaderStages[s].pShader;
+ auto& Resources = *pShaderVk->GetShaderResources();
for (Uint32 n = 0; n < Resources.GetNumUBs(); ++n)
{
const auto& UB = Resources.GetUB(n);
auto VarType = GetShaderVariableType(Resources.GetShaderType(), UB.Name, ResourceLayoutDesc);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- AddResource(s, Layout, Resources, UB);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, UB);
}
}
}
// Second, process all storage buffers
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- auto& Layout = Layouts[s];
- const auto& Resources = *Layout.m_pResources;
+ auto& Layout = Layouts[s];
+ auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
for (Uint32 n = 0; n < Resources.GetNumSBs(); ++n)
{
const auto& SB = Resources.GetSB(n);
auto VarType = GetShaderVariableType(Resources.GetShaderType(), SB.Name, ResourceLayoutDesc);
if (IsAllowedType(VarType, AllowedTypeBits))
{
- AddResource(s, Layout, Resources, SB);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SB);
}
}
}
// Finally, process all other resource types
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
- auto& Layout = Layouts[s];
- const auto& Resources = *Layout.m_pResources;
+ auto& Layout = Layouts[s];
+ auto& Resources = *ShaderStages[s].pShader->GetShaderResources();
// clang-format off
Resources.ProcessResources(
[&](const SPIRVShaderResourceAttribs& UB, Uint32)
@@ -505,39 +552,39 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
[&](const SPIRVShaderResourceAttribs& Img, Uint32)
{
VERIFY_EXPR(Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageImage || Img.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer);
- AddResource(s, Layout, Resources, Img);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, Img);
},
[&](const SPIRVShaderResourceAttribs& SmplImg, Uint32)
{
VERIFY_EXPR(SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::SampledImage || SmplImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
- AddResource(s, Layout, Resources, SmplImg);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SmplImg);
},
[&](const SPIRVShaderResourceAttribs& AC, Uint32)
{
VERIFY_EXPR(AC.Type == SPIRVShaderResourceAttribs::ResourceType::AtomicCounter);
- AddResource(s, Layout, Resources, AC);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, AC);
},
[&](const SPIRVShaderResourceAttribs& SepSmpl, Uint32)
{
VERIFY_EXPR(SepSmpl.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler);
- AddResource(s, Layout, Resources, SepSmpl);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SepSmpl);
},
[&](const SPIRVShaderResourceAttribs& SepImg, Uint32)
{
VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage || SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::UniformTexelBuffer);
- AddResource(s, Layout, Resources, SepImg);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, SepImg);
},
[&](const SPIRVShaderResourceAttribs& InputAtt, Uint32)
{
VERIFY_EXPR(InputAtt.Type == SPIRVShaderResourceAttribs::ResourceType::InputAttachment);
- AddResource(s, Layout, Resources, InputAtt);
+ AddResource(static_cast<Uint32>(s), Layout, Resources, InputAtt);
}
);
// clang-format on
}
#ifdef DILIGENT_DEBUG
- for (Uint32 s = 0; s < NumShaders; ++s)
+ for (size_t s = 0; s < ShaderStages.size(); ++s)
{
auto& Layout = Layouts[s];
for (SHADER_RESOURCE_VARIABLE_TYPE VarType = SHADER_RESOURCE_VARIABLE_TYPE_STATIC; VarType < SHADER_RESOURCE_VARIABLE_TYPE_NUM_TYPES; VarType = static_cast<SHADER_RESOURCE_VARIABLE_TYPE>(VarType + 1))
@@ -550,43 +597,6 @@ void ShaderResourceLayoutVk::Initialize(IRenderDevice*
#endif
}
-
-Uint32 ShaderResourceLayoutVk::FindAssignedSampler(const SPIRVShaderResourceAttribs& SepImg,
- Uint32 CurrResourceCount,
- SHADER_RESOURCE_VARIABLE_TYPE ImgVarType) const
-{
- VERIFY_EXPR(SepImg.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateImage);
-
- Uint32 SamplerInd = VkResource::InvalidSamplerInd;
- if (m_pResources->IsUsingCombinedSamplers() && SepImg.IsValidSepSamplerAssigned())
- {
- const auto& SepSampler = m_pResources->GetAssignedSepSampler(SepImg);
- for (SamplerInd = 0; SamplerInd < CurrResourceCount; ++SamplerInd)
- {
- const auto& Res = GetResource(ImgVarType, SamplerInd);
- if (Res.SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::SeparateSampler &&
- strcmp(Res.SpirvAttribs.Name, SepSampler.Name) == 0)
- {
- VERIFY(ImgVarType == Res.GetVariableType(),
- "The type (", GetShaderVariableTypeLiteralName(ImgVarType), ") of separate image variable '", SepImg.Name,
- "' is not consistent with the type (", GetShaderVariableTypeLiteralName(Res.GetVariableType()),
- ") of the separate sampler '", SepSampler.Name,
- "' that is assigned to it. "
- "This should never happen as when HLSL-style combined texture samplers are used, the type of the sampler "
- "is derived from the type of the corresponding separate image.");
- break;
- }
- }
- if (SamplerInd == CurrResourceCount)
- {
- LOG_ERROR("Unable to find separate sampler '", SepSampler.Name, "' assigned to separate image '", SepImg.Name, "' in the list of already created resources. This seems to be a bug.");
- SamplerInd = VkResource::InvalidSamplerInd;
- }
- }
- return SamplerInd;
-}
-
-
void ShaderResourceLayoutVk::VkResource::UpdateDescriptorHandle(VkDescriptorSet vkDescrSet,
uint32_t ArrayElement,
const VkDescriptorImageInfo* pImageInfo,
@@ -692,6 +702,16 @@ void ShaderResourceLayoutVk::VkResource::CacheStorageBuffer(IDeviceObject*
// HLSL buffer SRVs are mapped to storge buffers in GLSL
auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::ROStorageBuffer ? BUFFER_VIEW_SHADER_RESOURCE : BUFFER_VIEW_UNORDERED_ACCESS;
VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ if (pBufferViewVk != nullptr)
+ {
+ const auto& ViewDesc = pBufferViewVk->GetDesc();
+ const auto& BuffDesc = pBufferViewVk->GetBuffer()->GetDesc();
+ if (BuffDesc.Mode != BUFFER_MODE_STRUCTURED && BuffDesc.Mode != BUFFER_MODE_RAW)
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': structured buffer view is expected.");
+ }
+ }
}
#endif
@@ -738,6 +758,16 @@ void ShaderResourceLayoutVk::VkResource::CacheTexelBuffer(IDeviceObject*
// HLSL buffer SRVs are mapped to storge buffers in GLSL
auto RequiredViewType = SpirvAttribs.Type == SPIRVShaderResourceAttribs::ResourceType::StorageTexelBuffer ? BUFFER_VIEW_UNORDERED_ACCESS : BUFFER_VIEW_SHADER_RESOURCE;
VerifyResourceViewBinding(SpirvAttribs, GetVariableType(), ArrayInd, pBufferView, pBufferViewVk.RawPtr(), {RequiredViewType}, DstRes.pObject.RawPtr(), ParentResLayout.GetShaderName());
+ if (pBufferViewVk != nullptr)
+ {
+ const auto& ViewDesc = pBufferViewVk->GetDesc();
+ const auto& BuffDesc = pBufferViewVk->GetBuffer()->GetDesc();
+ if (!((BuffDesc.Mode == BUFFER_MODE_FORMATTED && ViewDesc.Format.ValueType != VT_UNDEFINED) || BuffDesc.Mode == BUFFER_MODE_RAW))
+ {
+ LOG_ERROR_MESSAGE("Error binding buffer view '", ViewDesc.Name, "' of buffer '", BuffDesc.Name, "' to shader variable '",
+ SpirvAttribs.Name, "' in shader '", ParentResLayout.GetShaderName(), "': formatted buffer view is expected.");
+ }
+ }
}
#endif
@@ -1017,7 +1047,7 @@ void ShaderResourceLayoutVk::InitializeStaticResources(const ShaderResourceLayou
{
auto NumStaticResources = m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC];
VERIFY(NumStaticResources == SrcLayout.m_NumResources[SHADER_RESOURCE_VARIABLE_TYPE_STATIC], "Inconsistent number of static resources");
- VERIFY(SrcLayout.m_pResources->GetShaderType() == m_pResources->GetShaderType(), "Incosistent shader types");
+ VERIFY(SrcLayout.GetShaderType() == GetShaderType(), "Incosistent shader types");
// Static shader resources are stored in one large continuous descriptor set
for (Uint32 r = 0; r < NumStaticResources; ++r)
diff --git a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
index 82d26b44..7e06bd69 100644
--- a/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/ShaderVariableVk.cpp
@@ -65,20 +65,15 @@ size_t ShaderVariableManagerVk::GetRequiredMemorySize(const ShaderResourceLayout
}
// Creates shader variable for every resource from SrcLayout whose type is one AllowedVarTypes
-ShaderVariableManagerVk::ShaderVariableManagerVk(IObject& Owner,
- const ShaderResourceLayoutVk& SrcLayout,
- IMemoryAllocator& Allocator,
- const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
- Uint32 NumAllowedTypes,
- ShaderResourceCacheVk& ResourceCache) :
- // clang-format off
- m_Owner {Owner },
- m_ResourceCache{ResourceCache}
+void ShaderVariableManagerVk::Initialize(const ShaderResourceLayoutVk& SrcLayout,
+ IMemoryAllocator& Allocator,
+ const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
+ Uint32 NumAllowedTypes)
+{
#ifdef DILIGENT_DEBUG
- , m_DbgAllocator {Allocator}
+ m_pDbgAllocator = &Allocator;
#endif
-// clang-format on
-{
+
const Uint32 AllowedTypeBits = GetAllowedTypeBits(AllowedVarTypes, NumAllowedTypes);
VERIFY_EXPR(m_NumVariables == 0);
auto MemSize = GetRequiredMemorySize(SrcLayout, AllowedVarTypes, NumAllowedTypes, m_NumVariables);
@@ -119,10 +114,10 @@ ShaderVariableManagerVk::~ShaderVariableManagerVk()
void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator)
{
- VERIFY(&m_DbgAllocator == &Allocator, "Incosistent alloctor");
-
if (m_pVariables != nullptr)
{
+ VERIFY(m_pDbgAllocator == &Allocator, "Incosistent alloctor");
+
for (Uint32 v = 0; v < m_NumVariables; ++v)
m_pVariables[v].~ShaderVariableVkImpl();
Allocator.Free(m_pVariables);
@@ -130,7 +125,7 @@ void ShaderVariableManagerVk::DestroyVariables(IMemoryAllocator& Allocator)
}
}
-ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name)
+ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name) const
{
ShaderVariableVkImpl* pVar = nullptr;
for (Uint32 v = 0; v < m_NumVariables; ++v)
@@ -147,7 +142,7 @@ ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(const Char* Name)
}
-ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index)
+ShaderVariableVkImpl* ShaderVariableManagerVk::GetVariable(Uint32 Index) const
{
if (Index >= m_NumVariables)
{
@@ -178,7 +173,7 @@ Uint32 ShaderVariableManagerVk::GetVariableIndex(const ShaderVariableVkImpl& Var
}
}
-void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags)
+void ShaderVariableManagerVk::BindResources(IResourceMapping* pResourceMapping, Uint32 Flags) const
{
if (!pResourceMapping)
{
diff --git a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
index 313de089..488e4bf6 100644
--- a/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/TextureVkImpl.cpp
@@ -54,13 +54,13 @@ TextureVkImpl::TextureVkImpl(IReferenceCounters* pRefCounters,
}
// clang-format on
{
- if (m_Desc.Usage == USAGE_STATIC && (pInitData == nullptr || pInitData->pSubResources == nullptr))
- LOG_ERROR_AND_THROW("Static textures must be initialized with data at creation time: pInitData can't be null");
+ if (m_Desc.Usage == USAGE_IMMUTABLE && (pInitData == nullptr || pInitData->pSubResources == nullptr))
+ LOG_ERROR_AND_THROW("Immutable textures must be initialized with data at creation time: pInitData can't be null");
const auto& FmtAttribs = GetTextureFormatAttribs(m_Desc.Format);
const auto& LogicalDevice = pRenderDeviceVk->GetLogicalDevice();
- if (m_Desc.Usage == USAGE_STATIC || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC)
+ if (m_Desc.Usage == USAGE_IMMUTABLE || m_Desc.Usage == USAGE_DEFAULT || m_Desc.Usage == USAGE_DYNAMIC)
{
VkImageCreateInfo ImageCI = {};
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
index fa03bca6..6358174c 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanTypeConversions.cpp
@@ -1528,6 +1528,35 @@ VkAccessFlags AccessFlagsToVkAccessFlags(ACCESS_FLAGS AccessFlags)
}
#undef ASSERT_SAME
+
+VkShaderStageFlagBits ShaderTypeToVkShaderStageFlagBit(SHADER_TYPE ShaderType)
+{
+ static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
+ VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "More than one shader type is specified");
+ switch (ShaderType)
+ {
+ // clang-format off
+ case SHADER_TYPE_VERTEX: return VK_SHADER_STAGE_VERTEX_BIT;
+ case SHADER_TYPE_HULL: return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
+ case SHADER_TYPE_DOMAIN: return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
+ case SHADER_TYPE_GEOMETRY: return VK_SHADER_STAGE_GEOMETRY_BIT;
+ case SHADER_TYPE_PIXEL: return VK_SHADER_STAGE_FRAGMENT_BIT;
+ case SHADER_TYPE_COMPUTE: return VK_SHADER_STAGE_COMPUTE_BIT;
+ case SHADER_TYPE_AMPLIFICATION: return VK_SHADER_STAGE_TASK_BIT_NV;
+ case SHADER_TYPE_MESH: return VK_SHADER_STAGE_MESH_BIT_NV;
+ case SHADER_TYPE_RAY_GEN: return VK_SHADER_STAGE_RAYGEN_BIT_KHR;
+ case SHADER_TYPE_RAY_MISS: return VK_SHADER_STAGE_MISS_BIT_KHR;
+ case SHADER_TYPE_RAY_CLOSEST_HIT: return VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR;
+ case SHADER_TYPE_RAY_ANY_HIT: return VK_SHADER_STAGE_ANY_HIT_BIT_KHR;
+ case SHADER_TYPE_RAY_INTERSECTION: return VK_SHADER_STAGE_INTERSECTION_BIT_KHR;
+ case SHADER_TYPE_CALLABLE: return VK_SHADER_STAGE_CALLABLE_BIT_KHR;
+ // clang-format on
+ default:
+ UNEXPECTED("Unknown shader type");
+ return VK_SHADER_STAGE_VERTEX_BIT;
+ }
+}
+
VkBuildAccelerationStructureFlagsKHR BuildASFlagsToVkBuildAccelerationStructureFlags(RAYTRACING_BUILD_AS_FLAGS Flags)
{
static_assert(RAYTRACING_BUILD_AS_FLAGS_LAST == RAYTRACING_BUILD_AS_LOW_MEMORY,
diff --git a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp
index 5c35de33..091e2343 100644
--- a/Graphics/ShaderTools/include/SPIRVShaderResources.hpp
+++ b/Graphics/ShaderTools/include/SPIRVShaderResources.hpp
@@ -78,10 +78,11 @@ struct SPIRVShaderResourceAttribs
static constexpr const Uint32 InvalidSepSmplrOrImgInd = static_cast<Uint32>(-1);
-/* 0 */const char* const Name;
-/* 8 */const Uint16 ArraySize;
-/* 10 */const ResourceType Type;
-/* 11 */ // unused
+/* 0 */const char* const Name;
+/* 8 */const Uint16 ArraySize;
+/* 10 */const ResourceType Type;
+/* 11.0*/const Uint8 ResourceDim : 7;
+/* 11.7*/const Uint8 IsMS : 1;
private:
// Defines the mapping between separate samplers and seperate images when HLSL-style
// combined texture samplers are in use (i.e. texture2D g_Tex + sampler g_Tex_sampler).
@@ -159,6 +160,16 @@ public:
}
ShaderResourceDesc GetResourceDesc() const;
+
+ RESOURCE_DIMENSION GetResourceDimension() const
+ {
+ return static_cast<RESOURCE_DIMENSION>(ResourceDim);
+ }
+
+ bool IsMultisample() const
+ {
+ return IsMS != 0;
+ }
};
static_assert(sizeof(SPIRVShaderResourceAttribs) % sizeof(void*) == 0, "Size of SPIRVShaderResourceAttribs struct must be multiple of sizeof(void*)");
diff --git a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp
index dbdc81bc..cda18772 100644
--- a/Graphics/ShaderTools/src/SPIRVShaderResources.cpp
+++ b/Graphics/ShaderTools/src/SPIRVShaderResources.cpp
@@ -53,6 +53,46 @@ Type GetResourceArraySize(const diligent_spirv_cross::Compiler& Compiler,
return static_cast<Type>(arrSize);
}
+static RESOURCE_DIMENSION GetResourceDimension(const diligent_spirv_cross::Compiler& Compiler,
+ const diligent_spirv_cross::Resource& Res)
+{
+ const auto& type = Compiler.get_type(Res.type_id);
+ if (type.basetype == diligent_spirv_cross::SPIRType::BaseType::Image ||
+ type.basetype == diligent_spirv_cross::SPIRType::BaseType::SampledImage)
+ {
+ switch (type.image.dim)
+ {
+ // clang-format off
+ case spv::Dim1D: return type.image.arrayed ? RESOURCE_DIM_TEX_1D_ARRAY : RESOURCE_DIM_TEX_1D;
+ case spv::Dim2D: return type.image.arrayed ? RESOURCE_DIM_TEX_2D_ARRAY : RESOURCE_DIM_TEX_2D;
+ case spv::Dim3D: return RESOURCE_DIM_TEX_3D;
+ case spv::DimCube: return type.image.arrayed ? RESOURCE_DIM_TEX_CUBE_ARRAY : RESOURCE_DIM_TEX_CUBE;
+ case spv::DimBuffer: return RESOURCE_DIM_BUFFER;
+ // clang-format on
+ default: return RESOURCE_DIM_UNDEFINED;
+ }
+ }
+ else
+ {
+ return RESOURCE_DIM_UNDEFINED;
+ }
+}
+
+static bool IsMultisample(const diligent_spirv_cross::Compiler& Compiler,
+ const diligent_spirv_cross::Resource& Res)
+{
+ const auto& type = Compiler.get_type(Res.type_id);
+ if (type.basetype == diligent_spirv_cross::SPIRType::BaseType::Image ||
+ type.basetype == diligent_spirv_cross::SPIRType::BaseType::SampledImage)
+ {
+ return type.image.ms;
+ }
+ else
+ {
+ return RESOURCE_DIM_UNDEFINED;
+ }
+}
+
static uint32_t GetDecorationOffset(const diligent_spirv_cross::Compiler& Compiler,
const diligent_spirv_cross::Resource& Res,
spv::Decoration Decoration)
@@ -74,6 +114,8 @@ SPIRVShaderResourceAttribs::SPIRVShaderResourceAttribs(const diligent_spirv_cros
Name {_Name},
ArraySize {GetResourceArraySize<decltype(ArraySize)>(Compiler, Res)},
Type {_Type},
+ ResourceDim {Diligent::GetResourceDimension(Compiler, Res)},
+ IsMS {Diligent::IsMultisample(Compiler, Res) ? Uint8{1} : Uint8{0}},
SepSmplrOrImgInd {_SepSmplrOrImgInd},
BindingDecorationOffset {GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationBinding)},
DescriptorSetDecorationOffset {GetDecorationOffset(Compiler, Res, spv::Decoration::DecorationDescriptorSet)}
@@ -588,6 +630,7 @@ void SPIRVShaderResources::Initialize(IMemoryAllocator& Allocator,
VERIFY_EXPR(GetNumACs() == Counters.NumACs);
VERIFY_EXPR(GetNumSepSmplrs() == Counters.NumSepSmplrs);
VERIFY_EXPR(GetNumSepImgs() == Counters.NumSepImgs);
+ VERIFY_EXPR(GetNumInptAtts() == Counters.NumInptAtts);
// clang-format on
if (MemorySize)
@@ -624,6 +667,9 @@ SPIRVShaderResources::~SPIRVShaderResources()
for (Uint32 n = 0; n < GetNumSepImgs(); ++n)
GetSepImg(n).~SPIRVShaderResourceAttribs();
+ for (Uint32 n = 0; n < GetNumInptAtts(); ++n)
+ GetInptAtt(n).~SPIRVShaderResourceAttribs();
+
for (Uint32 n = 0; n < GetNumShaderStageInputs(); ++n)
GetShaderStageInputAttribs(n).~SPIRVShaderStageInputAttribs();
}
@@ -754,7 +800,8 @@ bool SPIRVShaderResources::IsCompatibleWith(const SPIRVShaderResources& Resource
GetNumSmpldImgs() != Resources.GetNumSmpldImgs() ||
GetNumACs() != Resources.GetNumACs() ||
GetNumSepImgs() != Resources.GetNumSepImgs() ||
- GetNumSepSmplrs() != Resources.GetNumSepSmplrs())
+ GetNumSepSmplrs() != Resources.GetNumSepSmplrs() ||
+ GetNumInptAtts() != Resources.GetNumInptAtts())
return false;
// clang-format on
VERIFY_EXPR(GetTotalResources() == Resources.GetTotalResources());