git.s-ol.nu ~forks/DiligentCore / 42217cc
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 azhirnov 10 months ago
145 changed file(s) with 5847 addition(s) and 3273 deletion(s). Raw diff Collapse all Expand all
1818 interface/FixedBlockMemoryAllocator.hpp
1919 interface/HashUtils.hpp
2020 interface/LockHelper.hpp
21 interface/LinearAllocator.hpp
2122 interface/MemoryFileStream.hpp
2223 interface/ObjectBase.hpp
2324 interface/RefCntAutoPtr.hpp
2929 /// \file
3030 /// Alignment utilities
3131
32 #include <cstdint>
33
3234 #include "../../Platforms/Basic/interface/DebugUtilities.hpp"
3335
3436 namespace Diligent
4850 }
4951
5052 template <typename T>
53 inline T* Align(T* val, size_t alignment)
54 {
55 return reinterpret_cast<T*>(Align(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment)));
56 }
57
58 template <typename T>
5159 inline T AlignDown(T val, T alignment)
5260 {
5361 VERIFY(IsPowerOfTwo(alignment), "Alignment (", alignment, ") must be power of 2");
5462 return val & ~(alignment - 1);
5563 }
5664
65 template <typename T>
66 inline T* AlignDown(T* val, size_t alignment)
67 {
68 return reinterpret_cast<T*>(AlignDown(reinterpret_cast<uintptr_t>(val), static_cast<uintptr_t>(alignment)));
69 }
70
5771 } // namespace Diligent
0 /*
1 * Copyright 2019-2020 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #pragma once
28
29 /// \file
30 /// Defines Diligent::LinearAllocator class
31
32 #include <vector>
33
34 #include "../../Primitives/interface/BasicTypes.h"
35 #include "../../Primitives/interface/MemoryAllocator.h"
36 #include "../../Platforms/Basic/interface/DebugUtilities.hpp"
37 #include "Align.hpp"
38
39 namespace Diligent
40 {
41
42 /// Implementation of a linear allocator on a fixed-size memory page
43 class LinearAllocator
44 {
45 public:
46 // clang-format off
47 LinearAllocator (const LinearAllocator&) = delete;
48 LinearAllocator& operator=(const LinearAllocator&) = delete;
49 LinearAllocator& operator=(LinearAllocator&&) = delete;
50 // clang-format on
51
52 explicit LinearAllocator(IMemoryAllocator& Allocator) noexcept :
53 m_pAllocator{&Allocator}
54 {}
55
56 LinearAllocator(LinearAllocator&& Other) noexcept :
57 // clang-format off
58 m_pDataStart {Other.m_pDataStart },
59 m_pCurrPtr {Other.m_pCurrPtr },
60 m_ReservedSize {Other.m_ReservedSize },
61 m_CurrAlignment{Other.m_CurrAlignment},
62 m_pAllocator {Other.m_pAllocator }
63 // clang-format on
64 {
65 Other.Reset();
66 }
67
68 ~LinearAllocator()
69 {
70 Free();
71 }
72
73 void Free()
74 {
75 if (m_pDataStart != nullptr && m_pAllocator != nullptr)
76 {
77 m_pAllocator->Free(m_pDataStart);
78 }
79 Reset();
80 }
81
82 void* Release()
83 {
84 void* Ptr = m_pDataStart;
85 Reset();
86 return Ptr;
87 }
88
89 void* ReleaseOwnership() noexcept
90 {
91 m_pAllocator = nullptr;
92 return GetDataPtr();
93 }
94
95 void* GetDataPtr() const noexcept
96 {
97 return m_pDataStart;
98 }
99
100 void AddSpace(size_t size, size_t alignment) noexcept
101 {
102 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
103 VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!");
104
105 if (size == 0)
106 return;
107
108 if (m_CurrAlignment == 0)
109 {
110 VERIFY(m_ReservedSize == 0, "This is expected to be a very first time the space is added");
111 m_CurrAlignment = sizeof(void*);
112 }
113
114 if (alignment > m_CurrAlignment)
115 {
116 // Reserve extra space that may be needed for alignment
117 m_ReservedSize += alignment - m_CurrAlignment;
118 }
119 m_CurrAlignment = alignment;
120
121 size = Align(size, alignment);
122 m_ReservedSize += size;
123
124 #if DILIGENT_DEBUG
125 m_DbgAllocations.emplace_back(size, alignment, m_ReservedSize);
126 #endif
127 }
128
129 template <typename T>
130 void AddSpace(size_t count = 1) noexcept
131 {
132 AddSpace(sizeof(T) * count, alignof(T));
133 }
134
135 void AddSpaceForString(const Char* str) noexcept
136 {
137 VERIFY_EXPR(str != nullptr);
138 AddSpace(strlen(str) + 1, 1);
139 }
140
141 void AddSpaceForString(const String& str) noexcept
142 {
143 AddSpaceForString(str.c_str());
144 }
145
146 void Reserve(size_t size)
147 {
148 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
149 VERIFY(m_ReservedSize == 0, "Space has been added to the allocator and will be overriden");
150 m_ReservedSize = size;
151 Reserve();
152 }
153
154 void Reserve()
155 {
156 VERIFY(m_pDataStart == nullptr, "Memory has already been allocated");
157 VERIFY(m_pAllocator != nullptr, "Allocator must not be null");
158 // Make sure the data size is at least sizeof(void*)-aligned
159 m_ReservedSize = Align(m_ReservedSize, sizeof(void*));
160 if (m_ReservedSize > 0)
161 {
162 m_pDataStart = reinterpret_cast<uint8_t*>(m_pAllocator->Allocate(m_ReservedSize, "Raw memory for linear allocator", __FILE__, __LINE__));
163 VERIFY(m_pDataStart == Align(m_pDataStart, sizeof(void*)), "Memory pointer must be at least sizeof(void*)-aligned");
164
165 m_pCurrPtr = m_pDataStart;
166 }
167 m_CurrAlignment = sizeof(void*);
168 }
169
170 void* Allocate(size_t size, size_t alignment)
171 {
172 VERIFY(size == 0 || m_pDataStart != nullptr, "Memory has not been allocated");
173 VERIFY(IsPowerOfTwo(alignment), "Alignment is not a power of two!");
174
175 if (size == 0)
176 return nullptr;
177
178 size = Align(size, alignment);
179
180 #if DILIGENT_DEBUG
181 VERIFY(m_DbgCurrAllocation < m_DbgAllocations.size(), "Allocation number exceed the number of allocations that were originally reserved.");
182 const auto& CurrAllocation = m_DbgAllocations[m_DbgCurrAllocation++];
183 VERIFY(CurrAllocation.size == size, "Allocation size (", size, ") does not match the initially requested size (", CurrAllocation.size, ")");
184 VERIFY(CurrAllocation.alignment == alignment, "Allocation alignment (", alignment, ") does not match the initially requested alignment (", CurrAllocation.alignment, ")");
185 #endif
186
187 VERIFY(Align(m_pCurrPtr, m_CurrAlignment) == m_pCurrPtr, "Current pointer is not aligned as expected");
188 m_pCurrPtr = Align(m_pCurrPtr, alignment);
189 m_CurrAlignment = alignment;
190
191 VERIFY(m_pCurrPtr + size <= m_pDataStart + CurrAllocation.reserved_size,
192 "Allocation size exceeds the initially reserved space. This is likely a bug.");
193
194 auto* ptr = m_pCurrPtr;
195 m_pCurrPtr += size;
196
197 VERIFY(m_pCurrPtr <= m_pDataStart + m_ReservedSize, "Allocation size exceeds the reserved space");
198
199 return ptr;
200 }
201
202 template <typename T>
203 T* Allocate(size_t count = 1)
204 {
205 return reinterpret_cast<T*>(Allocate(sizeof(T) * count, alignof(T)));
206 }
207
208 template <typename T, typename... Args>
209 T* Construct(Args&&... args)
210 {
211 T* Ptr = Allocate<T>();
212 new (Ptr) T{std::forward<Args>(args)...};
213 return Ptr;
214 }
215
216 template <typename T, typename... Args>
217 T* ConstructArray(size_t count, const Args&... args)
218 {
219 T* Ptr = Allocate<T>(count);
220 for (size_t i = 0; i < count; ++i)
221 {
222 new (Ptr + i) T{args...};
223 }
224 return Ptr;
225 }
226
227 template <typename T>
228 T* Copy(const T& Src)
229 {
230 return Construct<T>(Src);
231 }
232
233 template <typename T>
234 T* CopyArray(const T* Src, size_t count)
235 {
236 T* Dst = Allocate<T>(count);
237 for (size_t i = 0; i < count; ++i)
238 {
239 new (Dst + i) T{Src[i]};
240 }
241 return Dst;
242 }
243
244 Char* CopyString(const char* Str)
245 {
246 if (Str == nullptr)
247 return nullptr;
248
249 auto* Ptr = reinterpret_cast<Char*>(Allocate(strlen(Str) + 1, 1));
250 Char* Dst = Ptr;
251
252 const auto* pDataEnd = reinterpret_cast<Char*>(m_pDataStart) + m_ReservedSize;
253 while (*Str != 0 && Dst < pDataEnd)
254 {
255 *(Dst++) = *(Str++);
256 }
257 if (Dst < pDataEnd)
258 *(Dst++) = 0;
259 else
260 UNEXPECTED("Not enough space reserved for the string");
261
262 VERIFY_EXPR(reinterpret_cast<Char*>(m_pCurrPtr) == Dst);
263 return Ptr;
264 }
265
266 Char* CopyString(const std::string& Str)
267 {
268 return CopyString(Str.c_str());
269 }
270
271 size_t GetCurrentSize() const
272 {
273 return static_cast<size_t>(m_pCurrPtr - m_pDataStart);
274 }
275
276 size_t GetReservedSize() const
277 {
278 return m_ReservedSize;
279 }
280
281 private:
282 void Reset()
283 {
284 m_pDataStart = nullptr;
285 m_pCurrPtr = nullptr;
286 m_ReservedSize = 0;
287 m_CurrAlignment = 0;
288 m_pAllocator = nullptr;
289 }
290
291 uint8_t* m_pDataStart = nullptr;
292 uint8_t* m_pCurrPtr = nullptr;
293 size_t m_ReservedSize = 0;
294 size_t m_CurrAlignment = 0;
295 IMemoryAllocator* m_pAllocator = nullptr;
296
297 #if DILIGENT_DEBUG
298 size_t m_DbgCurrAllocation = 0;
299 struct DbgAllocationInfo
300 {
301 const size_t size;
302 const size_t alignment;
303 const size_t reserved_size;
304
305 DbgAllocationInfo(size_t _size, size_t _alignment, size_t _reserved_size) :
306 size{_size},
307 alignment{_alignment},
308 reserved_size{_reserved_size}
309 {
310 }
311 };
312 std::vector<DbgAllocationInfo> m_DbgAllocations;
313 #endif
314 };
315
316 } // namespace Diligent
3636
3737 void* DefaultRawMemoryAllocator::Allocate(size_t Size, const Char* dbgDescription, const char* dbgFileName, const Int32 dbgLineNumber)
3838 {
39 VERIFY_EXPR(Size > 0);
3940 return new Uint8[Size];
4041 }
4142
7373
7474 void* FixedBlockMemoryAllocator::Allocate(size_t Size, const Char* dbgDescription, const char* dbgFileName, const Int32 dbgLineNumber)
7575 {
76 VERIFY_EXPR(Size > 0);
77
7678 Size = AdjustBlockSize(Size);
7779 VERIFY(m_BlockSize == Size, "Requested size (", Size, ") does not match the block size (", m_BlockSize, ")");
7880
770770 {
771771 // clang-format off
772772 #define INIT_USGAGE_STR(Usage)UsageStrings[Usage] = #Usage
773 INIT_USGAGE_STR( USAGE_STATIC );
774 INIT_USGAGE_STR( USAGE_DEFAULT );
775 INIT_USGAGE_STR( USAGE_DYNAMIC );
776 INIT_USGAGE_STR( USAGE_STAGING );
777 INIT_USGAGE_STR( USAGE_UNIFIED );
773 INIT_USGAGE_STR(USAGE_IMMUTABLE);
774 INIT_USGAGE_STR(USAGE_DEFAULT);
775 INIT_USGAGE_STR(USAGE_DYNAMIC);
776 INIT_USGAGE_STR(USAGE_STAGING);
777 INIT_USGAGE_STR(USAGE_UNIFIED);
778778 #undef INIT_USGAGE_STR
779779 // clang-format on
780780 bUsageStringsInit = true;
781781 }
782 if (Usage >= USAGE_STATIC && Usage < USAGE_NUM_USAGES)
782 if (Usage >= USAGE_IMMUTABLE && Usage < USAGE_NUM_USAGES)
783783 return UsageStrings[Usage];
784784 else
785785 {
796796 {
797797 TexTypeStrings[RESOURCE_DIM_UNDEFINED] = "Undefined";
798798 TexTypeStrings[RESOURCE_DIM_BUFFER] = "Buffer";
799 TexTypeStrings[RESOURCE_DIM_TEX_1D] = "Tex 1D";
800 TexTypeStrings[RESOURCE_DIM_TEX_1D_ARRAY] = "Tex 1D Array";
801 TexTypeStrings[RESOURCE_DIM_TEX_2D] = "Tex 2D";
802 TexTypeStrings[RESOURCE_DIM_TEX_2D_ARRAY] = "Tex 2D Array";
803 TexTypeStrings[RESOURCE_DIM_TEX_3D] = "Tex 3D";
804 TexTypeStrings[RESOURCE_DIM_TEX_CUBE] = "Tex Cube";
805 TexTypeStrings[RESOURCE_DIM_TEX_CUBE_ARRAY] = "Tex Cube Array";
799 TexTypeStrings[RESOURCE_DIM_TEX_1D] = "Texture 1D";
800 TexTypeStrings[RESOURCE_DIM_TEX_1D_ARRAY] = "Texture 1D Array";
801 TexTypeStrings[RESOURCE_DIM_TEX_2D] = "Texture 2D";
802 TexTypeStrings[RESOURCE_DIM_TEX_2D_ARRAY] = "Texture 2D Array";
803 TexTypeStrings[RESOURCE_DIM_TEX_3D] = "Texture 3D";
804 TexTypeStrings[RESOURCE_DIM_TEX_CUBE] = "Texture Cube";
805 TexTypeStrings[RESOURCE_DIM_TEX_CUBE_ARRAY] = "Texture Cube Array";
806806 static_assert(RESOURCE_DIM_NUM_DIMENSIONS == RESOURCE_DIM_TEX_CUBE_ARRAY + 1, "Not all texture type strings initialized.");
807807
808808 bTexTypeStrsInit = true;
13361336 {
13371337 VERIFY(IsConsistentShaderType(ShaderType, PipelineType), "Shader type ", GetShaderTypeLiteralName(ShaderType),
13381338 " is inconsistent with pipeline type ", GetPipelineTypeString(PipelineType));
1339 VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "Only single shader stage should be provided");
1339 VERIFY(IsPowerOfTwo(Uint32{ShaderType}), "More than one shader type is specified");
13401340
13411341 static_assert(SHADER_TYPE_LAST == SHADER_TYPE_CALLABLE, "Please update the switch below to handle the new shader type");
13421342 switch (ShaderType)
14871487 // For non-compressed formats, BlockWidth is 1.
14881488 Offset += (LocationX / FmtAttribs.BlockWidth) * FmtAttribs.GetElementSize();
14891489
1490 // Note: this addressing complies with how Vulkan addresses textures when copying data to/from buffer:
1490 // Note: this addressing complies with how Vulkan (as well as OpenGL/GLES and Metal) address
1491 // textures when copying data to/from buffers:
14911492 // address of (x,y,z) = bufferOffset + (((z * imageHeight) + y) * rowLength + x) * texelBlockSize; (18.4.1)
14921493 }
14931494
7171 src/DefaultShaderSourceStreamFactory.cpp
7272 src/EngineMemory.cpp
7373 src/FramebufferBase.cpp
74 src/PipelineStateBase.cpp
7475 src/ResourceMappingBase.cpp
7576 src/RenderPassBase.cpp
7677 src/TextureBase.cpp
2929 /// \file
3030 /// Implementation of the Diligent::BufferBase template class
3131
32 #include <memory>
33
3234 #include "Buffer.h"
3335 #include "GraphicsTypes.h"
3436 #include "DeviceObjectBase.hpp"
3537 #include "GraphicsAccessories.hpp"
3638 #include "STDAllocator.hpp"
37 #include <memory>
39 #include "FormatString.hpp"
3840
3941 namespace Diligent
4042 {
231233 {
232234 BufferViewDesc ViewDesc;
233235 ViewDesc.ViewType = BUFFER_VIEW_UNORDERED_ACCESS;
236 auto UAVName = FormatString("Default UAV of buffer '", this->m_Desc.Name, '\'');
237 ViewDesc.Name = UAVName.c_str();
238
234239 IBufferView* pUAV = nullptr;
235240 CreateViewInternal(ViewDesc, &pUAV, true);
236241 m_pDefaultUAV.reset(static_cast<BufferViewImplType*>(pUAV));
241246 {
242247 BufferViewDesc ViewDesc;
243248 ViewDesc.ViewType = BUFFER_VIEW_SHADER_RESOURCE;
249 auto SRVName = FormatString("Default SRV of buffer '", this->m_Desc.Name, '\'');
250 ViewDesc.Name = SRVName.c_str();
251
244252 IBufferView* pSRV = nullptr;
245253 CreateViewInternal(ViewDesc, &pSRV, true);
246254 m_pDefaultSRV.reset(static_cast<BufferViewImplType*>(pSRV));
16711671 return;
16721672 }
16731673
1674 const auto& PSODesc = m_pPipelineState->GetDesc();
1675 if (!PSODesc.IsAnyGraphicsPipeline())
1676 {
1677 LOG_ERROR_MESSAGE("Pipeline state '", PSODesc.Name, "' is not a graphics pipeline");
1678 return;
1679 }
1680
16741681 TEXTURE_FORMAT BoundRTVFormats[8] = {TEX_FORMAT_UNKNOWN};
16751682 TEXTURE_FORMAT BoundDSVFormat = TEX_FORMAT_UNKNOWN;
16761683
16841691
16851692 BoundDSVFormat = m_pBoundDepthStencil ? m_pBoundDepthStencil->GetDesc().Format : TEX_FORMAT_UNKNOWN;
16861693
1687 const auto& PSODesc = m_pPipelineState->GetDesc();
1688 const auto& GraphicsPipeline = PSODesc.GraphicsPipeline;
1694 const auto& GraphicsPipeline = m_pPipelineState->GetGraphicsPipelineDesc();
16891695 if (GraphicsPipeline.NumRenderTargets != m_NumBoundRenderTargets)
16901696 {
16911697 LOG_WARNING_MESSAGE("The number of currently bound render targets (", m_NumBoundRenderTargets,
3737 #include "STDAllocator.hpp"
3838 #include "EngineMemory.h"
3939 #include "GraphicsAccessories.hpp"
40 #include "StringPool.hpp"
40 #include "LinearAllocator.hpp"
4141
4242 namespace Diligent
4343 {
44
45 void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false);
46 void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false);
47
48 void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept;
4449
4550 /// Template class implementing base functionality for a pipeline state object.
4651
5661 public:
5762 using TDeviceObjectBase = DeviceObjectBase<BaseInterface, RenderDeviceImplType, PipelineStateDesc>;
5863
59 /// \param pRefCounters - reference counters object that controls the lifetime of this PSO
60 /// \param pDevice - pointer to the device.
61 /// \param PSODesc - pipeline state description.
62 /// \param bIsDeviceInternal - flag indicating if the blend state is an internal device object and
64 /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO
65 /// \param pDevice - Pointer to the device.
66 /// \param CreateInfo - Pipeline state create info.
67 /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and
6368 /// must not keep a strong reference to the device.
6469 PipelineStateBase(IReferenceCounters* pRefCounters,
6570 RenderDeviceImplType* pDevice,
6671 const PipelineStateDesc& PSODesc,
6772 bool bIsDeviceInternal = false) :
68 TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal},
69 m_NumShaders{0}
70 {
71 ValidateDesc();
72
73 const auto& SrcLayout = PSODesc.ResourceLayout;
74 size_t StringPoolSize = 0;
75 if (SrcLayout.Variables != nullptr)
76 {
77 for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
78 StringPoolSize += strlen(SrcLayout.Variables[i].Name) + 1;
79 }
80
81 if (SrcLayout.StaticSamplers != nullptr)
82 {
83 for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i)
84 StringPoolSize += strlen(SrcLayout.StaticSamplers[i].SamplerOrTextureName) + 1;
85 }
86
87 if (PSODesc.IsAnyGraphicsPipeline())
88 {
89 CheckAndCorrectBlendStateDesc();
90 CheckRasterizerStateDesc();
91 CheckAndCorrectDepthStencilDesc();
92
93 const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout;
94 for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
95 StringPoolSize += strlen(InputLayout.LayoutElements[i].HLSLSemantic) + 1;
96 }
97 else
98 {
99 DEV_CHECK_ERR(PSODesc.GraphicsPipeline.InputLayout.NumElements == 0, "Compute pipelines must not have input layout elements");
100 }
101
102 m_StringPool.Reserve(StringPoolSize, GetRawAllocator());
103
104 auto& DstLayout = this->m_Desc.ResourceLayout;
105 if (SrcLayout.Variables != nullptr)
106 {
107 ShaderResourceVariableDesc* Variables =
108 ALLOCATE(GetRawAllocator(), "Memory for ShaderResourceVariableDesc array", ShaderResourceVariableDesc, SrcLayout.NumVariables);
109 DstLayout.Variables = Variables;
110 for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
111 {
112 VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null");
113 Variables[i] = SrcLayout.Variables[i];
114 Variables[i].Name = m_StringPool.CopyString(SrcLayout.Variables[i].Name);
115 }
116 }
117
118 if (SrcLayout.StaticSamplers != nullptr)
119 {
120 StaticSamplerDesc* StaticSamplers =
121 ALLOCATE(GetRawAllocator(), "Memory for StaticSamplerDesc array", StaticSamplerDesc, SrcLayout.NumStaticSamplers);
122 DstLayout.StaticSamplers = StaticSamplers;
123 for (Uint32 i = 0; i < SrcLayout.NumStaticSamplers; ++i)
124 {
125 VERIFY(SrcLayout.StaticSamplers[i].SamplerOrTextureName != nullptr, "Static sampler or texture name can't be null");
126 #ifdef DILIGENT_DEVELOPMENT
127 {
128 const auto& BorderColor = SrcLayout.StaticSamplers[i].Desc.BorderColor;
129 if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) ||
130 (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) ||
131 (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1)))
132 {
133 LOG_WARNING_MESSAGE("Static sampler for variable \"", SrcLayout.StaticSamplers[i].SamplerOrTextureName, "\" specifies border color (",
134 BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3],
135 "). 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");
136 }
137 }
138 #endif
139
140 StaticSamplers[i] = SrcLayout.StaticSamplers[i];
141 StaticSamplers[i].SamplerOrTextureName = m_StringPool.CopyString(SrcLayout.StaticSamplers[i].SamplerOrTextureName);
142 }
143 }
144
145
146 if (this->m_Desc.IsComputePipeline())
147 {
148 const auto& ComputePipeline = PSODesc.ComputePipeline;
149 if (ComputePipeline.pCS == nullptr)
150 {
151 LOG_ERROR_AND_THROW("Compute shader is not provided");
152 }
153
154 #define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \
155 if (Shader && Shader->GetDesc().ShaderType != ExpectedType) \
156 { \
157 LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \
158 }
159
160 VALIDATE_SHADER_TYPE(ComputePipeline.pCS, SHADER_TYPE_COMPUTE, "compute")
161
162 m_pCS = ComputePipeline.pCS;
163 m_ppShaders[0] = ComputePipeline.pCS;
164 m_NumShaders = 1;
165 }
166 else
167 {
168 const auto& GraphicsPipeline = PSODesc.GraphicsPipeline;
169
170 VALIDATE_SHADER_TYPE(GraphicsPipeline.pVS, SHADER_TYPE_VERTEX, "vertex")
171 VALIDATE_SHADER_TYPE(GraphicsPipeline.pPS, SHADER_TYPE_PIXEL, "pixel")
172 VALIDATE_SHADER_TYPE(GraphicsPipeline.pGS, SHADER_TYPE_GEOMETRY, "geometry")
173 VALIDATE_SHADER_TYPE(GraphicsPipeline.pHS, SHADER_TYPE_HULL, "hull")
174 VALIDATE_SHADER_TYPE(GraphicsPipeline.pDS, SHADER_TYPE_DOMAIN, "domain")
175 VALIDATE_SHADER_TYPE(GraphicsPipeline.pAS, SHADER_TYPE_AMPLIFICATION, "amplification")
176 VALIDATE_SHADER_TYPE(GraphicsPipeline.pMS, SHADER_TYPE_MESH, "mesh")
177 #undef VALIDATE_SHADER_TYPE
178
179 if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS)
180 {
181 DEV_CHECK_ERR(GraphicsPipeline.pVS, "Vertex shader must be defined");
182 DEV_CHECK_ERR(!GraphicsPipeline.pAS && !GraphicsPipeline.pMS, "Mesh shaders are not supported in graphics pipeline");
183 m_pVS = GraphicsPipeline.pVS;
184 m_pPS = GraphicsPipeline.pPS;
185 m_pGS = GraphicsPipeline.pGS;
186 m_pDS = GraphicsPipeline.pDS;
187 m_pHS = GraphicsPipeline.pHS;
188 }
189 else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH)
190 {
191 DEV_CHECK_ERR(GraphicsPipeline.pMS, "Mesh shader must be defined");
192 DEV_CHECK_ERR(!GraphicsPipeline.pVS && !GraphicsPipeline.pGS && !GraphicsPipeline.pDS && !GraphicsPipeline.pHS,
193 "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline");
194 DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout ignored in mesh shader");
195 DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ||
196 GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED,
197 "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)");
198 m_pAS = GraphicsPipeline.pAS;
199 m_pMS = GraphicsPipeline.pMS;
200 m_pPS = GraphicsPipeline.pPS;
201 }
202
203 if (GraphicsPipeline.pVS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pVS;
204 if (GraphicsPipeline.pPS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pPS;
205 if (GraphicsPipeline.pGS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pGS;
206 if (GraphicsPipeline.pHS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pHS;
207 if (GraphicsPipeline.pDS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pDS;
208 if (GraphicsPipeline.pAS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pAS;
209 if (GraphicsPipeline.pMS) m_ppShaders[m_NumShaders++] = GraphicsPipeline.pMS;
210
211 DEV_CHECK_ERR(m_NumShaders > 0, "There must be at least one shader in the Pipeline State");
212
213 m_pRenderPass = PSODesc.GraphicsPipeline.pRenderPass;
214
215 for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt)
216 {
217 auto RTVFmt = GraphicsPipeline.RTVFormats[rt];
218 if (RTVFmt != TEX_FORMAT_UNKNOWN)
219 {
220 LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt,
221 " must be set to TEX_FORMAT_UNKNOWN");
222 }
223 }
224
225 if (m_pRenderPass)
226 {
227 const auto& RPDesc = m_pRenderPass->GetDesc();
228 VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount);
229 const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex];
230
231 this->m_Desc.GraphicsPipeline.NumRenderTargets = static_cast<Uint8>(Subpass.RenderTargetAttachmentCount);
232 for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt)
233 {
234 const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt];
235 if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED)
236 {
237 VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount);
238 this->m_Desc.GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format;
239 }
240 }
241
242 if (Subpass.pDepthStencilAttachment != nullptr)
243 {
244 const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment;
245 if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED)
246 {
247 VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount);
248 this->m_Desc.GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format;
249 }
250 }
251 }
252
253 const auto& InputLayout = PSODesc.GraphicsPipeline.InputLayout;
254 LayoutElement* pLayoutElements = nullptr;
255 if (InputLayout.NumElements > 0)
256 {
257 pLayoutElements = ALLOCATE(GetRawAllocator(), "Raw memory for input layout elements", LayoutElement, InputLayout.NumElements);
258 }
259 this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements;
260 for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem)
261 {
262 pLayoutElements[Elem] = InputLayout.LayoutElements[Elem];
263 pLayoutElements[Elem].HLSLSemantic = m_StringPool.CopyString(InputLayout.LayoutElements[Elem].HLSLSemantic);
264 }
265
266
267 // Correct description and compute offsets and tight strides
268 std::array<Uint32, MAX_BUFFER_SLOTS> Strides, TightStrides = {};
269 // Set all strides to an invalid value because an application may want to use 0 stride
270 for (auto& Stride : Strides)
271 Stride = LAYOUT_ELEMENT_AUTO_STRIDE;
272
273 for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
274 {
275 auto& LayoutElem = pLayoutElements[i];
276
277 if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16)
278 LayoutElem.IsNormalized = false; // Floating point values cannot be normalized
279
280 auto BuffSlot = LayoutElem.BufferSlot;
281 if (BuffSlot >= Strides.size())
282 {
283 UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds maximum allowed value (", Strides.size() - 1, ")");
284 continue;
285 }
286 m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, BuffSlot + 1);
287
288 auto& CurrAutoStride = TightStrides[BuffSlot];
289 // If offset is not explicitly specified, use current auto stride value
290 if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET)
291 {
292 LayoutElem.RelativeOffset = CurrAutoStride;
293 }
294
295 // If stride is explicitly specified, use it for the current buffer slot
296 if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE)
297 {
298 // Verify that the value is consistent with the previously specified stride, if any
299 if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride)
300 {
301 LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot,
302 ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ",
303 LayoutElem.Stride, ", while current value is ", Strides[BuffSlot],
304 ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow "
305 "the engine compute strides automatically.");
306 }
307 Strides[BuffSlot] = LayoutElem.Stride;
308 }
309
310 CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType));
311 }
312
313 for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
314 {
315 auto& LayoutElem = pLayoutElements[i];
316
317 auto BuffSlot = LayoutElem.BufferSlot;
318 // If no input elements explicitly specified stride for this buffer slot, use automatic stride
319 if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE)
320 {
321 Strides[BuffSlot] = TightStrides[BuffSlot];
322 }
323 else
324 {
325 if (Strides[BuffSlot] < TightStrides[BuffSlot])
326 {
327 LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot,
328 " is smaller than the minimum stride ", TightStrides[BuffSlot],
329 " required to accomodate all input elements.");
330 }
331 }
332 if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE)
333 LayoutElem.Stride = Strides[BuffSlot];
334 }
335
336 if (m_BufferSlotsUsed > 0)
337 {
338 m_pStrides = ALLOCATE(GetRawAllocator(), "Raw memory for buffer strides", Uint32, m_BufferSlotsUsed);
339
340 // Set strides for all unused slots to 0
341 for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i)
342 {
343 auto Stride = Strides[i];
344 m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0;
345 }
346 }
347 }
348
349 VERIFY_EXPR(m_StringPool.GetRemainingSize() == 0);
350
73 TDeviceObjectBase{pRefCounters, pDevice, PSODesc, bIsDeviceInternal}
74 {
35175 Uint64 DeviceQueuesMask = pDevice->GetCommandQueueMask();
35276 DEV_CHECK_ERR((this->m_Desc.CommandQueueMask & DeviceQueuesMask) != 0,
35377 "No bits in the command queue mask (0x", std::hex, this->m_Desc.CommandQueueMask,
35478 ") correspond to one of ", pDevice->GetCommandQueueCount(), " available device command queues");
35579 this->m_Desc.CommandQueueMask &= DeviceQueuesMask;
35680 }
81
82 /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO
83 /// \param pDevice - Pointer to the device.
84 /// \param GraphicsPipelineCI - Graphics pipeline create information.
85 /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and
86 /// must not keep a strong reference to the device.
87 PipelineStateBase(IReferenceCounters* pRefCounters,
88 RenderDeviceImplType* pDevice,
89 const GraphicsPipelineStateCreateInfo& GraphicsPipelineCI,
90 bool bIsDeviceInternal = false) :
91 PipelineStateBase{pRefCounters, pDevice, GraphicsPipelineCI.PSODesc, bIsDeviceInternal}
92 {
93 ValidateGraphicsPipelineCreateInfo(GraphicsPipelineCI);
94 }
95
96 /// \param pRefCounters - Reference counters object that controls the lifetime of this PSO
97 /// \param pDevice - Pointer to the device.
98 /// \param ComputePipelineCI - Compute pipeline create information.
99 /// \param bIsDeviceInternal - Flag indicating if the pipeline state is an internal device object and
100 /// must not keep a strong reference to the device.
101 PipelineStateBase(IReferenceCounters* pRefCounters,
102 RenderDeviceImplType* pDevice,
103 const ComputePipelineStateCreateInfo& ComputePipelineCI,
104 bool bIsDeviceInternal = false) :
105 PipelineStateBase{pRefCounters, pDevice, ComputePipelineCI.PSODesc, bIsDeviceInternal}
106 {
107 ValidateComputePipelineCreateInfo(ComputePipelineCI);
108 }
109
357110
358111 ~PipelineStateBase()
359112 {
374127 RasterizerStateRegistry.ReportDeletedObject();
375128 DSSRegistry.ReportDeletedObject();
376129 */
377
378 auto& RawAllocator = GetRawAllocator();
379 if (this->m_Desc.ResourceLayout.Variables != nullptr)
380 RawAllocator.Free(const_cast<ShaderResourceVariableDesc*>(this->m_Desc.ResourceLayout.Variables));
381 if (this->m_Desc.ResourceLayout.StaticSamplers != nullptr)
382 RawAllocator.Free(const_cast<StaticSamplerDesc*>(this->m_Desc.ResourceLayout.StaticSamplers));
383 if (this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements != nullptr)
384 RawAllocator.Free(const_cast<LayoutElement*>(this->m_Desc.GraphicsPipeline.InputLayout.LayoutElements));
385 if (m_pStrides != nullptr)
386 RawAllocator.Free(m_pStrides);
387130 }
388131
389132 IMPLEMENT_QUERY_INTERFACE_IN_PLACE(IID_PipelineState, TDeviceObjectBase)
398141 return m_BufferSlotsUsed;
399142 }
400143
401 IShader* GetVS() { return m_pVS; }
402 IShader* GetPS() { return m_pPS; }
403 IShader* GetGS() { return m_pGS; }
404 IShader* GetDS() { return m_pDS; }
405 IShader* GetHS() { return m_pHS; }
406 IShader* GetCS() { return m_pCS; }
407
408 IShader* const* GetShaders() const { return m_ppShaders.data(); }
409 Uint32 GetNumShaders() const { return m_NumShaders; }
410
411 template <typename ShaderType>
412 ShaderType* GetShader(Uint32 ShaderInd)
413 {
414 VERIFY_EXPR(ShaderInd < m_NumShaders);
415 return ValidatedCast<ShaderType>(m_ppShaders[ShaderInd]);
416 }
417 template <typename ShaderType>
418 ShaderType* GetShader(Uint32 ShaderInd) const
419 {
420 VERIFY_EXPR(ShaderInd < m_NumShaders);
421 return ValidatedCast<ShaderType>(m_ppShaders[ShaderInd]);
422 }
144 SHADER_TYPE GetShaderStageType(Uint32 Stage) const { return m_ShaderStageTypes[Stage]; }
145 Uint32 GetNumShaderStages() const { return m_NumShaderStages; }
423146
424147 // This function only compares shader resource layout hashes, so
425148 // it can potentially give false negatives
428151 return m_ShaderResourceLayoutHash != ValidatedCast<const PipelineStateBase>(pPSO)->m_ShaderResourceLayoutHash;
429152 }
430153
431 protected:
432 Uint32 m_BufferSlotsUsed = 0;
433 Uint32 m_NumShaders = 0; ///< Number of shaders that this PSO uses
434 Uint32* m_pStrides = nullptr;
435
436 StringPool m_StringPool;
437
438 RefCntAutoPtr<IShader> m_pVS; ///< Strong reference to the vertex shader
439 RefCntAutoPtr<IShader> m_pPS; ///< Strong reference to the pixel shader
440 RefCntAutoPtr<IShader> m_pGS; ///< Strong reference to the geometry shader
441 RefCntAutoPtr<IShader> m_pDS; ///< Strong reference to the domain shader
442 RefCntAutoPtr<IShader> m_pHS; ///< Strong reference to the hull shader
443 RefCntAutoPtr<IShader> m_pCS; ///< Strong reference to the compute shader
444 RefCntAutoPtr<IShader> m_pAS; ///< Strong reference to the amplification shader
445 RefCntAutoPtr<IShader> m_pMS; ///< Strong reference to the mesh shader
446
447 RefCntAutoPtr<IRenderPass> m_pRenderPass; ///< Strong reference to the render pass object
448
449 std::array<IShader*, MAX_SHADERS_IN_PIPELINE> m_ppShaders = {}; ///< Array of pointers to the shaders used by this PSO
450 size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout
451
154 virtual const GraphicsPipelineDesc& DILIGENT_CALL_TYPE GetGraphicsPipelineDesc() const override final
155 {
156 VERIFY_EXPR(this->m_Desc.IsAnyGraphicsPipeline());
157 VERIFY_EXPR(m_pGraphicsPipelineDesc != nullptr);
158 return *m_pGraphicsPipelineDesc;
159 }
452160
453161 protected:
454162 Int8 GetStaticVariableCountHelper(SHADER_TYPE ShaderType, const std::array<Int8, MAX_SHADERS_IN_PIPELINE>& ResourceLayoutIndex) const
511219 return LayoutInd;
512220 }
513221
222
223 void ReserveSpaceForPipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo,
224 LinearAllocator& MemPool) noexcept
225 {
226 MemPool.AddSpace<GraphicsPipelineDesc>();
227 ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool);
228
229 const auto& InputLayout = CreateInfo.GraphicsPipeline.InputLayout;
230 MemPool.AddSpace<LayoutElement>(InputLayout.NumElements);
231 for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
232 {
233 auto& LayoutElem = InputLayout.LayoutElements[i];
234 MemPool.AddSpaceForString(LayoutElem.HLSLSemantic);
235 m_BufferSlotsUsed = std::max(m_BufferSlotsUsed, static_cast<Uint8>(LayoutElem.BufferSlot + 1));
236 }
237
238 MemPool.AddSpace<Uint32>(m_BufferSlotsUsed);
239 }
240
241 void ReserveSpaceForPipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo,
242 LinearAllocator& MemPool) const noexcept
243 {
244 ReserveResourceLayout(CreateInfo.PSODesc.ResourceLayout, MemPool);
245 }
246
247
248 template <typename ShaderImplType, typename TShaderStages>
249 void ExtractShaders(const GraphicsPipelineStateCreateInfo& CreateInfo,
250 TShaderStages& ShaderStages)
251 {
252 VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once.");
253
254 ShaderStages.clear();
255 auto AddShaderStage = [&](IShader* pShader) {
256 if (pShader != nullptr)
257 {
258 auto ShaderType = pShader->GetDesc().ShaderType;
259 ShaderStages.emplace_back(ShaderType, ValidatedCast<ShaderImplType>(pShader));
260 VERIFY(m_ShaderStageTypes[m_NumShaderStages] == SHADER_TYPE_UNKNOWN, "This shader stage is already initialized.");
261 m_ShaderStageTypes[m_NumShaderStages++] = ShaderType;
262 }
263 };
264
265 switch (CreateInfo.PSODesc.PipelineType)
266 {
267 case PIPELINE_TYPE_GRAPHICS:
268 {
269 AddShaderStage(CreateInfo.pVS);
270 AddShaderStage(CreateInfo.pHS);
271 AddShaderStage(CreateInfo.pDS);
272 AddShaderStage(CreateInfo.pGS);
273 AddShaderStage(CreateInfo.pPS);
274 VERIFY(CreateInfo.pVS != nullptr, "Vertex shader must not be null");
275 break;
276 }
277
278 case PIPELINE_TYPE_MESH:
279 {
280 AddShaderStage(CreateInfo.pAS);
281 AddShaderStage(CreateInfo.pMS);
282 AddShaderStage(CreateInfo.pPS);
283 VERIFY(CreateInfo.pMS != nullptr, "Mesh shader must not be null");
284 break;
285 }
286
287 default:
288 UNEXPECTED("unknown pipeline type");
289 }
290
291 VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages);
292 }
293
294 template <typename ShaderImplType, typename TShaderStages>
295 void ExtractShaders(const ComputePipelineStateCreateInfo& CreateInfo,
296 TShaderStages& ShaderStages)
297 {
298 VERIFY(m_NumShaderStages == 0, "The number of shader stages is not zero! ExtractShaders must only be called once.");
299
300 ShaderStages.clear();
301
302 VERIFY_EXPR(CreateInfo.PSODesc.PipelineType == PIPELINE_TYPE_COMPUTE);
303 VERIFY_EXPR(CreateInfo.pCS != nullptr);
304 VERIFY_EXPR(CreateInfo.pCS->GetDesc().ShaderType == SHADER_TYPE_COMPUTE);
305
306 ShaderStages.emplace_back(SHADER_TYPE_COMPUTE, ValidatedCast<ShaderImplType>(CreateInfo.pCS));
307 m_ShaderStageTypes[m_NumShaderStages++] = SHADER_TYPE_COMPUTE;
308
309 VERIFY_EXPR(!ShaderStages.empty() && ShaderStages.size() == m_NumShaderStages);
310 }
311
312
313 void InitializePipelineDesc(const GraphicsPipelineStateCreateInfo& CreateInfo,
314 LinearAllocator& MemPool)
315 {
316 this->m_pGraphicsPipelineDesc = MemPool.Copy(CreateInfo.GraphicsPipeline);
317
318 auto& GraphicsPipeline = *this->m_pGraphicsPipelineDesc;
319 CorrectGraphicsPipelineDesc(GraphicsPipeline);
320
321 CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool);
322
323 m_pRenderPass = GraphicsPipeline.pRenderPass;
324 if (m_pRenderPass)
325 {
326 const auto& RPDesc = m_pRenderPass->GetDesc();
327 VERIFY_EXPR(GraphicsPipeline.SubpassIndex < RPDesc.SubpassCount);
328 const auto& Subpass = RPDesc.pSubpasses[GraphicsPipeline.SubpassIndex];
329
330 GraphicsPipeline.NumRenderTargets = static_cast<Uint8>(Subpass.RenderTargetAttachmentCount);
331 for (Uint32 rt = 0; rt < Subpass.RenderTargetAttachmentCount; ++rt)
332 {
333 const auto& RTAttachmentRef = Subpass.pRenderTargetAttachments[rt];
334 if (RTAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED)
335 {
336 VERIFY_EXPR(RTAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount);
337 GraphicsPipeline.RTVFormats[rt] = RPDesc.pAttachments[RTAttachmentRef.AttachmentIndex].Format;
338 }
339 }
340
341 if (Subpass.pDepthStencilAttachment != nullptr)
342 {
343 const auto& DSAttachmentRef = *Subpass.pDepthStencilAttachment;
344 if (DSAttachmentRef.AttachmentIndex != ATTACHMENT_UNUSED)
345 {
346 VERIFY_EXPR(DSAttachmentRef.AttachmentIndex < RPDesc.AttachmentCount);
347 GraphicsPipeline.DSVFormat = RPDesc.pAttachments[DSAttachmentRef.AttachmentIndex].Format;
348 }
349 }
350 }
351
352 const auto& InputLayout = GraphicsPipeline.InputLayout;
353 LayoutElement* pLayoutElements = MemPool.Allocate<LayoutElement>(InputLayout.NumElements);
354 for (size_t Elem = 0; Elem < InputLayout.NumElements; ++Elem)
355 {
356 const auto& SrcElem = InputLayout.LayoutElements[Elem];
357 pLayoutElements[Elem] = SrcElem;
358 VERIFY_EXPR(SrcElem.HLSLSemantic != nullptr);
359 pLayoutElements[Elem].HLSLSemantic = MemPool.CopyString(SrcElem.HLSLSemantic);
360 }
361 GraphicsPipeline.InputLayout.LayoutElements = pLayoutElements;
362
363
364 // Correct description and compute offsets and tight strides
365 std::array<Uint32, MAX_BUFFER_SLOTS> Strides, TightStrides = {};
366 // Set all strides to an invalid value because an application may want to use 0 stride
367 for (auto& Stride : Strides)
368 Stride = LAYOUT_ELEMENT_AUTO_STRIDE;
369
370 for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
371 {
372 auto& LayoutElem = pLayoutElements[i];
373
374 if (LayoutElem.ValueType == VT_FLOAT32 || LayoutElem.ValueType == VT_FLOAT16)
375 LayoutElem.IsNormalized = false; // Floating point values cannot be normalized
376
377 auto BuffSlot = LayoutElem.BufferSlot;
378 if (BuffSlot >= Strides.size())
379 {
380 UNEXPECTED("Buffer slot (", BuffSlot, ") exceeds the maximum allowed value (", Strides.size() - 1, ")");
381 continue;
382 }
383 VERIFY_EXPR(BuffSlot < m_BufferSlotsUsed);
384
385 auto& CurrAutoStride = TightStrides[BuffSlot];
386 // If offset is not explicitly specified, use current auto stride value
387 if (LayoutElem.RelativeOffset == LAYOUT_ELEMENT_AUTO_OFFSET)
388 {
389 LayoutElem.RelativeOffset = CurrAutoStride;
390 }
391
392 // If stride is explicitly specified, use it for the current buffer slot
393 if (LayoutElem.Stride != LAYOUT_ELEMENT_AUTO_STRIDE)
394 {
395 // Verify that the value is consistent with the previously specified stride, if any
396 if (Strides[BuffSlot] != LAYOUT_ELEMENT_AUTO_STRIDE && Strides[BuffSlot] != LayoutElem.Stride)
397 {
398 LOG_ERROR_MESSAGE("Inconsistent strides are specified for buffer slot ", BuffSlot,
399 ". Input element at index ", LayoutElem.InputIndex, " explicitly specifies stride ",
400 LayoutElem.Stride, ", while current value is ", Strides[BuffSlot],
401 ". Specify consistent strides or use LAYOUT_ELEMENT_AUTO_STRIDE to allow "
402 "the engine compute strides automatically.");
403 }
404 Strides[BuffSlot] = LayoutElem.Stride;
405 }
406
407 CurrAutoStride = std::max(CurrAutoStride, LayoutElem.RelativeOffset + LayoutElem.NumComponents * GetValueSize(LayoutElem.ValueType));
408 }
409
410 for (Uint32 i = 0; i < InputLayout.NumElements; ++i)
411 {
412 auto& LayoutElem = pLayoutElements[i];
413
414 auto BuffSlot = LayoutElem.BufferSlot;
415 // If no input elements explicitly specified stride for this buffer slot, use automatic stride
416 if (Strides[BuffSlot] == LAYOUT_ELEMENT_AUTO_STRIDE)
417 {
418 Strides[BuffSlot] = TightStrides[BuffSlot];
419 }
420 else
421 {
422 if (Strides[BuffSlot] < TightStrides[BuffSlot])
423 {
424 LOG_ERROR_MESSAGE("Stride ", Strides[BuffSlot], " explicitly specified for slot ", BuffSlot,
425 " is smaller than the minimum stride ", TightStrides[BuffSlot],
426 " required to accomodate all input elements.");
427 }
428 }
429 if (LayoutElem.Stride == LAYOUT_ELEMENT_AUTO_STRIDE)
430 LayoutElem.Stride = Strides[BuffSlot];
431 }
432
433 m_pStrides = MemPool.Allocate<Uint32>(m_BufferSlotsUsed);
434
435 // Set strides for all unused slots to 0
436 for (Uint32 i = 0; i < m_BufferSlotsUsed; ++i)
437 {
438 auto Stride = Strides[i];
439 m_pStrides[i] = Stride != LAYOUT_ELEMENT_AUTO_STRIDE ? Stride : 0;
440 }
441 }
442
443 void InitializePipelineDesc(const ComputePipelineStateCreateInfo& CreateInfo,
444 LinearAllocator& MemPool)
445 {
446 CopyResourceLayout(CreateInfo.PSODesc.ResourceLayout, this->m_Desc.ResourceLayout, MemPool);
447 }
448
514449 private:
515 #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__)
516
517 void ValidateDesc() const
518 {
519 if (this->m_Desc.IsComputePipeline())
520 {
521 if (this->m_Desc.GraphicsPipeline.pRenderPass != nullptr)
522 {
523 LOG_PSO_ERROR_AND_THROW("GraphicsPipeline.pRenderPass must be null for compute pipelines");
524 }
525 }
526 else
527 {
528 const auto& GraphicsPipeline = this->m_Desc.GraphicsPipeline;
529 if (GraphicsPipeline.pRenderPass != nullptr)
530 {
531 if (GraphicsPipeline.NumRenderTargets != 0)
532 LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used");
533 if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN)
534 LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
535
536 for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
450 static void ReserveResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, LinearAllocator& MemPool) noexcept
451 {
452 if (SrcLayout.Variables != nullptr)
453 {
454 MemPool.AddSpace<ShaderResourceVariableDesc>(SrcLayout.NumVariables);
455 for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
456 {
457 VERIFY(SrcLayout.Variables[i].Name != nullptr, "Variable name can't be null");
458 MemPool.AddSpaceForString(SrcLayout.Variables[i].Name);
459 }
460 }
461
462 if (SrcLayout.ImmutableSamplers != nullptr)
463 {
464 MemPool.AddSpace<ImmutableSamplerDesc>(SrcLayout.NumImmutableSamplers);
465 for (Uint32 i = 0; i < SrcLayout.NumImmutableSamplers; ++i)
466 {
467 VERIFY(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName != nullptr, "Immutable sampler or texture name can't be null");
468 MemPool.AddSpaceForString(SrcLayout.ImmutableSamplers[i].SamplerOrTextureName);
469 }
470 }
471 }
472
473 static void CopyResourceLayout(const PipelineResourceLayoutDesc& SrcLayout, PipelineResourceLayoutDesc& DstLayout, LinearAllocator& MemPool)
474 {
475 if (SrcLayout.Variables != nullptr)
476 {
477 auto* Variables = MemPool.Allocate<ShaderResourceVariableDesc>(SrcLayout.NumVariables);
478 DstLayout.Variables = Variables;
479 for (Uint32 i = 0; i < SrcLayout.NumVariables; ++i)
480 {
481 const auto& SrcVar = SrcLayout.Variables[i];
482 Variables[i] = SrcVar;
483 Variables[i].Name = MemPool.CopyString(SrcVar.Name);
484 }
485 }
486
487 if (SrcLayout.ImmutableSamplers != nullptr)
488 {
489 auto* ImmutableSamplers = MemPool.Allocate<ImmutableSamplerDesc>(SrcLayout.NumImmutableSamplers);
490 DstLayout.ImmutableSamplers = ImmutableSamplers;
491 for (Uint32 i = 0; i < SrcLayout.NumImmutableSamplers; ++i)
492 {
493 const auto& SrcSmplr = SrcLayout.ImmutableSamplers[i];
494 #ifdef DILIGENT_DEVELOPMENT
537495 {
538 if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN)
539 LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
496 const auto& BorderColor = SrcSmplr.Desc.BorderColor;
497 if (!((BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 0) ||
498 (BorderColor[0] == 0 && BorderColor[1] == 0 && BorderColor[2] == 0 && BorderColor[3] == 1) ||
499 (BorderColor[0] == 1 && BorderColor[1] == 1 && BorderColor[2] == 1 && BorderColor[3] == 1)))
500 {
501 LOG_WARNING_MESSAGE("Immutable sampler for variable \"", SrcSmplr.SamplerOrTextureName, "\" specifies border color (",
502 BorderColor[0], ", ", BorderColor[1], ", ", BorderColor[2], ", ", BorderColor[3],
503 "). 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");
504 }
540505 }
541
542 const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc();
543 if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount)
544 LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'");
545 }
546 else
547 {
548 if (GraphicsPipeline.SubpassIndex != 0)
549 LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used");
550 }
551 }
552 }
553
554 void CheckRasterizerStateDesc() const
555 {
556 const auto& RSDesc = this->m_Desc.GraphicsPipeline.RasterizerDesc;
557 if (RSDesc.FillMode == FILL_MODE_UNDEFINED)
558 LOG_PSO_ERROR_AND_THROW("RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED");
559 if (RSDesc.CullMode == CULL_MODE_UNDEFINED)
560 LOG_PSO_ERROR_AND_THROW("RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED");
561 }
562
563 void CheckAndCorrectDepthStencilDesc()
564 {
565 auto& DSSDesc = this->m_Desc.GraphicsPipeline.DepthStencilDesc;
566 if (DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN)
567 {
568 if (DSSDesc.DepthEnable)
569 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled");
570 else
571 DSSDesc.DepthFunc = DepthStencilStateDesc{}.DepthFunc;
572 }
573
574 auto CheckAndCorrectStencilOpDesc = [&](StencilOpDesc& OpDesc, const char* FaceName) //
575 {
576 if (DSSDesc.StencilEnable)
577 {
578 if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
579 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
580 if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
581 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
582 if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
583 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
584 if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
585 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled");
586 }
587 else
588 {
589 if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
590 OpDesc.StencilFailOp = StencilOpDesc{}.StencilFailOp;
591 if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
592 OpDesc.StencilDepthFailOp = StencilOpDesc{}.StencilDepthFailOp;
593 if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
594 OpDesc.StencilPassOp = StencilOpDesc{}.StencilPassOp;
595 if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
596 OpDesc.StencilFunc = StencilOpDesc{}.StencilFunc;
597 }
598 };
599 CheckAndCorrectStencilOpDesc(DSSDesc.FrontFace, "FrontFace");
600 CheckAndCorrectStencilOpDesc(DSSDesc.BackFace, "BackFace");
601 }
602
603 void CheckAndCorrectBlendStateDesc()
604 {
605 auto& BlendDesc = this->m_Desc.GraphicsPipeline.BlendDesc;
606 for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
607 {
608 auto& RTDesc = BlendDesc.RenderTargets[rt];
609 // clang-format off
610 const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
611 const auto LogicOpEnable = RTDesc.LogicOperationEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
612 // clang-format on
613 if (BlendEnable)
614 {
615 if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
616 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED");
617 if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
618 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED");
619 if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
620 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED");
621
622 if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
623 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
624 if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
625 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
626 if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
627 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED");
628 }
629 else
630 {
631 if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
632 RTDesc.SrcBlend = RenderTargetBlendDesc{}.SrcBlend;
633 if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
634 RTDesc.DestBlend = RenderTargetBlendDesc{}.DestBlend;
635 if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
636 RTDesc.BlendOp = RenderTargetBlendDesc{}.BlendOp;
637
638 if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
639 RTDesc.SrcBlendAlpha = RenderTargetBlendDesc{}.SrcBlendAlpha;
640 if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
641 RTDesc.DestBlendAlpha = RenderTargetBlendDesc{}.DestBlendAlpha;
642 if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
643 RTDesc.BlendOpAlpha = RenderTargetBlendDesc{}.BlendOpAlpha;
644 }
645
646 if (!LogicOpEnable)
647 RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp;
648 }
649 }
650 #undef LOG_PSO_ERROR_AND_THROW
506 #endif
507
508 ImmutableSamplers[i] = SrcSmplr;
509 ImmutableSamplers[i].SamplerOrTextureName = MemPool.CopyString(SrcSmplr.SamplerOrTextureName);
510 }
511 }
512 }
513
514 protected:
515 size_t m_ShaderResourceLayoutHash = 0; ///< Hash computed from the shader resource layout
516
517 Uint32* m_pStrides = nullptr;
518 Uint8 m_BufferSlotsUsed = 0;
519
520 Uint8 m_NumShaderStages = 0; ///< Number of shader stages in this PSO
521
522 /// Array of shader types for every shader stage used by this PSO
523 std::array<SHADER_TYPE, MAX_SHADERS_IN_PIPELINE> m_ShaderStageTypes = {};
524
525 RefCntAutoPtr<IRenderPass> m_pRenderPass; ///< Strong reference to the render pass object
526
527 GraphicsPipelineDesc* m_pGraphicsPipelineDesc = nullptr;
651528 };
652529
653530 } // namespace Diligent
3131
3232 #include <vector>
3333
34 #include "Atomics.hpp"
3435 #include "ShaderResourceVariable.h"
3536 #include "PipelineState.h"
3637 #include "StringTools.hpp"
113114 return AllowedTypeBits;
114115 }
115116
116 inline Int32 FindStaticSampler(const StaticSamplerDesc* StaticSamplers,
117 Uint32 NumStaticSamplers,
118 SHADER_TYPE ShaderType,
119 const char* ResourceName,
120 const char* SamplerSuffix)
121 {
122 for (Uint32 s = 0; s < NumStaticSamplers; ++s)
123 {
124 const auto& StSam = StaticSamplers[s];
117 inline Int32 FindImmutableSampler(const ImmutableSamplerDesc* ImtblSamplers,
118 Uint32 NumImtblSamplers,
119 SHADER_TYPE ShaderType,
120 const char* ResourceName,
121 const char* SamplerSuffix)
122 {
123 for (Uint32 s = 0; s < NumImtblSamplers; ++s)
124 {
125 const auto& StSam = ImtblSamplers[s];
125126 if (((StSam.ShaderStages & ShaderType) != 0) && StreqSuff(ResourceName, StSam.SamplerOrTextureName, SamplerSuffix))
126127 return s;
127128 }
211212 inline const char* GetResourceTypeName<BUFFER_VIEW_TYPE>()
212213 {
213214 return "buffer view";
215 }
216
217 inline RESOURCE_DIMENSION GetResourceViewDimension(const ITextureView* pTexView)
218 {
219 VERIFY_EXPR(pTexView != nullptr);
220 return pTexView->GetDesc().TextureDim;
221 }
222
223 inline RESOURCE_DIMENSION GetResourceViewDimension(const IBufferView* /*pBuffView*/)
224 {
225 return RESOURCE_DIM_BUFFER;
226 }
227
228 inline Uint32 GetResourceSampleCount(const ITextureView* pTexView)
229 {
230 VERIFY_EXPR(pTexView != nullptr);
231 return const_cast<ITextureView*>(pTexView)->GetTexture()->GetDesc().SampleCount;
232 }
233
234 inline Uint32 GetResourceSampleCount(const IBufferView* /*pBuffView*/)
235 {
236 return 0;
214237 }
215238
216239 template <typename ResourceAttribsType,
253276
254277 if (!IsExpectedViewType)
255278 {
256 std::string ExpectedViewTypeName;
257
258279 std::stringstream ss;
259280 ss << "Error binding " << ExpectedResourceType << " '" << pViewImpl->GetDesc().Name << "' to variable '"
260281 << Attribs.GetPrintName(ArrayIndex) << '\'';
278299
279300 BindingOK = false;
280301 }
302
303 const auto ExpectedResourceDim = Attribs.GetResourceDimension();
304 if (ExpectedResourceDim != RESOURCE_DIM_UNDEFINED)
305 {
306 auto ResourceDim = GetResourceViewDimension(pViewImpl);
307 if (ResourceDim != ExpectedResourceDim)
308 {
309 LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '",
310 Attribs.GetPrintName(ArrayIndex), "': incorrect resource dimension: ",
311 GetResourceDimString(ExpectedResourceDim), " is expected, but the actual dimension is ",
312 GetResourceDimString(ResourceDim));
313
314 BindingOK = false;
315 }
316
317 if (ResourceDim == RESOURCE_DIM_TEX_2D || ResourceDim == RESOURCE_DIM_TEX_2D_ARRAY)
318 {
319 auto SampleCount = GetResourceSampleCount(pViewImpl);
320 auto IsMS = Attribs.IsMultisample();
321 if (IsMS && SampleCount == 1)
322 {
323 LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '",
324 Attribs.GetPrintName(ArrayIndex), "': multisample texture is expected.");
325 BindingOK = false;
326 }
327 else if (!IsMS && SampleCount > 1)
328 {
329 LOG_ERROR_MESSAGE("Error binding ", ExpectedResourceType, " '", pViewImpl->GetDesc().Name, "' to variable '",
330 Attribs.GetPrintName(ArrayIndex), "': single-sample texture is expected.");
331 BindingOK = false;
332 }
333 }
334 }
281335 }
282336
283337 if (VarType != SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC && pCachedView != nullptr && pCachedView != pViewImpl)
284338 {
285 auto VarTypeStr = GetShaderVariableTypeLiteralName(VarType);
339 const auto* VarTypeStr = GetShaderVariableTypeLiteralName(VarType);
340
286341 std::stringstream ss;
287342 ss << "Non-null resource '" << pCachedView->GetDesc().Name << "' is already bound to " << VarTypeStr
288343 << " shader variable '" << Attribs.GetPrintName(ArrayIndex) << '\'';
304359
305360 BindingOK = false;
306361 }
362
307363 return BindingOK;
308364 }
309365
339395 struct ShaderVariableBase : public ResourceVariableBaseInterface
340396 {
341397 ShaderVariableBase(ResourceLayoutType& ParentResLayout) :
342 m_ParentResLayout(ParentResLayout)
398 m_ParentResLayout{ParentResLayout}
343399 {
344400 }
345401
2929 /// \file
3030 /// Implementation of the Diligent::TextureBase template class
3131
32 #include <memory>
33
3234 #include "Texture.h"
3335 #include "GraphicsTypes.h"
3436 #include "DeviceObjectBase.hpp"
3537 #include "GraphicsAccessories.hpp"
3638 #include "STDAllocator.hpp"
3739 #include "FormatString.hpp"
38 #include <memory>
3940
4041 namespace Diligent
4142 {
2929 /// \file
3030 /// Diligent API information
3131
32 #define DILIGENT_API_VERSION 240074
32 #define DILIGENT_API_VERSION 240078
3333
3434 #include "../../../Primitives/interface/BasicTypes.h"
3535
3838 /// Diligent API Info. This tructure can be used to verify API compatibility.
3939 struct APIInfo
4040 {
41 size_t StructSize DEFAULT_INITIALIZER(0);
42 int APIVersion DEFAULT_INITIALIZER(0);
43 size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0);
44 size_t BlendStateDescSize DEFAULT_INITIALIZER(0);
45 size_t BufferDescSize DEFAULT_INITIALIZER(0);
46 size_t BufferDataSize DEFAULT_INITIALIZER(0);
47 size_t BufferFormatSize DEFAULT_INITIALIZER(0);
48 size_t BufferViewDescSize DEFAULT_INITIALIZER(0);
49 size_t StencilOpDescSize DEFAULT_INITIALIZER(0);
50 size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0);
51 size_t SamplerCapsSize DEFAULT_INITIALIZER(0);
52 size_t TextureCapsSize DEFAULT_INITIALIZER(0);
53 size_t DeviceCapsSize DEFAULT_INITIALIZER(0);
54 size_t DrawAttribsSize DEFAULT_INITIALIZER(0);
55 size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0);
56 size_t ViewportSize DEFAULT_INITIALIZER(0);
57 size_t RectSize DEFAULT_INITIALIZER(0);
58 size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0);
59 size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0);
60 size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0);
61 size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0);
62 size_t SwapChainDescSize DEFAULT_INITIALIZER(0);
63 size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0);
64 size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0);
65 size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0);
66 size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0);
67 size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0);
68 size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0);
69 size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0);
70 size_t BoxSize DEFAULT_INITIALIZER(0);
71 size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0);
72 size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0);
73 size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0);
74 size_t StateTransitionDescSize DEFAULT_INITIALIZER(0);
75 size_t LayoutElementSize DEFAULT_INITIALIZER(0);
76 size_t InputLayoutDescSize DEFAULT_INITIALIZER(0);
77 size_t SampleDescSize DEFAULT_INITIALIZER(0);
78 size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0);
79 size_t StaticSamplerDescSize DEFAULT_INITIALIZER(0);
80 size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0);
81 size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0);
82 size_t ComputePipelineDescSize DEFAULT_INITIALIZER(0);
83 size_t PipelineStateDescSize DEFAULT_INITIALIZER(0);
84 size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0);
85 size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0);
86 size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0);
87 size_t SamplerDescSize DEFAULT_INITIALIZER(0);
88 size_t ShaderDescSize DEFAULT_INITIALIZER(0);
89 size_t ShaderMacroSize DEFAULT_INITIALIZER(0);
90 size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0);
91 size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0);
92 size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0);
93 size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0);
94 size_t TextureDescSize DEFAULT_INITIALIZER(0);
95 size_t TextureSubResDataSize DEFAULT_INITIALIZER(0);
96 size_t TextureDataSize DEFAULT_INITIALIZER(0);
97 size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0);
98 size_t TextureViewDescSize DEFAULT_INITIALIZER(0);
41 size_t StructSize DEFAULT_INITIALIZER(0);
42 int APIVersion DEFAULT_INITIALIZER(0);
43 size_t RenderTargetBlendDescSize DEFAULT_INITIALIZER(0);
44 size_t BlendStateDescSize DEFAULT_INITIALIZER(0);
45 size_t BufferDescSize DEFAULT_INITIALIZER(0);
46 size_t BufferDataSize DEFAULT_INITIALIZER(0);
47 size_t BufferFormatSize DEFAULT_INITIALIZER(0);
48 size_t BufferViewDescSize DEFAULT_INITIALIZER(0);
49 size_t StencilOpDescSize DEFAULT_INITIALIZER(0);
50 size_t DepthStencilStateDescSize DEFAULT_INITIALIZER(0);
51 size_t SamplerCapsSize DEFAULT_INITIALIZER(0);
52 size_t TextureCapsSize DEFAULT_INITIALIZER(0);
53 size_t DeviceCapsSize DEFAULT_INITIALIZER(0);
54 size_t DrawAttribsSize DEFAULT_INITIALIZER(0);
55 size_t DispatchComputeAttribsSize DEFAULT_INITIALIZER(0);
56 size_t ViewportSize DEFAULT_INITIALIZER(0);
57 size_t RectSize DEFAULT_INITIALIZER(0);
58 size_t CopyTextureAttribsSize DEFAULT_INITIALIZER(0);
59 size_t DeviceObjectAttribsSize DEFAULT_INITIALIZER(0);
60 size_t GraphicsAdapterInfoSize DEFAULT_INITIALIZER(0);
61 size_t DisplayModeAttribsSize DEFAULT_INITIALIZER(0);
62 size_t SwapChainDescSize DEFAULT_INITIALIZER(0);
63 size_t FullScreenModeDescSize DEFAULT_INITIALIZER(0);
64 size_t EngineCreateInfoSize DEFAULT_INITIALIZER(0);
65 size_t EngineGLCreateInfoSize DEFAULT_INITIALIZER(0);
66 size_t EngineD3D11CreateInfoSize DEFAULT_INITIALIZER(0);
67 size_t EngineD3D12CreateInfoSize DEFAULT_INITIALIZER(0);
68 size_t EngineVkCreateInfoSize DEFAULT_INITIALIZER(0);
69 size_t EngineMtlCreateInfoSize DEFAULT_INITIALIZER(0);
70 size_t BoxSize DEFAULT_INITIALIZER(0);
71 size_t TextureFormatAttribsSize DEFAULT_INITIALIZER(0);
72 size_t TextureFormatInfoSize DEFAULT_INITIALIZER(0);
73 size_t TextureFormatInfoExtSize DEFAULT_INITIALIZER(0);
74 size_t StateTransitionDescSize DEFAULT_INITIALIZER(0);
75 size_t LayoutElementSize DEFAULT_INITIALIZER(0);
76 size_t InputLayoutDescSize DEFAULT_INITIALIZER(0);
77 size_t SampleDescSize DEFAULT_INITIALIZER(0);
78 size_t ShaderResourceVariableDescSize DEFAULT_INITIALIZER(0);
79 size_t ImmutableSamplerDescSize DEFAULT_INITIALIZER(0);
80 size_t PipelineResourceLayoutDescSize DEFAULT_INITIALIZER(0);
81 size_t GraphicsPipelineDescSize DEFAULT_INITIALIZER(0);
82 size_t GraphicsPipelineStateCreateInfoSize DEFAULT_INITIALIZER(0);
83 size_t ComputePipelineStateCreateInfoSize DEFAULT_INITIALIZER(0);
84 size_t PipelineStateDescSize DEFAULT_INITIALIZER(0);
85 size_t RasterizerStateDescSize DEFAULT_INITIALIZER(0);
86 size_t ResourceMappingEntrySize DEFAULT_INITIALIZER(0);
87 size_t ResourceMappingDescSize DEFAULT_INITIALIZER(0);
88 size_t SamplerDescSize DEFAULT_INITIALIZER(0);
89 size_t ShaderDescSize DEFAULT_INITIALIZER(0);
90 size_t ShaderMacroSize DEFAULT_INITIALIZER(0);
91 size_t ShaderCreateInfoSize DEFAULT_INITIALIZER(0);
92 size_t ShaderResourceDescSize DEFAULT_INITIALIZER(0);
93 size_t DepthStencilClearValueSize DEFAULT_INITIALIZER(0);
94 size_t OptimizedClearValueSize DEFAULT_INITIALIZER(0);
95 size_t TextureDescSize DEFAULT_INITIALIZER(0);
96 size_t TextureSubResDataSize DEFAULT_INITIALIZER(0);
97 size_t TextureDataSize DEFAULT_INITIALIZER(0);
98 size_t MappedTextureSubresourceSize DEFAULT_INITIALIZER(0);
99 size_t TextureViewDescSize DEFAULT_INITIALIZER(0);
99100 };
100101 typedef struct APIInfo APIInfo;
101102
104104 /// when it is created, since it cannot be changed after creation. \n
105105 /// D3D11 Counterpart: D3D11_USAGE_IMMUTABLE. OpenGL counterpart: GL_STATIC_DRAW
106106 /// \remarks Static buffers do not allow CPU access and must use CPU_ACCESS_NONE flag.
107 USAGE_STATIC = 0,
107 USAGE_IMMUTABLE = 0,
108108
109109 /// A resource that requires read and write access by the GPU and can also be occasionally
110110 /// written by the CPU. \n
212212 /// - TextureViewDesc to describe texture view type
213213 DILIGENT_TYPED_ENUM(RESOURCE_DIMENSION, Uint8)
214214 {
215 RESOURCE_DIM_UNDEFINED = 0, ///< Texture type undefined
216 RESOURCE_DIM_BUFFER, ///< Buffer
217 RESOURCE_DIM_TEX_1D, ///< One-dimensional texture
218 RESOURCE_DIM_TEX_1D_ARRAY, ///< One-dimensional texture array
219 RESOURCE_DIM_TEX_2D, ///< Two-dimensional texture
220 RESOURCE_DIM_TEX_2D_ARRAY, ///< Two-dimensional texture array
221 RESOURCE_DIM_TEX_3D, ///< Three-dimensional texture
222 RESOURCE_DIM_TEX_CUBE, ///< Cube-map texture
223 RESOURCE_DIM_TEX_CUBE_ARRAY, ///< Cube-map array texture
224 RESOURCE_DIM_NUM_DIMENSIONS ///< Helper value that stores the total number of texture types in the enumeration
215 RESOURCE_DIM_UNDEFINED = 0, ///< Texture type undefined
216 RESOURCE_DIM_BUFFER, ///< Buffer
217 RESOURCE_DIM_TEX_1D, ///< One-dimensional texture
218 RESOURCE_DIM_TEX_1D_ARRAY, ///< One-dimensional texture array
219 RESOURCE_DIM_TEX_2D, ///< Two-dimensional texture
220 RESOURCE_DIM_TEX_2D_ARRAY, ///< Two-dimensional texture array
221 RESOURCE_DIM_TEX_3D, ///< Three-dimensional texture
222 RESOURCE_DIM_TEX_CUBE, ///< Cube-map texture
223 RESOURCE_DIM_TEX_CUBE_ARRAY, ///< Cube-map array texture
224 RESOURCE_DIM_NUM_DIMENSIONS ///< Helper value that stores the total number of texture types in the enumeration
225225 };
226226
227227 /// Texture view type
15161516 /// Indicates if device supports separable programs
15171517 DEVICE_FEATURE_STATE SeparablePrograms DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
15181518
1519 /// Indicates if device supports resource queries from shader objects.
1520
1521 /// \ note This feature indicates if IShader::GetResourceCount() and IShader::GetResourceDesc() methods
1522 /// can be used to query the list of resources of individual shader objects.
1523 /// Shader variable queries from pipeline state and shader resource binding objects are always
1524 /// available.
1525 ///
1526 /// The feature is always enabled in Direct3D11, Direct3D12 and Vulkan. It is enabled in
1527 /// OpenGL when separable programs are available, and it is always disabled in Metal.
1528 DEVICE_FEATURE_STATE ShaderResourceQueries DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
1529
15191530 /// Indicates if device supports indirect draw commands
15201531 DEVICE_FEATURE_STATE IndirectRendering DEFAULT_INITIALIZER(DEVICE_FEATURE_STATE_DISABLED);
15211532
16201631
16211632 explicit DeviceFeatures(DEVICE_FEATURE_STATE State) noexcept :
16221633 SeparablePrograms {State},
1634 ShaderResourceQueries {State},
16231635 IndirectRendering {State},
16241636 WireframeFill {State},
16251637 MultithreadedResourceCreation {State},
16521664 UniformBuffer8BitAccess {State}
16531665 {
16541666 # if defined(_MSC_VER) && defined(_WIN64)
1655 static_assert(sizeof(*this) == 31, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
1667 static_assert(sizeof(*this) == 32, "Did you add a new feature to DeviceFeatures? Please handle its status above.");
16561668 # endif
16571669 }
16581670 #endif
17111723
17121724 /// The amount of local video memory that is inaccessible by CPU, in bytes.
17131725
1714 /// \note Device-local memory is where USAGE_DEFAULT and USAGE_STATIC resources
1726 /// \note Device-local memory is where USAGE_DEFAULT and USAGE_IMMUTABLE resources
17151727 /// are typically allocated.
17161728 ///
17171729 /// On some devices it may not be possible to query the memory size,
18801892 /// provide additional runtime checking, validation, and logging
18811893 /// functionality while possibly incurring performance penalties
18821894 bool CreateDebugContext DEFAULT_INITIALIZER(false);
1895
1896 /// Force using non-separable programs.
1897
1898 /// Setting this to true is typically needed for testing purposes only.
1899 bool ForceNonSeparablePrograms DEFAULT_INITIALIZER(false);
18831900 };
18841901 typedef struct EngineGLCreateInfo EngineGLCreateInfo;
18851902
178178
179179 /// Layout description
180180
181 /// This structure is used by IRenderDevice::CreatePipelineState().
181 /// This structure is used by IRenderDevice::CreateGraphicsPipelineState().
182182 struct InputLayoutDesc
183183 {
184184 /// Array of layout elements
9595 typedef struct ShaderResourceVariableDesc ShaderResourceVariableDesc;
9696
9797
98 /// Static sampler description
99 struct StaticSamplerDesc
100 {
101 /// Shader stages that this static sampler applies to. More than one shader stage can be specified.
98 /// Immutable sampler description.
99
100 /// An immutable sampler is compiled into the pipeline state and can't be changed.
101 /// It is generally more efficient than a regular sampler and should be used
102 /// whenever possible.
103 struct ImmutableSamplerDesc
104 {
105 /// Shader stages that this immutable sampler applies to. More than one shader stage can be specified.
102106 SHADER_TYPE ShaderStages DEFAULT_INITIALIZER(SHADER_TYPE_UNKNOWN);
103107
104108 /// The name of the sampler itself or the name of the texture variable that
105 /// this static sampler is assigned to if combined texture samplers are used.
109 /// this immutable sampler is assigned to if combined texture samplers are used.
106110 const Char* SamplerOrTextureName DEFAULT_INITIALIZER(nullptr);
107111
108112 /// Sampler description
109113 struct SamplerDesc Desc;
110114
111115 #if DILIGENT_CPP_INTERFACE
112 StaticSamplerDesc()noexcept{}
113
114 StaticSamplerDesc(SHADER_TYPE _ShaderStages,
115 const Char* _SamplerOrTextureName,
116 const SamplerDesc& _Desc)noexcept :
116 ImmutableSamplerDesc()noexcept{}
117
118 ImmutableSamplerDesc(SHADER_TYPE _ShaderStages,
119 const Char* _SamplerOrTextureName,
120 const SamplerDesc& _Desc)noexcept :
117121 ShaderStages {_ShaderStages },
118122 SamplerOrTextureName{_SamplerOrTextureName},
119123 Desc {_Desc }
120124 {}
121125 #endif
122126 };
123 typedef struct StaticSamplerDesc StaticSamplerDesc;
127 typedef struct ImmutableSamplerDesc ImmutableSamplerDesc;
124128
125129 /// Pipeline layout description
126130 struct PipelineResourceLayoutDesc
128132 /// Default shader resource variable type. This type will be used if shader
129133 /// variable description is not found in the Variables array
130134 /// or if Variables == nullptr
131 SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType DEFAULT_INITIALIZER(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
135 SHADER_RESOURCE_VARIABLE_TYPE DefaultVariableType DEFAULT_INITIALIZER(SHADER_RESOURCE_VARIABLE_TYPE_STATIC);
132136
133137 /// Number of elements in Variables array
134 Uint32 NumVariables DEFAULT_INITIALIZER(0);
138 Uint32 NumVariables DEFAULT_INITIALIZER(0);
135139
136140 /// Array of shader resource variable descriptions
137 const ShaderResourceVariableDesc* Variables DEFAULT_INITIALIZER(nullptr);
141 const ShaderResourceVariableDesc* Variables DEFAULT_INITIALIZER(nullptr);
138142
139 /// Number of static samplers in StaticSamplers array
140 Uint32 NumStaticSamplers DEFAULT_INITIALIZER(0);
143 /// Number of immutable samplers in ImmutableSamplers array
144 Uint32 NumImmutableSamplers DEFAULT_INITIALIZER(0);
141145
142 /// Array of static sampler descriptions
143 const StaticSamplerDesc* StaticSamplers DEFAULT_INITIALIZER(nullptr);
146 /// Array of immutable sampler descriptions
147 const ImmutableSamplerDesc* ImmutableSamplers DEFAULT_INITIALIZER(nullptr);
144148 };
145149 typedef struct PipelineResourceLayoutDesc PipelineResourceLayoutDesc;
146150
150154 /// This structure describes the graphics pipeline state and is part of the PipelineStateDesc structure.
151155 struct GraphicsPipelineDesc
152156 {
153 /// Vertex shader to be used with the pipeline.
154 IShader* pVS DEFAULT_INITIALIZER(nullptr);
155
156 /// Pixel shader to be used with the pipeline.
157 IShader* pPS DEFAULT_INITIALIZER(nullptr);
158
159 /// Domain shader to be used with the pipeline.
160 IShader* pDS DEFAULT_INITIALIZER(nullptr);
161
162 /// Hull shader to be used with the pipeline.
163 IShader* pHS DEFAULT_INITIALIZER(nullptr);
164
165 /// Geometry shader to be used with the pipeline.
166 IShader* pGS DEFAULT_INITIALIZER(nullptr);
167
168 /// Amplification shader to be used with the pipeline.
169 IShader* pAS DEFAULT_INITIALIZER(nullptr);
170
171 /// Mesh shader to be used with the pipeline.
172 IShader* pMS DEFAULT_INITIALIZER(nullptr);
173
174 //D3D12_STREAM_OUTPUT_DESC StreamOutput;
175
176157 /// Blend state description.
177158 BlendStateDesc BlendDesc;
178159
347328 /// Pipeline layout description
348329 PipelineResourceLayoutDesc ResourceLayout;
349330
350 /// Graphics pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_GRAPHICS or PIPELINE_TYPE_MESH
351 GraphicsPipelineDesc GraphicsPipeline;
352
353 /// Compute pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_COMPUTE
354 ComputePipelineDesc ComputePipeline;
355
356 // TODO (AZ): use pointer
357 /// Ray tracing pipeline state description. This memeber is ignored if PipelineType is not PIPELINE_TYPE_RAY_TRACING.
358 RayTracingPipelineDesc RayTracingPipeline;
359
360331 #if DILIGENT_CPP_INTERFACE
361332 bool IsAnyGraphicsPipeline() const { return PipelineType == PIPELINE_TYPE_GRAPHICS || PipelineType == PIPELINE_TYPE_MESH; }
362 bool IsComputePipeline () const { return PipelineType == PIPELINE_TYPE_COMPUTE; }
333 bool IsComputePipeline() const { return PipelineType == PIPELINE_TYPE_COMPUTE; }
363334 #endif
364335 };
365336 typedef struct PipelineStateDesc PipelineStateDesc;
369340 DILIGENT_TYPED_ENUM(PSO_CREATE_FLAGS, Uint32)
370341 {
371342 /// Null flag.
372 PSO_CREATE_FLAG_NONE = 0x00,
343 PSO_CREATE_FLAG_NONE = 0x00,
373344
374345 /// Ignore missing variables.
375346
377348 /// provided as part of the pipeline resource layout description
378349 /// that is not found in any of the designated shader stages.
379350 /// Use this flag to silence these warnings.
380 PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES = 0x01,
381
382 /// Ignore missing static samplers.
383
384 /// By default, the engine outputs a warning for every static sampler
351 PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES = 0x01,
352
353 /// Ignore missing immutable samplers.
354
355 /// By default, the engine outputs a warning for every immutable sampler
385356 /// provided as part of the pipeline resource layout description
386357 /// that is not found in any of the designated shader stages.
387358 /// Use this flag to silence these warnings.
388 PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS = 0x02,
359 PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS = 0x02,
389360 };
390361 DEFINE_FLAG_ENUM_OPERATORS(PSO_CREATE_FLAGS);
391362
397368 PipelineStateDesc PSODesc;
398369
399370 /// Pipeline state creation flags, see Diligent::PSO_CREATE_FLAGS.
400 PSO_CREATE_FLAGS Flags DEFAULT_INITIALIZER(PSO_CREATE_FLAG_NONE);
371 PSO_CREATE_FLAGS Flags DEFAULT_INITIALIZER(PSO_CREATE_FLAG_NONE);
401372 };
402373 typedef struct PipelineStateCreateInfo PipelineStateCreateInfo;
374
375
376 /// Graphics pipeline state creation attributes
377 struct GraphicsPipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo)
378
379 /// Graphics pipeline state description.
380 GraphicsPipelineDesc GraphicsPipeline;
381
382 /// Vertex shader to be used with the pipeline.
383 IShader* pVS DEFAULT_INITIALIZER(nullptr);
384
385 /// Pixel shader to be used with the pipeline.
386 IShader* pPS DEFAULT_INITIALIZER(nullptr);
387
388 /// Domain shader to be used with the pipeline.
389 IShader* pDS DEFAULT_INITIALIZER(nullptr);
390
391 /// Hull shader to be used with the pipeline.
392 IShader* pHS DEFAULT_INITIALIZER(nullptr);
393
394 /// Geometry shader to be used with the pipeline.
395 IShader* pGS DEFAULT_INITIALIZER(nullptr);
396
397 /// Amplification shader to be used with the pipeline.
398 IShader* pAS DEFAULT_INITIALIZER(nullptr);
399
400 /// Mesh shader to be used with the pipeline.
401 IShader* pMS DEFAULT_INITIALIZER(nullptr);
402 };
403 typedef struct GraphicsPipelineStateCreateInfo GraphicsPipelineStateCreateInfo;
404
405
406 /// Compute pipeline state description.
407 struct ComputePipelineStateCreateInfo DILIGENT_DERIVE(PipelineStateCreateInfo)
408
409 /// Compute shader to be used with the pipeline
410 IShader* pCS DEFAULT_INITIALIZER(nullptr);
411
412 #if DILIGENT_CPP_INTERFACE
413 ComputePipelineStateCreateInfo() noexcept
414 {
415 PSODesc.PipelineType = PIPELINE_TYPE_COMPUTE;
416 }
417 #endif
418 };
419 typedef struct ComputePipelineStateCreateInfo ComputePipelineStateCreateInfo;
420
403421
404422 // {06084AE5-6A71-4FE8-84B9-395DD489A28C}
405423 static const struct INTERFACE_ID IID_PipelineState =
418436 DILIGENT_BEGIN_INTERFACE(IPipelineState, IDeviceObject)
419437 {
420438 #if DILIGENT_CPP_INTERFACE
421 /// Returns the blend state description used to create the object
422 virtual const PipelineStateDesc& METHOD(GetDesc)()const override = 0;
423 #endif
424
439 /// Returns the pipeline description used to create the object
440 virtual const PipelineStateDesc& METHOD(GetDesc)() const override = 0;
441 #endif
442
443 /// Returns the graphics pipeline description used to create the object.
444 /// This method must only be called for a graphics or mesh pipeline.
445 VIRTUAL const GraphicsPipelineDesc REF METHOD(GetGraphicsPipelineDesc)(THIS) CONST PURE;
425446
426447 /// Binds resources for all shaders in the pipeline state
427448
511532
512533 # define IPipelineState_GetDesc(This) (const struct PipelineStateDesc*)IDeviceObject_GetDesc(This)
513534
535 # define IPipelineState_GetGraphicsPipelineDesc(This) CALL_IFACE_METHOD(PipelineState, GetGraphicsPipelineDesc, This)
514536 # define IPipelineState_BindStaticResources(This, ...) CALL_IFACE_METHOD(PipelineState, BindStaticResources, This, __VA_ARGS__)
515537 # define IPipelineState_GetStaticVariableCount(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableCount, This, __VA_ARGS__)
516538 # define IPipelineState_GetStaticVariableByName(This, ...) CALL_IFACE_METHOD(PipelineState, GetStaticVariableByName, This, __VA_ARGS__)
7777 /// \param [in] BuffDesc - Buffer description, see Diligent::BufferDesc for details.
7878 /// \param [in] pBuffData - Pointer to Diligent::BufferData structure that describes
7979 /// initial buffer data or nullptr if no data is provided.
80 /// Static buffers (USAGE_STATIC) must be initialized at creation time.
80 /// Immutable buffers (USAGE_IMMUTABLE) must be initialized at creation time.
8181 /// \param [out] ppBuffer - Address of the memory location where the pointer to the
8282 /// buffer interface will be stored. The function calls AddRef(),
8383 /// so that the new buffer will contain one reference and must be
108108 /// \param [in] TexDesc - Texture description, see Diligent::TextureDesc for details.
109109 /// \param [in] pData - Pointer to Diligent::TextureData structure that describes
110110 /// initial texture data or nullptr if no data is provided.
111 /// Static textures (USAGE_STATIC) must be initialized at creation time.
111 /// Immutable textures (USAGE_IMMUTABLE) must be initialized at creation time.
112112 ///
113113 /// \param [out] ppTexture - Address of the memory location where the pointer to the
114114 /// texture interface will be stored.
155155 const ResourceMappingDesc REF MappingDesc,
156156 IResourceMapping** ppMapping) PURE;
157157
158 /// Creates a new pipeline state object
159
160 /// \param [in] PSOCreateInfo - Pipeline state create info, see Diligent::PipelineStateCreateInfo for details.
158 /// Creates a new graphics pipeline state object
159
160 /// \param [in] PSOCreateInfo - Graphics pipeline state create info, see Diligent::GraphicsPipelineStateCreateInfo for details.
161161 /// \param [out] ppPipelineState - Address of the memory location where the pointer to the
162162 /// pipeline state interface will be stored.
163163 /// The function calls AddRef(), so that the new object will contain
164164 /// one reference.
165 VIRTUAL void METHOD(CreatePipelineState)(THIS_
166 const PipelineStateCreateInfo REF PSOCreateInfo,
167 IPipelineState** ppPipelineState) PURE;
168
165 VIRTUAL void METHOD(CreateGraphicsPipelineState)(THIS_
166 const GraphicsPipelineStateCreateInfo REF PSOCreateInfo,
167 IPipelineState** ppPipelineState) PURE;
168
169 /// Creates a new compute pipeline state object
170
171 /// \param [in] PSOCreateInfo - Compute pipeline state create info, see Diligent::ComputePipelineStateCreateInfo for details.
172 /// \param [out] ppPipelineState - Address of the memory location where the pointer to the
173 /// pipeline state interface will be stored.
174 /// The function calls AddRef(), so that the new object will contain
175 /// one reference.
176 VIRTUAL void METHOD(CreateComputePipelineState)(THIS_
177 const ComputePipelineStateCreateInfo REF PSOCreateInfo,
178 IPipelineState** ppPipelineState) PURE;
169179
170180 /// Creates a new fence object
171181
311321
312322 // clang-format off
313323
314 # define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__)
315 # define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__)
316 # define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__)
317 # define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__)
318 # define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__)
319 # define IRenderDevice_CreatePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreatePipelineState, This, __VA_ARGS__)
320 # define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__)
321 # define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__)
322 # define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This)
323 # define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__)
324 # define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt,This, __VA_ARGS__)
325 # define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__)
326 # define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This)
327 # define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This)
324 # define IRenderDevice_CreateBuffer(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateBuffer, This, __VA_ARGS__)
325 # define IRenderDevice_CreateShader(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateShader, This, __VA_ARGS__)
326 # define IRenderDevice_CreateTexture(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateTexture, This, __VA_ARGS__)
327 # define IRenderDevice_CreateSampler(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateSampler, This, __VA_ARGS__)
328 # define IRenderDevice_CreateResourceMapping(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateResourceMapping, This, __VA_ARGS__)
329 # define IRenderDevice_CreateGraphicsPipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateGraphicsPipelineState, This, __VA_ARGS__)
330 # define IRenderDevice_CreateComputePipelineState(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateComputePipelineState, This, __VA_ARGS__)
331 # define IRenderDevice_CreateFence(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateFence, This, __VA_ARGS__)
332 # define IRenderDevice_CreateQuery(This, ...) CALL_IFACE_METHOD(RenderDevice, CreateQuery, This, __VA_ARGS__)
333 # define IRenderDevice_GetDeviceCaps(This) CALL_IFACE_METHOD(RenderDevice, GetDeviceCaps, This)
334 # define IRenderDevice_GetTextureFormatInfo(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfo, This, __VA_ARGS__)
335 # define IRenderDevice_GetTextureFormatInfoExt(This, ...) CALL_IFACE_METHOD(RenderDevice, GetTextureFormatInfoExt, This, __VA_ARGS__)
336 # define IRenderDevice_ReleaseStaleResources(This, ...) CALL_IFACE_METHOD(RenderDevice, ReleaseStaleResources, This, __VA_ARGS__)
337 # define IRenderDevice_IdleGPU(This) CALL_IFACE_METHOD(RenderDevice, IdleGPU, This)
338 # define IRenderDevice_GetEngineFactory(This) CALL_IFACE_METHOD(RenderDevice, GetEngineFactory, This)
328339
329340 // clang-format on
330341
351351 SHADER_RESOURCE_TYPE_SAMPLER,
352352
353353 /// Input attachment in a render pass
354 SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT
354 SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT,
355
356 SHADER_RESOURCE_TYPE_LAST = SHADER_RESOURCE_TYPE_INPUT_ATTACHMENT
355357 };
356358 // clang-format on
357359
8686 INIT_STRUCTURE_SIZE(InputLayoutDesc);
8787 INIT_STRUCTURE_SIZE(SampleDesc);
8888 INIT_STRUCTURE_SIZE(ShaderResourceVariableDesc);
89 INIT_STRUCTURE_SIZE(StaticSamplerDesc);
89 INIT_STRUCTURE_SIZE(ImmutableSamplerDesc);
9090 INIT_STRUCTURE_SIZE(PipelineResourceLayoutDesc);
9191 INIT_STRUCTURE_SIZE(GraphicsPipelineDesc);
92 INIT_STRUCTURE_SIZE(ComputePipelineDesc);
92 INIT_STRUCTURE_SIZE(GraphicsPipelineStateCreateInfo);
93 INIT_STRUCTURE_SIZE(ComputePipelineStateCreateInfo);
9394 INIT_STRUCTURE_SIZE(PipelineStateDesc);
9495 INIT_STRUCTURE_SIZE(RasterizerStateDesc);
9596 INIT_STRUCTURE_SIZE(ResourceMappingEntry);
7373
7474 switch (Desc.Usage)
7575 {
76 case USAGE_STATIC:
76 case USAGE_IMMUTABLE:
7777 case USAGE_DEFAULT:
7878 VERIFY_BUFFER(Desc.CPUAccessFlags == CPU_ACCESS_NONE, "static and default buffers can't have any CPU access flags set.");
7979 break;
116116
117117 void ValidateBufferInitData(const BufferDesc& Desc, const BufferData* pBuffData)
118118 {
119 if (Desc.Usage == USAGE_STATIC && (pBuffData == nullptr || pBuffData->pData == nullptr))
120 LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as static buffers must be initialized at creation time.");
119 if (Desc.Usage == USAGE_IMMUTABLE && (pBuffData == nullptr || pBuffData->pData == nullptr))
120 LOG_BUFFER_ERROR_AND_THROW("initial data must not be null as immutable buffers must be initialized at creation time.");
121121
122122 if (Desc.Usage == USAGE_DYNAMIC && pBuffData != nullptr && pBuffData->pData != nullptr)
123123 LOG_BUFFER_ERROR_AND_THROW("initial data must be null for dynamic buffers.");
0 /*
1 * Copyright 2019-2020 Diligent Graphics LLC
2 * Copyright 2015-2019 Egor Yusov
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 * In no event and under no legal theory, whether in tort (including negligence),
17 * contract, or otherwise, unless required by applicable law (such as deliberate
18 * and grossly negligent acts) or agreed to in writing, shall any Contributor be
19 * liable for any damages, including any direct, indirect, special, incidental,
20 * or consequential damages of any character arising as a result of this License or
21 * out of the use or inability to use the software (including but not limited to damages
22 * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
23 * all other commercial damages or losses), even if such Contributor has been advised
24 * of the possibility of such damages.
25 */
26
27 #include "pch.h"
28 #include "PipelineStateBase.hpp"
29
30 namespace Diligent
31 {
32
33 #define LOG_PSO_ERROR_AND_THROW(...) LOG_ERROR_AND_THROW("Description of ", GetPipelineTypeString(PSODesc.PipelineType), " PSO '", PSODesc.Name, "' is invalid: ", ##__VA_ARGS__)
34
35 namespace
36 {
37
38 void ValidateRasterizerStateDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false)
39 {
40 const auto& RSDesc = GraphicsPipeline.RasterizerDesc;
41 if (RSDesc.FillMode == FILL_MODE_UNDEFINED)
42 LOG_PSO_ERROR_AND_THROW("RasterizerDesc.FillMode must not be FILL_MODE_UNDEFINED");
43 if (RSDesc.CullMode == CULL_MODE_UNDEFINED)
44 LOG_PSO_ERROR_AND_THROW("RasterizerDesc.CullMode must not be CULL_MODE_UNDEFINED");
45 }
46
47 void ValidateDepthStencilDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false)
48 {
49 const auto& DSSDesc = GraphicsPipeline.DepthStencilDesc;
50 if (DSSDesc.DepthEnable && DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN)
51 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.DepthFunc must not be COMPARISON_FUNC_UNKNOWN when depth is enabled");
52
53 auto CheckStencilOpDesc = [&](const StencilOpDesc& OpDesc, const char* FaceName) //
54 {
55 if (DSSDesc.StencilEnable)
56 {
57 if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
58 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
59 if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
60 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilDepthFailOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
61 if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
62 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilPassOp must not be STENCIL_OP_UNDEFINED when stencil is enabled");
63 if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
64 LOG_PSO_ERROR_AND_THROW("DepthStencilDesc.", FaceName, ".StencilFunc must not be COMPARISON_FUNC_UNKNOWN when stencil is enabled");
65 }
66 };
67 CheckStencilOpDesc(DSSDesc.FrontFace, "FrontFace");
68 CheckStencilOpDesc(DSSDesc.BackFace, "BackFace");
69 }
70
71 void CorrectDepthStencilDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept
72 {
73 auto& DSSDesc = GraphicsPipeline.DepthStencilDesc;
74 if (!DSSDesc.DepthEnable && DSSDesc.DepthFunc == COMPARISON_FUNC_UNKNOWN)
75 DSSDesc.DepthFunc = DepthStencilStateDesc{}.DepthFunc;
76
77 auto CorrectStencilOpDesc = [&](StencilOpDesc& OpDesc) //
78 {
79 if (!DSSDesc.StencilEnable)
80 {
81 if (OpDesc.StencilFailOp == STENCIL_OP_UNDEFINED)
82 OpDesc.StencilFailOp = StencilOpDesc{}.StencilFailOp;
83 if (OpDesc.StencilDepthFailOp == STENCIL_OP_UNDEFINED)
84 OpDesc.StencilDepthFailOp = StencilOpDesc{}.StencilDepthFailOp;
85 if (OpDesc.StencilPassOp == STENCIL_OP_UNDEFINED)
86 OpDesc.StencilPassOp = StencilOpDesc{}.StencilPassOp;
87 if (OpDesc.StencilFunc == COMPARISON_FUNC_UNKNOWN)
88 OpDesc.StencilFunc = StencilOpDesc{}.StencilFunc;
89 }
90 };
91 CorrectStencilOpDesc(DSSDesc.FrontFace);
92 CorrectStencilOpDesc(DSSDesc.BackFace);
93 }
94
95 void ValidateBlendStateDesc(const PipelineStateDesc& PSODesc, const GraphicsPipelineDesc& GraphicsPipeline) noexcept(false)
96 {
97 const auto& BlendDesc = GraphicsPipeline.BlendDesc;
98 for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
99 {
100 auto& RTDesc = BlendDesc.RenderTargets[rt];
101
102 const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
103 if (BlendEnable)
104 {
105 if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
106 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlend must not be BLEND_FACTOR_UNDEFINED");
107 if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
108 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlend must not be BLEND_FACTOR_UNDEFINED");
109 if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
110 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOp must not be BLEND_OPERATION_UNDEFINED");
111
112 if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
113 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].SrcBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
114 if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
115 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].DestBlendAlpha must not be BLEND_FACTOR_UNDEFINED");
116 if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
117 LOG_PSO_ERROR_AND_THROW("BlendDesc.RenderTargets[", rt, "].BlendOpAlpha must not be BLEND_OPERATION_UNDEFINED");
118 }
119 }
120 }
121
122 void CorrectBlendStateDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept
123 {
124 auto& BlendDesc = GraphicsPipeline.BlendDesc;
125 for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
126 {
127 auto& RTDesc = BlendDesc.RenderTargets[rt];
128 // clang-format off
129 const auto BlendEnable = RTDesc.BlendEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
130 const auto LogicOpEnable = RTDesc.LogicOperationEnable && (rt == 0 || (BlendDesc.IndependentBlendEnable && rt > 0));
131 // clang-format on
132 if (!BlendEnable)
133 {
134 if (RTDesc.SrcBlend == BLEND_FACTOR_UNDEFINED)
135 RTDesc.SrcBlend = RenderTargetBlendDesc{}.SrcBlend;
136 if (RTDesc.DestBlend == BLEND_FACTOR_UNDEFINED)
137 RTDesc.DestBlend = RenderTargetBlendDesc{}.DestBlend;
138 if (RTDesc.BlendOp == BLEND_OPERATION_UNDEFINED)
139 RTDesc.BlendOp = RenderTargetBlendDesc{}.BlendOp;
140
141 if (RTDesc.SrcBlendAlpha == BLEND_FACTOR_UNDEFINED)
142 RTDesc.SrcBlendAlpha = RenderTargetBlendDesc{}.SrcBlendAlpha;
143 if (RTDesc.DestBlendAlpha == BLEND_FACTOR_UNDEFINED)
144 RTDesc.DestBlendAlpha = RenderTargetBlendDesc{}.DestBlendAlpha;
145 if (RTDesc.BlendOpAlpha == BLEND_OPERATION_UNDEFINED)
146 RTDesc.BlendOpAlpha = RenderTargetBlendDesc{}.BlendOpAlpha;
147 }
148
149 if (!LogicOpEnable)
150 RTDesc.LogicOp = RenderTargetBlendDesc{}.LogicOp;
151 }
152 }
153
154 } // namespace
155
156 #define VALIDATE_SHADER_TYPE(Shader, ExpectedType, ShaderName) \
157 if (Shader != nullptr && Shader->GetDesc().ShaderType != ExpectedType) \
158 { \
159 LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(Shader->GetDesc().ShaderType), " is not a valid type for ", ShaderName, " shader"); \
160 }
161
162 void ValidateGraphicsPipelineCreateInfo(const GraphicsPipelineStateCreateInfo& CreateInfo) noexcept(false)
163 {
164 const auto& PSODesc = CreateInfo.PSODesc;
165 if (PSODesc.PipelineType != PIPELINE_TYPE_GRAPHICS && PSODesc.PipelineType != PIPELINE_TYPE_MESH)
166 LOG_PSO_ERROR_AND_THROW("Pipeline type must be GRAPHICS or MESH");
167
168 const auto& GraphicsPipeline = CreateInfo.GraphicsPipeline;
169
170 ValidateBlendStateDesc(PSODesc, GraphicsPipeline);
171 ValidateRasterizerStateDesc(PSODesc, GraphicsPipeline);
172 ValidateDepthStencilDesc(PSODesc, GraphicsPipeline);
173
174
175 if (PSODesc.PipelineType == PIPELINE_TYPE_GRAPHICS)
176 {
177 if (CreateInfo.pVS == nullptr)
178 LOG_ERROR_AND_THROW("Vertex shader must not be null");
179
180 DEV_CHECK_ERR(CreateInfo.pAS == nullptr && CreateInfo.pMS == nullptr, "Mesh shaders are not supported in graphics pipeline");
181 }
182 else if (PSODesc.PipelineType == PIPELINE_TYPE_MESH)
183 {
184 if (CreateInfo.pMS == nullptr)
185 LOG_ERROR_AND_THROW("Mesh shader must not be null");
186
187 DEV_CHECK_ERR(CreateInfo.pVS == nullptr && CreateInfo.pGS == nullptr && CreateInfo.pDS == nullptr && CreateInfo.pHS == nullptr,
188 "Vertex, geometry and tessellation shaders are not supported in a mesh pipeline");
189 DEV_CHECK_ERR(GraphicsPipeline.InputLayout.NumElements == 0, "Input layout is ignored in a mesh pipeline");
190 DEV_CHECK_ERR(GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_TRIANGLE_LIST ||
191 GraphicsPipeline.PrimitiveTopology == PRIMITIVE_TOPOLOGY_UNDEFINED,
192 "Primitive topology is ignored in a mesh pipeline, set it to undefined or keep default value (triangle list)");
193 }
194
195
196 VALIDATE_SHADER_TYPE(CreateInfo.pVS, SHADER_TYPE_VERTEX, "vertex")
197 VALIDATE_SHADER_TYPE(CreateInfo.pPS, SHADER_TYPE_PIXEL, "pixel")
198 VALIDATE_SHADER_TYPE(CreateInfo.pGS, SHADER_TYPE_GEOMETRY, "geometry")
199 VALIDATE_SHADER_TYPE(CreateInfo.pHS, SHADER_TYPE_HULL, "hull")
200 VALIDATE_SHADER_TYPE(CreateInfo.pDS, SHADER_TYPE_DOMAIN, "domain")
201 VALIDATE_SHADER_TYPE(CreateInfo.pAS, SHADER_TYPE_AMPLIFICATION, "amplification")
202 VALIDATE_SHADER_TYPE(CreateInfo.pMS, SHADER_TYPE_MESH, "mesh")
203
204
205 if (GraphicsPipeline.pRenderPass != nullptr)
206 {
207 if (GraphicsPipeline.NumRenderTargets != 0)
208 LOG_PSO_ERROR_AND_THROW("NumRenderTargets must be 0 when explicit render pass is used");
209 if (GraphicsPipeline.DSVFormat != TEX_FORMAT_UNKNOWN)
210 LOG_PSO_ERROR_AND_THROW("DSVFormat must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
211
212 for (Uint32 rt = 0; rt < MAX_RENDER_TARGETS; ++rt)
213 {
214 if (GraphicsPipeline.RTVFormats[rt] != TEX_FORMAT_UNKNOWN)
215 LOG_PSO_ERROR_AND_THROW("RTVFormats[", rt, "] must be TEX_FORMAT_UNKNOWN when explicit render pass is used");
216 }
217
218 const auto& RPDesc = GraphicsPipeline.pRenderPass->GetDesc();
219 if (GraphicsPipeline.SubpassIndex >= RPDesc.SubpassCount)
220 LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") exceeds the number of subpasses (", Uint32{RPDesc.SubpassCount}, ") in render pass '", RPDesc.Name, "'");
221 }
222 else
223 {
224 for (Uint32 rt = GraphicsPipeline.NumRenderTargets; rt < _countof(GraphicsPipeline.RTVFormats); ++rt)
225 {
226 auto RTVFmt = GraphicsPipeline.RTVFormats[rt];
227 if (RTVFmt != TEX_FORMAT_UNKNOWN)
228 {
229 LOG_ERROR_MESSAGE("Render target format (", GetTextureFormatAttribs(RTVFmt).Name, ") of unused slot ", rt,
230 " must be set to TEX_FORMAT_UNKNOWN");
231 }
232 }
233
234 if (GraphicsPipeline.SubpassIndex != 0)
235 LOG_PSO_ERROR_AND_THROW("Subpass index (", Uint32{GraphicsPipeline.SubpassIndex}, ") must be 0 when explicit render pass is not used");
236 }
237 }
238
239 void ValidateComputePipelineCreateInfo(const ComputePipelineStateCreateInfo& CreateInfo) noexcept(false)
240 {
241 const auto& PSODesc = CreateInfo.PSODesc;
242 if (PSODesc.PipelineType != PIPELINE_TYPE_COMPUTE)
243 LOG_PSO_ERROR_AND_THROW("Pipeline type must be COMPUTE");
244
245 if (CreateInfo.pCS == nullptr)
246 LOG_ERROR_AND_THROW("Compute shader must not be null");
247
248 VALIDATE_SHADER_TYPE(CreateInfo.pCS, SHADER_TYPE_COMPUTE, "compute");
249 }
250 #undef VALIDATE_SHADER_TYPE
251 #undef LOG_PSO_ERROR_AND_THROW
252
253 void CorrectGraphicsPipelineDesc(GraphicsPipelineDesc& GraphicsPipeline) noexcept
254 {
255 CorrectBlendStateDesc(GraphicsPipeline);
256 CorrectDepthStencilDesc(GraphicsPipeline);
257 }
258
259 } // namespace Diligent
7878 switch (Usage)
7979 {
8080 // clang-format off
81 case USAGE_STATIC: return D3D11_USAGE_IMMUTABLE;
81 case USAGE_IMMUTABLE: return D3D11_USAGE_IMMUTABLE;
8282 case USAGE_DEFAULT: return D3D11_USAGE_DEFAULT;
8383 case USAGE_DYNAMIC: return D3D11_USAGE_DYNAMIC;
8484 case USAGE_STAGING: return D3D11_USAGE_STAGING;
9292 switch (D3D11Usage)
9393 {
9494 // clang-format off
95 case D3D11_USAGE_IMMUTABLE: return USAGE_STATIC;
95 case D3D11_USAGE_IMMUTABLE: return USAGE_IMMUTABLE;
9696 case D3D11_USAGE_DEFAULT: return USAGE_DEFAULT;
9797 case D3D11_USAGE_DYNAMIC: return USAGE_DYNAMIC;
9898 case D3D11_USAGE_STAGING: return USAGE_STAGING;
3535 #include "ShaderResourceLayoutD3D11.hpp"
3636 #include "SRBMemoryAllocator.hpp"
3737 #include "RenderDeviceD3D11Impl.hpp"
38 #include "ShaderD3D11Impl.hpp"
3839
3940 namespace Diligent
4041 {
4748 public:
4849 using TPipelineStateBase = PipelineStateBase<IPipelineStateD3D11, RenderDeviceD3D11Impl>;
4950
50 PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
51 class RenderDeviceD3D11Impl* pDeviceD3D11,
52 const PipelineStateCreateInfo& CreateInfo);
51 PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
52 class RenderDeviceD3D11Impl* pDeviceD3D11,
53 const GraphicsPipelineStateCreateInfo& CreateInfo);
54 PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
55 class RenderDeviceD3D11Impl* pDeviceD3D11,
56 const ComputePipelineStateCreateInfo& CreateInfo);
5357 ~PipelineStateD3D11Impl();
5458
5559 virtual void DILIGENT_CALL_TYPE QueryInterface(const INTERFACE_ID& IID, IObject** ppInterface) override final;
116120
117121 const ShaderResourceLayoutD3D11& GetStaticResourceLayout(Uint32 s) const
118122 {
119 VERIFY_EXPR(s < m_NumShaders);
123 VERIFY_EXPR(s < GetNumShaderStages());
120124 return m_pStaticResourceLayouts[s];
121125 }
122126
123127 ShaderResourceCacheD3D11& GetStaticResourceCache(Uint32 s)
124128 {
125 VERIFY_EXPR(s < m_NumShaders);
129 VERIFY_EXPR(s < GetNumShaderStages());
126130 return m_pStaticResourceCaches[s];
127131 }
128132
129 void SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const;
133 const ShaderD3D11Impl* GetShaderByType(SHADER_TYPE ShaderType) const;
134 const ShaderD3D11Impl* GetShader(Uint32 Index) const;
135
136 void SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const;
130137
131138 private:
139 template <typename PSOCreateInfoType>
140 void InitInternalObjects(const PSOCreateInfoType& CreateInfo);
141
142 void InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
143 const std::vector<std::pair<SHADER_TYPE, ShaderD3D11Impl*>>& ShaderStages);
144
145 void Destruct();
146
132147 CComPtr<ID3D11BlendState> m_pd3d11BlendState;
133148 CComPtr<ID3D11RasterizerState> m_pd3d11RasterizerState;
134149 CComPtr<ID3D11DepthStencilState> m_pd3d11DepthStencilState;
135150 CComPtr<ID3D11InputLayout> m_pd3d11InputLayout;
136151
152 RefCntAutoPtr<ShaderD3D11Impl> m_pVS;
153 RefCntAutoPtr<ShaderD3D11Impl> m_pPS;
154 RefCntAutoPtr<ShaderD3D11Impl> m_pGS;
155 RefCntAutoPtr<ShaderD3D11Impl> m_pDS;
156 RefCntAutoPtr<ShaderD3D11Impl> m_pHS;
157 RefCntAutoPtr<ShaderD3D11Impl> m_pCS;
158
137159 // The caches are indexed by the shader order in the PSO, not shader index
138 ShaderResourceCacheD3D11* m_pStaticResourceCaches = nullptr;
139 ShaderResourceLayoutD3D11* m_pStaticResourceLayouts = nullptr;
160 ShaderResourceCacheD3D11* m_pStaticResourceCaches = nullptr; // [m_NumShaderStages]
161 ShaderResourceLayoutD3D11* m_pStaticResourceLayouts = nullptr; // [m_NumShaderStages]
140162
141163 // SRB memory allocator must be defined before the default shader res binding
142164 SRBMemoryAllocator m_SRBMemAllocator;
145167 // indexed by the shader type pipeline index (returned by GetShaderTypePipelineIndex)
146168 std::array<Int8, MAX_SHADERS_IN_PIPELINE> m_ResourceLayoutIndex = {-1, -1, -1, -1, -1};
147169
148 std::array<Uint16, MAX_SHADERS_IN_PIPELINE + 1> m_StaticSamplerOffsets = {};
149 struct StaticSamplerInfo
170 std::array<Uint16, MAX_SHADERS_IN_PIPELINE + 1> m_ImmutableSamplerOffsets = {};
171 struct ImmutableSamplerInfo
150172 {
151173 const D3DShaderResourceAttribs& Attribs;
152174 RefCntAutoPtr<ISampler> pSampler;
153 StaticSamplerInfo(const D3DShaderResourceAttribs& _Attribs,
154 RefCntAutoPtr<ISampler> _pSampler) :
175 ImmutableSamplerInfo(const D3DShaderResourceAttribs& _Attribs,
176 RefCntAutoPtr<ISampler> _pSampler) :
155177 // clang-format off
156178 Attribs {_Attribs},
157179 pSampler {std::move(_pSampler)}
158180 // clang-format on
159181 {}
160182 };
161 std::vector<StaticSamplerInfo, STDAllocatorRawMem<StaticSamplerInfo>> m_StaticSamplers;
183 std::vector<ImmutableSamplerInfo, STDAllocatorRawMem<ImmutableSamplerInfo>> m_ImmutableSamplers;
162184 };
163185
164186 } // namespace Diligent
6868 virtual void DILIGENT_CALL_TYPE CreateSampler(const SamplerDesc& SamplerDesc,
6969 ISampler** ppSampler) override final;
7070
71 /// Implementation of IRenderDevice::CreatePipelineState() in Direct3D11 backend.
72 virtual void DILIGENT_CALL_TYPE CreatePipelineState(const PipelineStateCreateInfo& PSOCreateInfo,
73 IPipelineState** ppPipelineState) override final;
71 /// Implementation of IRenderDevice::CreateGraphicsPipelineState() in Direct3D11 backend.
72 virtual void DILIGENT_CALL_TYPE CreateGraphicsPipelineState(const GraphicsPipelineStateCreateInfo& PSOCreateInfo,
73 IPipelineState** ppPipelineState) override final;
74
75 /// Implementation of IRenderDevice::CreateComputePipelineState() in Direct3D11 backend.
76 virtual void DILIGENT_CALL_TYPE CreateComputePipelineState(const ComputePipelineStateCreateInfo& PSOCreateInfo,
77 IPipelineState** ppPipelineState) override final;
7478
7579 /// Implementation of IRenderDevice::CreateFence() in Direct3D11 backend.
7680 virtual void DILIGENT_CALL_TYPE CreateFence(const FenceDesc& Desc,
131135 Uint64 GetCommandQueueMask() const { return Uint64{1}; }
132136
133137 private:
138 template <typename PSOCreateInfoType>
139 void CreatePipelineState(const PSOCreateInfoType& PSOCreateInfo, IPipelineState** ppPipelineState);
140
134141 virtual void TestTextureFormat(TEXTURE_FORMAT TexFormat) override final;
135142
136143 EngineD3D11CreateInfo m_EngineAttribs;
9999 }
100100
101101 private:
102 void Destruct();
103
102104 // The caches are indexed by the shader order in the PSO, not shader index
103105 ShaderResourceCacheD3D11* m_pBoundResourceCaches = nullptr;
104106 ShaderResourceLayoutD3D11* m_pResourceLayouts = nullptr;
5050 class ShaderResourceCacheD3D11
5151 {
5252 public:
53 ShaderResourceCacheD3D11()
53 ShaderResourceCacheD3D11() noexcept
5454 {}
5555
5656 ~ShaderResourceCacheD3D11();
4646 class ShaderResourceLayoutD3D11
4747 {
4848 public:
49 ShaderResourceLayoutD3D11(IObject& Owner,
50 std::shared_ptr<const ShaderResourcesD3D11> pSrcResources,
51 const PipelineResourceLayoutDesc& ResourceLayout,
52 const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes,
53 Uint32 NumVarTypes,
54 ShaderResourceCacheD3D11& ResourceCache,
55 IMemoryAllocator& ResCacheDataAllocator,
56 IMemoryAllocator& ResLayoutDataAllocator);
49 ShaderResourceLayoutD3D11(IObject& Owner,
50 ShaderResourceCacheD3D11& ResourceCache) noexcept :
51 m_Owner{Owner},
52 m_ResourceCache{ResourceCache}
53 {
54 }
55
56 void Initialize(std::shared_ptr<const ShaderResourcesD3D11> pSrcResources,
57 const PipelineResourceLayoutDesc& ResourceLayout,
58 const SHADER_RESOURCE_VARIABLE_TYPE* VarTypes,
59 Uint32 NumVarTypes,
60 IMemoryAllocator& ResCacheDataAllocator,
61 IMemoryAllocator& ResLayoutDataAllocator);
5762 ~ShaderResourceLayoutD3D11();
5863
5964 // clang-format off
6772 static size_t GetRequiredMemorySize(const ShaderResourcesD3D11& SrcResources,
6873 const PipelineResourceLayoutDesc& ResourceLayout,
6974 const SHADER_RESOURCE_VARIABLE_TYPE* AllowedVarTypes,
70 Uint32 NumAllowedTypes);
75 Uint32 NumAllowedTypes) noexcept;
7176
7277 void CopyResources(ShaderResourceCacheD3D11& DstCache) const;
7378
6161 LOG_ERROR_AND_THROW("Unified resources are not supported in Direct3D11");
6262 }
6363
64 if (m_Desc.Usage == USAGE_STATIC)
65 VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for static buffers");
64 if (m_Desc.Usage == USAGE_IMMUTABLE)
65 VERIFY(pBuffData != nullptr && pBuffData->pData != nullptr, "Initial data must not be null for immutable buffers");
6666
6767 if (m_Desc.BindFlags & BIND_UNIFORM_BUFFER)
6868 {
7474
7575 TDeviceContextBase::SetPipelineState(pPipelineStateD3D11, 0 /*Dummy*/);
7676 auto& Desc = pPipelineStateD3D11->GetDesc();
77 if (Desc.IsComputePipeline())
77 if (Desc.PipelineType == PIPELINE_TYPE_COMPUTE)
7878 {
7979 auto* pd3d11CS = pPipelineStateD3D11->GetD3D11ComputeShader();
8080 if (pd3d11CS == nullptr)
105105 COMMIT_SHADER(DS, DomainShader);
106106 #undef COMMIT_SHADER
107107
108 m_pd3d11DeviceContext->OMSetBlendState(pPipelineStateD3D11->GetD3D11BlendState(), m_BlendFactors, Desc.GraphicsPipeline.SampleMask);
108 const auto& GraphicsPipeline = pPipelineStateD3D11->GetGraphicsPipelineDesc();
109
110 m_pd3d11DeviceContext->OMSetBlendState(pPipelineStateD3D11->GetD3D11BlendState(), m_BlendFactors, GraphicsPipeline.SampleMask);
109111 m_pd3d11DeviceContext->RSSetState(pPipelineStateD3D11->GetD3D11RasterizerState());
110112 m_pd3d11DeviceContext->OMSetDepthStencilState(pPipelineStateD3D11->GetD3D11DepthStencilState(), m_StencilRef);
111113
118120 m_CommittedD3D11InputLayout = pd3d11InputLayout;
119121 }
120122
121 auto PrimTopology = Desc.GraphicsPipeline.PrimitiveTopology;
123 auto PrimTopology = GraphicsPipeline.PrimitiveTopology;
122124 if (m_CommittedPrimitiveTopology != PrimTopology)
123125 {
124126 m_CommittedPrimitiveTopology = PrimTopology;
178180 {
179181 #ifdef DILIGENT_DEVELOPMENT
180182 bool ResourcesPresent = false;
181 for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaders(); ++s)
182 {
183 auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
183 for (Uint32 s = 0; s < pPipelineStateD3D11->GetNumShaderStages(); ++s)
184 {
185 auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s);
184186 if (pShaderD3D11->GetD3D11Resources()->GetTotalResources() > 0)
185187 ResourcesPresent = true;
186188 }
205207 #endif
206208
207209 auto NumShaders = pShaderResBindingD3D11->GetNumActiveShaders();
208 VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaders(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state");
210 VERIFY(NumShaders == pPipelineStateD3D11->GetNumShaderStages(), "Number of active shaders in shader resource binding is not consistent with the number of shaders in the pipeline state");
209211
210212 #ifdef DILIGENT_DEVELOPMENT
211213 {
232234 const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType);
233235
234236 #ifdef DILIGENT_DEVELOPMENT
235 auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
237 auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s);
236238 VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType);
237239 #endif
238240
379381 const auto ShaderTypeInd = GetShaderTypeIndex(ShaderType);
380382
381383 #ifdef DILIGENT_DEVELOPMENT
382 auto* pShaderD3D11 = pPipelineStateD3D11->GetShader<ShaderD3D11Impl>(s);
384 auto* pShaderD3D11 = pPipelineStateD3D11->GetShader(s);
383385 VERIFY_EXPR(ShaderType == pShaderD3D11->GetDesc().ShaderType);
384386 #endif
385387
670672 {
671673 Uint32 SampleMask = 0xFFFFFFFF;
672674 ID3D11BlendState* pd3d11BS = nullptr;
673 if (m_pPipelineState)
674 {
675 SampleMask = m_pPipelineState->GetDesc().GraphicsPipeline.SampleMask;
675 if (m_pPipelineState && m_pPipelineState->GetDesc().IsAnyGraphicsPipeline())
676 {
677 SampleMask = m_pPipelineState->GetGraphicsPipelineDesc().SampleMask;
676678 pd3d11BS = m_pPipelineState->GetD3D11BlendState();
677679 }
678680 m_pd3d11DeviceContext->OMSetBlendState(pd3d11BS, m_BlendFactors, SampleMask);
3030 #include "RenderDeviceD3D11Impl.hpp"
3131 #include "ShaderResourceBindingD3D11Impl.hpp"
3232 #include "EngineMemory.h"
33 #include "ShaderD3D11Impl.hpp"
3433
3534 namespace Diligent
3635 {
3736
38 PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
39 RenderDeviceD3D11Impl* pRenderDeviceD3D11,
40 const PipelineStateCreateInfo& CreateInfo) :
37 template <typename PSOCreateInfoType>
38 void PipelineStateD3D11Impl::InitInternalObjects(const PSOCreateInfoType& CreateInfo)
39 {
40 m_ResourceLayoutIndex.fill(-1);
41
42 std::vector<std::pair<SHADER_TYPE, ShaderD3D11Impl*>> ShaderStages;
43 ExtractShaders<ShaderD3D11Impl>(CreateInfo, ShaderStages);
44
45 const auto NumShaderStages = GetNumShaderStages();
46 VERIFY_EXPR(NumShaderStages > 0 && NumShaderStages == ShaderStages.size());
47
48 LinearAllocator MemPool{GetRawAllocator()};
49
50 MemPool.AddSpace<ShaderResourceCacheD3D11>(NumShaderStages);
51 MemPool.AddSpace<ShaderResourceLayoutD3D11>(NumShaderStages);
52
53 ReserveSpaceForPipelineDesc(CreateInfo, MemPool);
54
55 MemPool.Reserve();
56
57 m_pStaticResourceCaches = MemPool.ConstructArray<ShaderResourceCacheD3D11>(NumShaderStages);
58
59 // The memory is now owned by PipelineStateD3D11Impl and will be freed by Destruct().
60 auto* Ptr = MemPool.ReleaseOwnership();
61 VERIFY_EXPR(Ptr == m_pStaticResourceCaches);
62 (void)Ptr;
63
64 m_pStaticResourceLayouts = MemPool.Allocate<ShaderResourceLayoutD3D11>(NumShaderStages);
65 for (Uint32 i = 0; i < NumShaderStages; ++i)
66 new (m_pStaticResourceLayouts + i) ShaderResourceLayoutD3D11{*this, m_pStaticResourceCaches[i]}; // noexcept
67
68 InitializePipelineDesc(CreateInfo, MemPool);
69
70 // It is important to construct all objects before initializing them because if an exception is thrown,
71 // destructors will be called for all objects
72
73 InitResourceLayouts(CreateInfo, ShaderStages);
74 }
75
76
77 PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
78 RenderDeviceD3D11Impl* pRenderDeviceD3D11,
79 const GraphicsPipelineStateCreateInfo& CreateInfo) :
4180 // clang-format off
4281 TPipelineStateBase
4382 {
4483 pRefCounters,
4584 pRenderDeviceD3D11,
46 CreateInfo.PSODesc
85 CreateInfo
4786 },
4887 m_SRBMemAllocator{GetRawAllocator()},
49 m_StaticSamplers (STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector<StaticSamplerInfo>"))
88 m_ImmutableSamplers (STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector<ImmutableSamplerInfo>"))
5089 // clang-format on
5190 {
52 m_ResourceLayoutIndex.fill(-1);
53
54 if (m_Desc.IsComputePipeline())
55 {
56 auto* pCS = ValidatedCast<ShaderD3D11Impl>(m_Desc.ComputePipeline.pCS);
57 m_pCS = pCS;
58 if (m_pCS == nullptr)
59 {
60 LOG_ERROR_AND_THROW("Compute shader is null");
61 }
62
63 if (m_pCS && m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE)
64 {
65 LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(SHADER_TYPE_COMPUTE), " shader is expeceted while ", GetShaderTypeLiteralName(m_pCS->GetDesc().ShaderType), " provided");
66 }
67 m_ShaderResourceLayoutHash = pCS->GetD3D11Resources()->GetHash();
68 }
69 else if (m_Desc.PipelineType == PIPELINE_TYPE_GRAPHICS)
70 {
91 try
92 {
93 InitInternalObjects(CreateInfo);
94
95 auto& GraphicsPipeline = GetGraphicsPipelineDesc();
7196
7297 #define INIT_SHADER(ShortName, ExpectedType) \
7398 do \
7499 { \
75 auto* pShader = ValidatedCast<ShaderD3D11Impl>(m_Desc.GraphicsPipeline.p##ShortName); \
100 auto* pShader = ValidatedCast<ShaderD3D11Impl>(CreateInfo.p##ShortName); \
76101 m_p##ShortName = pShader; \
77102 if (m_p##ShortName && m_p##ShortName->GetDesc().ShaderType != ExpectedType) \
78103 { \
97122 auto* pDeviceD3D11 = pRenderDeviceD3D11->GetD3D11Device();
98123
99124 D3D11_BLEND_DESC D3D11BSDesc = {};
100 BlendStateDesc_To_D3D11_BLEND_DESC(m_Desc.GraphicsPipeline.BlendDesc, D3D11BSDesc);
125 BlendStateDesc_To_D3D11_BLEND_DESC(GraphicsPipeline.BlendDesc, D3D11BSDesc);
101126 CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateBlendState(&D3D11BSDesc, &m_pd3d11BlendState),
102127 "Failed to create D3D11 blend state object");
103128
104129 D3D11_RASTERIZER_DESC D3D11RSDesc = {};
105 RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(m_Desc.GraphicsPipeline.RasterizerDesc, D3D11RSDesc);
130 RasterizerStateDesc_To_D3D11_RASTERIZER_DESC(GraphicsPipeline.RasterizerDesc, D3D11RSDesc);
106131 CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateRasterizerState(&D3D11RSDesc, &m_pd3d11RasterizerState),
107132 "Failed to create D3D11 rasterizer state");
108133
109134 D3D11_DEPTH_STENCIL_DESC D3D11DSSDesc = {};
110 DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(m_Desc.GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc);
135 DepthStencilStateDesc_To_D3D11_DEPTH_STENCIL_DESC(GraphicsPipeline.DepthStencilDesc, D3D11DSSDesc);
111136 CHECK_D3D_RESULT_THROW(pDeviceD3D11->CreateDepthStencilState(&D3D11DSSDesc, &m_pd3d11DepthStencilState),
112137 "Failed to create D3D11 depth stencil state");
113138
114139 // Create input layout
115 const auto& InputLayout = m_Desc.GraphicsPipeline.InputLayout;
140 const auto& InputLayout = GraphicsPipeline.InputLayout;
116141 if (InputLayout.NumElements > 0)
117142 {
118143 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>"));
126151 "Failed to create the Direct3D11 input layout");
127152 }
128153 }
129 else
130 {
131 UNEXPECTED(GetPipelineTypeString(m_Desc.PipelineType), " pipelines are not supported by Direct3D11 backend");
132 }
133
134 m_pStaticResourceLayouts = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceLayoutD3D11", ShaderResourceLayoutD3D11, m_NumShaders);
135 m_pStaticResourceCaches = ALLOCATE(GetRawAllocator(), "Raw memory for ShaderResourceCacheD3D11", ShaderResourceCacheD3D11, m_NumShaders);
136
154 catch (...)
155 {
156 Destruct();
157 throw;
158 }
159 }
160
161 PipelineStateD3D11Impl::PipelineStateD3D11Impl(IReferenceCounters* pRefCounters,
162 RenderDeviceD3D11Impl* pRenderDeviceD3D11,
163 const ComputePipelineStateCreateInfo& CreateInfo) :
164 // clang-format off
165 TPipelineStateBase
166 {
167 pRefCounters,
168 pRenderDeviceD3D11,
169 CreateInfo
170 },
171 m_SRBMemAllocator{GetRawAllocator()},
172 m_ImmutableSamplers(STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector<ImmutableSamplerInfo>"))
173 // clang-format on
174 {
175 try
176 {
177 InitInternalObjects(CreateInfo);
178
179 m_pCS = ValidatedCast<ShaderD3D11Impl>(CreateInfo.pCS);
180 if (m_pCS == nullptr)
181 {
182 LOG_ERROR_AND_THROW("Compute shader is null");
183 }
184
185 if (m_pCS->GetDesc().ShaderType != SHADER_TYPE_COMPUTE)
186 {
187 LOG_ERROR_AND_THROW(GetShaderTypeLiteralName(SHADER_TYPE_COMPUTE), " shader is expeceted while ", GetShaderTypeLiteralName(m_pCS->GetDesc().ShaderType), " provided");
188 }
189 m_ShaderResourceLayoutHash = m_pCS->GetD3D11Resources()->GetHash();
190 }
191 catch (...)
192 {
193 Destruct();
194 throw;
195 }
196 }
197
198 PipelineStateD3D11Impl::~PipelineStateD3D11Impl()
199 {
200 Destruct();
201 }
202
203 void PipelineStateD3D11Impl::Destruct()
204 {
205 if (m_pStaticResourceLayouts != nullptr)
206 {
207 for (Uint32 l = 0; l < GetNumShaderStages(); ++l)
208 {
209 m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11();
210 }
211 }
212
213 if (m_pStaticResourceCaches != nullptr)
214 {
215 for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
216 {
217 m_pStaticResourceCaches[s].Destroy(GetRawAllocator());
218 m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11();
219 }
220 }
221
222 // All subobjects are allocated in contiguous chunks of memory.
223 if (auto* pRawMem = m_pStaticResourceCaches)
224 GetRawAllocator().Free(pRawMem);
225 }
226
227 IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase)
228
229
230 void PipelineStateD3D11Impl::InitResourceLayouts(const PipelineStateCreateInfo& CreateInfo,
231 const std::vector<std::pair<SHADER_TYPE, ShaderD3D11Impl*>>& ShaderStages)
232 {
137233 const auto& ResourceLayout = m_Desc.ResourceLayout;
138234
139235 #ifdef DILIGENT_DEVELOPMENT
140236 {
141237 const ShaderResources* pResources[MAX_SHADERS_IN_PIPELINE] = {};
142 for (Uint32 s = 0; s < m_NumShaders; ++s)
143 {
144 auto* pShader = GetShader<const ShaderD3D11Impl>(s);
238 for (Uint32 s = 0; s < ShaderStages.size(); ++s)
239 {
240 auto* pShader = ShaderStages[s].second;
145241 pResources[s] = &(*pShader->GetD3D11Resources());
146242 }
147 ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, m_NumShaders,
243 ShaderResources::DvpVerifyResourceLayout(ResourceLayout, pResources, GetNumShaderStages(),
148244 (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_VARIABLES) == 0,
149 (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_STATIC_SAMPLERS) == 0);
245 (CreateInfo.Flags & PSO_CREATE_FLAG_IGNORE_MISSING_IMMUTABLE_SAMPLERS) == 0);
150246 }
151247 #endif
152248
153 decltype(m_StaticSamplers) StaticSamplers(STD_ALLOCATOR_RAW_MEM(StaticSamplerInfo, GetRawAllocator(), "Allocator for vector<StaticSamplerInfo>"));
249 decltype(m_ImmutableSamplers) ImmutableSamplers{STD_ALLOCATOR_RAW_MEM(ImmutableSamplerInfo, GetRawAllocator(), "Allocator for vector<ImmutableSamplerInfo>")};
250
154251 std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderResLayoutDataSizes = {};
155252 std::array<size_t, MAX_SHADERS_IN_PIPELINE> ShaderResCacheDataSizes = {};
156 for (Uint32 s = 0; s < m_NumShaders; ++s)
157 {
158 const auto* pShader = GetShader<const ShaderD3D11Impl>(s);
159 const auto& ShaderDesc = pShader->GetDesc();
160 const auto& ShaderResources = *pShader->GetD3D11Resources();
161 VERIFY_EXPR(ShaderDesc.ShaderType == ShaderResources.GetShaderType());
162
163 new (m_pStaticResourceCaches + s) ShaderResourceCacheD3D11;
164 // Do not initialize the cache as this will be performed by the resource layout
253 for (Uint32 s = 0; s < ShaderStages.size(); ++s)
254 {
255 const auto* pShader = ShaderStages[s].second;
256 const auto& ShaderDesc = pShader->GetDesc();
257 const auto& Resources = *pShader->GetD3D11Resources();
258 VERIFY_EXPR(ShaderDesc.ShaderType == Resources.GetShaderType());
259
260 // The cache will be initialized by the resource layout
165261
166262 // Shader resource layout will only contain dynamic and mutable variables
167263 const SHADER_RESOURCE_VARIABLE_TYPE StaticVarTypes[] = {SHADER_RESOURCE_VARIABLE_TYPE_STATIC};
168 // clang-format off
169 new (m_pStaticResourceLayouts + s)
170 ShaderResourceLayoutD3D11
264 m_pStaticResourceLayouts[s].Initialize(
265 pShader->GetD3D11Resources(),
266 m_Desc.ResourceLayout,
267 StaticVarTypes,
268 _countof(StaticVarTypes),
269 GetRawAllocator(),
270 GetRawAllocator() //
271 );
272
273 // Initialize immutable samplers
274 for (Uint32 sam = 0; sam < Resources.GetNumSamplers(); ++sam)
275 {
276 const auto& SamplerAttribs = Resources.GetSampler(sam);
277 constexpr bool LogImtblSamplerArrayError = true;
278 auto SrcImtblSamplerInd = Resources.FindImmutableSampler(SamplerAttribs, ResourceLayout, LogImtblSamplerArrayError);
279 if (SrcImtblSamplerInd >= 0)
171280 {
172 *this,
173 pShader->GetD3D11Resources(),
174 m_Desc.ResourceLayout,
175 StaticVarTypes,
176 _countof(StaticVarTypes),
177 m_pStaticResourceCaches[s],
178 GetRawAllocator(),
179 GetRawAllocator()
180 };
181 // clang-format on
182
183 // Initialize static samplers
184 for (Uint32 sam = 0; sam < ShaderResources.GetNumSamplers(); ++sam)
185 {
186 const auto& SamplerAttribs = ShaderResources.GetSampler(sam);
187 constexpr bool LogStaticSamplerArrayError = true;
188 auto SrcStaticSamplerInd = ShaderResources.FindStaticSampler(SamplerAttribs, ResourceLayout, LogStaticSamplerArrayError);
189 if (SrcStaticSamplerInd >= 0)
190 {
191 const auto& SrcStaticSamplerInfo = ResourceLayout.StaticSamplers[SrcStaticSamplerInd];
192 RefCntAutoPtr<ISampler> pStaticSampler;
193 pRenderDeviceD3D11->CreateSampler(SrcStaticSamplerInfo.Desc, &pStaticSampler);
194 StaticSamplers.emplace_back(SamplerAttribs, std::move(pStaticSampler));
281 const auto& SrcImtblSamplerInfo = ResourceLayout.ImmutableSamplers[SrcImtblSamplerInd];
282
283 RefCntAutoPtr<ISampler> pImbtlSampler;
284 GetDevice()->CreateSampler(SrcImtblSamplerInfo.Desc, &pImbtlSampler);
285 ImmutableSamplers.emplace_back(SamplerAttribs, std::move(pImbtlSampler));
195286 }
196287 }
197 m_StaticSamplerOffsets[s + 1] = static_cast<Uint16>(StaticSamplers.size());
288 m_ImmutableSamplerOffsets[s + 1] = static_cast<Uint16>(ImmutableSamplers.size());
198289
199290 if (m_Desc.SRBAllocationGranularity > 1)
200291 {
203294 SHADER_RESOURCE_VARIABLE_TYPE_MUTABLE,
204295 SHADER_RESOURCE_VARIABLE_TYPE_DYNAMIC //
205296 };
206 ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(ShaderResources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes));
207 ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(ShaderResources);
297 ShaderResLayoutDataSizes[s] = ShaderResourceLayoutD3D11::GetRequiredMemorySize(Resources, ResourceLayout, SRBVarTypes, _countof(SRBVarTypes));
298 ShaderResCacheDataSizes[s] = ShaderResourceCacheD3D11::GetRequriedMemorySize(Resources);
208299 }
209300
210301 auto ShaderInd = GetShaderTypePipelineIndex(ShaderDesc.ShaderType, m_Desc.PipelineType);
213304
214305 if (m_Desc.SRBAllocationGranularity > 1)
215306 {
216 m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, m_NumShaders, ShaderResLayoutDataSizes.data(), m_NumShaders, ShaderResCacheDataSizes.data());
217 }
218
219 m_StaticSamplers.reserve(StaticSamplers.size());
220 for (auto& Sam : StaticSamplers)
221 m_StaticSamplers.emplace_back(std::move(Sam));
222
223 for (Uint32 s = 0; s < m_NumShaders; ++s)
224 {
225 // Initialize static samplers in the static resource cache to avoid warning messages
226 SetStaticSamplers(m_pStaticResourceCaches[s], s);
227 }
228 }
229
230
231 PipelineStateD3D11Impl::~PipelineStateD3D11Impl()
232 {
233 for (Uint32 s = 0; s < m_NumShaders; ++s)
234 {
235 m_pStaticResourceCaches[s].Destroy(GetRawAllocator());
236 m_pStaticResourceCaches[s].~ShaderResourceCacheD3D11();
237 }
238 GetRawAllocator().Free(m_pStaticResourceCaches);
239
240 for (Uint32 l = 0; l < m_NumShaders; ++l)
241 {
242 m_pStaticResourceLayouts[l].~ShaderResourceLayoutD3D11();
243 }
244 GetRawAllocator().Free(m_pStaticResourceLayouts);
245 }
246
247 IMPLEMENT_QUERY_INTERFACE(PipelineStateD3D11Impl, IID_PipelineStateD3D11, TPipelineStateBase)
248
307 m_SRBMemAllocator.Initialize(m_Desc.SRBAllocationGranularity, GetNumShaderStages(), ShaderResLayoutDataSizes.data(), GetNumShaderStages(), ShaderResCacheDataSizes.data());
308 }
309
310 m_ImmutableSamplers.reserve(ImmutableSamplers.size());
311 for (auto& ImtblSam : ImmutableSamplers)
312 m_ImmutableSamplers.emplace_back(std::move(ImtblSam));
313
314 for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
315 {
316 // Initialize immutable samplers in the static resource cache to avoid warning messages
317 SetImmutableSamplers(m_pStaticResourceCaches[s], s);
318 }
319 }
249320
250321 ID3D11BlendState* PipelineStateD3D11Impl::GetD3D11BlendState()
251322 {
269340
270341 void PipelineStateD3D11Impl::CreateShaderResourceBinding(IShaderResourceBinding** ppShaderResourceBinding, bool InitStaticResources)
271342 {
272 auto* pRenderDeviceD3D11 = ValidatedCast<RenderDeviceD3D11Impl>(GetDevice());
273 auto& SRBAllocator = pRenderDeviceD3D11->GetSRBAllocator();
274 auto pShaderResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingD3D11Impl instance", ShaderResourceBindingD3D11Impl)(this, false);
343 auto& SRBAllocator = GetDevice()->GetSRBAllocator();
344 auto pShaderResBinding = NEW_RC_OBJ(SRBAllocator, "ShaderResourceBindingD3D11Impl instance", ShaderResourceBindingD3D11Impl)(this, false);
275345 if (InitStaticResources)
276346 pShaderResBinding->InitializeStaticResources(nullptr);
277347 pShaderResBinding->QueryInterface(IID_ShaderResourceBinding, reinterpret_cast<IObject**>(static_cast<IShaderResourceBinding**>(ppShaderResourceBinding)));
288358 if (m_ShaderResourceLayoutHash != pPSOD3D11->m_ShaderResourceLayoutHash)
289359 return false;
290360
291 if (m_NumShaders != pPSOD3D11->m_NumShaders)
361 if (GetNumShaderStages() != pPSOD3D11->GetNumShaderStages())
292362 return false;
293363
294 for (Uint32 s = 0; s < m_NumShaders; ++s)
295 {
296 auto* pShader0 = GetShader<const ShaderD3D11Impl>(s);
297 auto* pShader1 = pPSOD3D11->GetShader<const ShaderD3D11Impl>(s);
364 for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
365 {
366 auto* pShader0 = GetShader(s);
367 auto* pShader1 = pPSOD3D11->GetShader(s);
298368 if (pShader0->GetDesc().ShaderType != pShader1->GetDesc().ShaderType)
299369 return false;
300370 const auto& Res0 = *pShader0->GetD3D11Resources();
351421
352422 void PipelineStateD3D11Impl::BindStaticResources(Uint32 ShaderFlags, IResourceMapping* pResourceMapping, Uint32 Flags)
353423 {
354 for (Uint32 s = 0; s < m_NumShaders; ++s)
424 for (Uint32 s = 0; s < GetNumShaderStages(); ++s)
355425 {
356426 auto& StaticResLayout = m_pStaticResourceLayouts[s];
357427 if ((ShaderFlags & StaticResLayout.GetShaderType()) != 0)
365435 if (LayoutInd < 0)
366436 return 0;
367437
368 VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= m_NumShaders);
438 VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= GetNumShaderStages());
369439 return m_pStaticResourceLayouts[LayoutInd].GetTotalResourceCount();
370440 }
371441
375445 if (LayoutInd < 0)
376446 return nullptr;
377447
378 VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= m_NumShaders);
448 VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= GetNumShaderStages());
379449 return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Name);
380450 }
381451
385455 if (LayoutInd < 0)
386456 return nullptr;
387457
388 VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= m_NumShaders);
458 VERIFY_EXPR(static_cast<Uint32>(LayoutInd) <= GetNumShaderStages());
389459 return m_pStaticResourceLayouts[LayoutInd].GetShaderVariable(Index);
390460 }
391461
392 void PipelineStateD3D11Impl::SetStaticSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const
462 void PipelineStateD3D11Impl::SetImmutableSamplers(ShaderResourceCacheD3D11& ResourceCache, Uint32 ShaderInd) const
393463