• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "shader_manager.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 #include <cstring>
21 
22 #include <base/containers/array_view.h>
23 #include <core/io/intf_file_manager.h>
24 #include <render/device/pipeline_layout_desc.h>
25 #include <render/namespace.h>
26 
27 #include "device/device.h"
28 #include "device/gpu_program.h"
29 #include "device/gpu_program_util.h"
30 #include "device/gpu_resource_handle_util.h"
31 #include "device/shader_module.h"
32 #include "device/shader_pipeline_binder.h"
33 #include "loader/shader_loader.h"
34 #include "util/log.h"
35 #include "util/shader_saver.h"
36 
37 using namespace BASE_NS;
38 using namespace CORE_NS;
39 
40 constexpr uint64_t IA_HASH_PRIMITIVE_TOPOLOGY_SHIFT = 1;
41 
42 constexpr uint64_t RS_HASH_POLYGON_MODE_SHIFT = 4;
43 constexpr uint64_t RS_HASH_CULL_MODE_SHIFT = 8;
44 constexpr uint64_t RS_HASH_FRONT_FACE_SHIFT = 12;
45 
46 constexpr uint64_t DSS_HASH_DEPTH_COMPARE_SHIFT = 4;
47 
48 constexpr uint64_t HASH_RS_SHIFT = 0;
49 constexpr uint64_t HASH_DS_SHIFT = 32;
50 constexpr uint64_t HASH_IA_SHIFT = 56;
51 
52 union FloatAsUint32 {
53     float f;
54     uint32_t ui;
55 };
56 
57 template<>
hash(const RENDER_NS::GraphicsState::InputAssembly & inputAssembly)58 uint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::InputAssembly& inputAssembly)
59 {
60     uint64_t hash = 0;
61     hash |= static_cast<uint64_t>(inputAssembly.enablePrimitiveRestart);
62     hash |= (static_cast<uint64_t>(inputAssembly.primitiveTopology) << IA_HASH_PRIMITIVE_TOPOLOGY_SHIFT);
63     return hash;
64 }
65 
66 template<>
hash(const RENDER_NS::GraphicsState::RasterizationState & state)67 uint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::RasterizationState& state)
68 {
69     uint64_t hash = 0;
70     hash |= (static_cast<uint64_t>(state.enableRasterizerDiscard) << 2u) |
71             (static_cast<uint64_t>(state.enableDepthBias) << 1u) | static_cast<uint64_t>(state.enableDepthClamp);
72     hash |= (static_cast<uint64_t>(state.polygonMode) << RS_HASH_POLYGON_MODE_SHIFT);
73     hash |= (static_cast<uint64_t>(state.cullModeFlags) << RS_HASH_CULL_MODE_SHIFT);
74     hash |= (static_cast<uint64_t>(state.frontFace) << RS_HASH_FRONT_FACE_SHIFT);
75     return hash;
76 }
77 
78 template<>
hash(const RENDER_NS::GraphicsState::DepthStencilState & state)79 uint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::DepthStencilState& state)
80 {
81     uint64_t hash = 0;
82     hash |= (static_cast<uint64_t>(state.enableStencilTest) << 3u) |
83             (static_cast<uint64_t>(state.enableDepthBoundsTest) << 2u) |
84             (static_cast<uint64_t>(state.enableDepthWrite) << 1u) | static_cast<uint64_t>(state.enableDepthTest);
85     hash |= (static_cast<uint64_t>(state.depthCompareOp) << DSS_HASH_DEPTH_COMPARE_SHIFT);
86     return hash;
87 }
88 
89 template<>
hash(const RENDER_NS::GraphicsState::ColorBlendState::Attachment & state)90 uint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::ColorBlendState::Attachment& state)
91 {
92     uint64_t hash = 0;
93     hash |= (static_cast<uint64_t>(state.enableBlend) << 0u);
94     // blend factor values 0 - 18, 0x1f for exact (5 bits)
95     hash |= (static_cast<uint64_t>(state.srcColorBlendFactor) << 1u);
96     hash |= ((static_cast<uint64_t>(state.dstColorBlendFactor) & 0x1f) << 6u);
97     hash |= ((static_cast<uint64_t>(state.srcAlphaBlendFactor) & 0x1f) << 12u);
98     hash |= ((static_cast<uint64_t>(state.dstAlphaBlendFactor) & 0x1f) << 18u);
99     // blend op values 0 - 4, 0x7 for exact (3 bits)
100     hash |= ((static_cast<uint64_t>(state.colorBlendOp) & 0x7) << 24u);
101     hash |= ((static_cast<uint64_t>(state.alphaBlendOp) & 0x7) << 28u);
102     return hash;
103 }
104 
105 template<>
hash(const RENDER_NS::GraphicsState::ColorBlendState & state)106 uint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::ColorBlendState& state)
107 {
108     uint64_t hash = 0;
109     hash |= (static_cast<uint64_t>(state.enableLogicOp) << 0u);
110     hash |= (static_cast<uint64_t>(state.logicOp) << 1u);
111 
112     FloatAsUint32 vec[4u] = { { state.colorBlendConstants[0u] }, { state.colorBlendConstants[1u] },
113         { state.colorBlendConstants[2u] }, { state.colorBlendConstants[3u] } };
114     const uint64_t hashRG = (static_cast<uint64_t>(vec[0u].ui) << 32) | (vec[1u].ui);
115     const uint64_t hashBA = (static_cast<uint64_t>(vec[2u].ui) << 32) | (vec[3u].ui);
116     HashCombine(hash, hashRG, hashBA);
117     for (uint32_t idx = 0; idx < state.colorAttachmentCount; ++idx) {
118         HashCombine(hash, state.colorAttachments[idx]);
119     }
120     return hash;
121 }
122 
123 template<>
hash(const RENDER_NS::GraphicsState & state)124 uint64_t BASE_NS::hash(const RENDER_NS::GraphicsState& state)
125 {
126     const uint64_t iaHash = hash(state.inputAssembly);
127     const uint64_t rsHash = hash(state.rasterizationState);
128     const uint64_t dsHash = hash(state.depthStencilState);
129     const uint64_t cbsHash = hash(state.colorBlendState);
130     uint64_t finalHash = (iaHash << HASH_IA_SHIFT) | (rsHash << HASH_RS_SHIFT) | (dsHash << HASH_DS_SHIFT);
131     HashCombine(finalHash, cbsHash);
132     return finalHash;
133 }
134 
135 RENDER_BEGIN_NAMESPACE()
136 namespace {
GetPackedDescriptorTypeFlags(const ImageFlags imageFlags,const ImageDimension imageDimension)137 constexpr AdditionalDescriptorTypeFlags GetPackedDescriptorTypeFlags(
138     const ImageFlags imageFlags, const ImageDimension imageDimension)
139 {
140     AdditionalDescriptorFlags flags = 0U;
141     if (imageDimension == ImageDimension::DIMENSION_1D) {
142         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_1D_BIT;
143     }
144     if (imageDimension == ImageDimension::DIMENSION_2D) {
145         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_2D_BIT;
146     }
147     if (imageDimension == ImageDimension::DIMENSION_3D) {
148         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_3D_BIT;
149     }
150     if (imageDimension == ImageDimension::DIMENSION_CUBE) {
151         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_CUBE_BIT;
152     }
153     if (imageDimension == ImageDimension::DIMENSION_RECT) {
154         flags |= 0U;
155     }
156     if (imageDimension == ImageDimension::DIMENSION_BUFFER) {
157         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_BUFFER_BIT;
158     }
159     if (imageDimension == ImageDimension::DIMENSION_SUBPASS) {
160         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_SUBPASS_BIT;
161     }
162 
163     if (imageFlags == ImageFlags::IMAGE_DEPTH) {
164         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DEPTH_BIT;
165     }
166     if (imageFlags == ImageFlags::IMAGE_ARRAY) {
167         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_ARRAY_BIT;
168     }
169     if (imageFlags == ImageFlags::IMAGE_MULTISAMPLE) {
170         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_MULTISAMPLE_BIT;
171     }
172     if (imageFlags == ImageFlags::IMAGE_SAMPLED) {
173         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_SAMPLED_BIT;
174     }
175     if (imageFlags == ImageFlags::IMAGE_LOAD_STORE) {
176         flags |= AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_LOAD_STORE_BIT;
177     }
178 
179     return flags;
180 }
181 
IsUniformBuffer(const DescriptorType descriptorType)182 constexpr inline bool IsUniformBuffer(const DescriptorType descriptorType)
183 {
184     return ((descriptorType == CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
185             (descriptorType == CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER));
186 }
IsStorageBuffer(const DescriptorType descriptorType)187 constexpr inline bool IsStorageBuffer(const DescriptorType descriptorType)
188 {
189     return ((descriptorType == CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) ||
190             (descriptorType == CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER));
191 }
192 
GetPipelineLayoutCompatibilityFlags(const PipelineLayout & lhs,const PipelineLayout & rhs)193 ShaderManager::CompatibilityFlags GetPipelineLayoutCompatibilityFlags(
194     const PipelineLayout& lhs, const PipelineLayout& rhs)
195 {
196     ShaderManager::CompatibilityFlags flags = ShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT;
197     for (uint32_t setIdx = 0; setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++setIdx) {
198         const auto& lSet = lhs.descriptorSetLayouts[setIdx];
199         const auto& rSet = rhs.descriptorSetLayouts[setIdx];
200         if (lSet.set == rSet.set) {
201             for (const auto& lBind : lSet.bindings) {
202                 for (const auto& rBind : rSet.bindings) {
203                     if (lBind.binding == rBind.binding) {
204                         if ((lBind.descriptorCount != rBind.descriptorCount) ||
205                             (lBind.descriptorType != rBind.descriptorType)) {
206                             // re-check dynamic offsets
207                             if ((IsUniformBuffer(lBind.descriptorType) != IsUniformBuffer(rBind.descriptorType)) &&
208                                 (IsStorageBuffer(lBind.descriptorType) != IsStorageBuffer(rBind.descriptorType))) {
209                                 flags = 0;
210                             }
211                         }
212                     }
213                 }
214             }
215         }
216     }
217     if (flags != 0) {
218         // check for exact match
219         bool isExact = true;
220         for (uint32_t setIdx = 0; setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++setIdx) {
221             const auto& lSet = lhs.descriptorSetLayouts[setIdx];
222             const auto& rSet = rhs.descriptorSetLayouts[setIdx];
223             if (lSet.set == rSet.set) {
224                 if (lSet.bindings.size() == rSet.bindings.size()) {
225                     for (size_t idx = 0; idx < lSet.bindings.size(); ++idx) {
226                         const int cmpRes =
227                             std::memcmp(&(lSet.bindings[idx]), &(rSet.bindings[idx]), sizeof(lSet.bindings[idx]));
228                         if (cmpRes != 0) {
229                             isExact = false;
230                             break;
231                         }
232                     }
233                 } else {
234                     isExact = false;
235                     break;
236                 }
237             }
238         }
239         if (isExact) {
240             flags |= ShaderManager::CompatibilityFlagBits::EXACT_BIT;
241         }
242     }
243     return flags;
244 }
245 
246 // NOTE: checking the type for validity is enough
IsComputeShaderFunc(RenderHandle handle)247 inline bool IsComputeShaderFunc(RenderHandle handle)
248 {
249     return RenderHandleType::COMPUTE_SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle);
250 }
251 
IsShaderFunc(RenderHandle handle)252 inline bool IsShaderFunc(RenderHandle handle)
253 {
254     return RenderHandleType::SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle);
255 }
256 
IsAnyShaderFunc(RenderHandle handle)257 inline bool IsAnyShaderFunc(RenderHandle handle)
258 {
259     return (RenderHandleType::COMPUTE_SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle)) ||
260            (RenderHandleType::SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle));
261 }
262 
GetShadersBySlot(const uint32_t renderSlotId,const ShaderManager::ComputeMappings & mappings,vector<RenderHandleReference> & shaders)263 inline void GetShadersBySlot(
264     const uint32_t renderSlotId, const ShaderManager::ComputeMappings& mappings, vector<RenderHandleReference>& shaders)
265 {
266     for (const auto& ref : mappings.clientData) {
267         if (ref.renderSlotId == renderSlotId) {
268             shaders.push_back(ref.rhr);
269         }
270     }
271 }
272 
GetShadersBySlot(const uint32_t renderSlotId,const ShaderManager::GraphicsMappings & mappings,vector<RenderHandleReference> & shaders)273 inline void GetShadersBySlot(const uint32_t renderSlotId, const ShaderManager::GraphicsMappings& mappings,
274     vector<RenderHandleReference>& shaders)
275 {
276     for (const auto& ref : mappings.clientData) {
277         if (ref.renderSlotId == renderSlotId) {
278             shaders.push_back(ref.rhr);
279         }
280     }
281 }
282 
GetShadersBySlot(const uint32_t renderSlotId,const ShaderManager::ComputeMappings & mappings,vector<RenderHandle> & shaders)283 inline void GetShadersBySlot(
284     const uint32_t renderSlotId, const ShaderManager::ComputeMappings& mappings, vector<RenderHandle>& shaders)
285 {
286     for (const auto& ref : mappings.clientData) {
287         if (ref.renderSlotId == renderSlotId) {
288             shaders.push_back(ref.rhr.GetHandle());
289         }
290     }
291 }
292 
GetShadersBySlot(const uint32_t renderSlotId,const ShaderManager::GraphicsMappings & mappings,vector<RenderHandle> & shaders)293 inline void GetShadersBySlot(
294     const uint32_t renderSlotId, const ShaderManager::GraphicsMappings& mappings, vector<RenderHandle>& shaders)
295 {
296     for (const auto& ref : mappings.clientData) {
297         if (ref.renderSlotId == renderSlotId) {
298             shaders.push_back(ref.rhr.GetHandle());
299         }
300     }
301 }
302 
GetGraphicsStatesBySlot(const uint32_t renderSlotId,const ShaderManager::GraphicsStateData & gsd,vector<RenderHandleReference> & states)303 inline void GetGraphicsStatesBySlot(
304     const uint32_t renderSlotId, const ShaderManager::GraphicsStateData& gsd, vector<RenderHandleReference>& states)
305 {
306     PLUGIN_ASSERT(gsd.data.size() == gsd.rhr.size());
307     for (size_t idx = 0; idx < gsd.data.size(); ++idx) {
308         const auto& ref = gsd.data[idx];
309         if (ref.renderSlotId == renderSlotId) {
310             states.push_back(gsd.rhr[idx]);
311         }
312     }
313 }
314 
GetHandle(const string_view path,const unordered_map<string,RenderHandle> & nameToClientHandle)315 inline RenderHandle GetHandle(const string_view path, const unordered_map<string, RenderHandle>& nameToClientHandle)
316 {
317     if (auto const pos = nameToClientHandle.find(path); pos != nameToClientHandle.end()) {
318         return pos->second;
319     }
320     return {};
321 }
322 
HashHandleAndSlot(const RenderHandle & handle,const uint32_t renderSlotId)323 constexpr inline uint64_t HashHandleAndSlot(const RenderHandle& handle, const uint32_t renderSlotId)
324 {
325     // normally there are < 16 render slot ids used which way less than 0xffff
326     // NOTE: the render slot id might be an invalid index
327     return (handle.id << 16ull) | (renderSlotId & 0xffff);
328 }
329 
GetBaseGraphicsStateVariantIndex(const ShaderManager::GraphicsStateData & graphicsStates,const ShaderManager::GraphicsStateVariantCreateInfo & vci)330 uint32_t GetBaseGraphicsStateVariantIndex(
331     const ShaderManager::GraphicsStateData& graphicsStates, const ShaderManager::GraphicsStateVariantCreateInfo& vci)
332 {
333     uint32_t baseVariantIndex = INVALID_SM_INDEX;
334     if (!vci.baseShaderState.empty()) {
335         const string fullBaseName = vci.baseShaderState + vci.baseVariant;
336         if (const auto bhIter = graphicsStates.nameToIndex.find(fullBaseName);
337             bhIter != graphicsStates.nameToIndex.cend()) {
338             PLUGIN_ASSERT(bhIter->second < graphicsStates.rhr.size());
339             if ((bhIter->second < graphicsStates.rhr.size()) && graphicsStates.rhr[bhIter->second]) {
340                 const RenderHandle baseHandle = graphicsStates.rhr[bhIter->second].GetHandle();
341                 baseVariantIndex = RenderHandleUtil::GetIndexPart(baseHandle);
342             }
343         } else {
344             PLUGIN_LOG_W("base state not found (%s %s)", vci.baseShaderState.data(), vci.baseVariant.data());
345         }
346     }
347     return baseVariantIndex;
348 }
349 
Read8U(const uint8_t * & ptr)350 inline uint8_t Read8U(const uint8_t*& ptr)
351 {
352     uint8_t ret = *(ptr);
353     ptr += sizeof(ret);
354     return ret;
355 }
356 
Read16U(const uint8_t * & ptr)357 inline uint16_t Read16U(const uint8_t*& ptr)
358 {
359     auto ret = static_cast<uint16_t>(*(ptr) | (*(ptr + 1) << 8U));
360     ptr += sizeof(ret);
361     return ret;
362 }
Read32U(const uint8_t * & ptr)363 inline uint32_t Read32U(const uint8_t*& ptr)
364 {
365     auto ret = static_cast<uint32_t>(*ptr | *(ptr + 1) << 8U | *(ptr + 2) << 16U | *(ptr + 3) << 24U);
366     ptr += sizeof(ret);
367     return ret;
368 }
369 } // namespace
370 
ShaderManager(Device & device)371 ShaderManager::ShaderManager(Device& device) : device_(device) {}
372 
373 ShaderManager::~ShaderManager() = default;
374 
Get(const RenderHandle & handle) const375 RenderHandleReference ShaderManager::Get(const RenderHandle& handle) const
376 {
377     if (RenderHandleUtil::IsValid(handle)) {
378         const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
379         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
380         if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
381             if (arrayIndex < computeShaderMappings_.clientData.size()) {
382                 return computeShaderMappings_.clientData[arrayIndex].rhr;
383             }
384         } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
385             if (arrayIndex < shaderMappings_.clientData.size()) {
386                 return shaderMappings_.clientData[arrayIndex].rhr;
387             }
388         } else if (handleType == RenderHandleType::GRAPHICS_STATE) {
389             if (arrayIndex < graphicsStates_.rhr.size()) {
390                 return graphicsStates_.rhr[arrayIndex];
391             }
392         } else if (handleType == RenderHandleType::PIPELINE_LAYOUT) {
393             if (arrayIndex < pl_.rhr.size()) {
394                 return pl_.rhr[arrayIndex];
395             }
396         }
397         PLUGIN_LOG_I("invalid render handle (id: %" PRIu64 ", type: %u)", handle.id, static_cast<uint32_t>(handleType));
398     }
399     return RenderHandleReference {};
400 }
401 
HashGraphicsState(const GraphicsState & graphicsState) const402 uint64_t ShaderManager::HashGraphicsState(const GraphicsState& graphicsState) const
403 {
404     return BASE_NS::hash(graphicsState);
405 }
406 
CreateRenderSlotId(const string_view renderSlot)407 uint32_t ShaderManager::CreateRenderSlotId(const string_view renderSlot)
408 {
409     if (renderSlot.empty()) {
410         return INVALID_SM_INDEX;
411     }
412 
413     if (const auto iter = renderSlotIds_.nameToId.find(renderSlot); iter != renderSlotIds_.nameToId.cend()) {
414         return iter->second;
415     } else { // create new id
416         const auto renderSlotId = static_cast<uint32_t>(renderSlotIds_.data.size());
417         renderSlotIds_.nameToId[renderSlot] = renderSlotId;
418         renderSlotIds_.data.push_back(RenderSlotData { renderSlotId, {}, {}, {}, {} });
419         return renderSlotId;
420     }
421 }
422 
GetRenderSlotName(const uint32_t renderSlotId) const423 string ShaderManager::GetRenderSlotName(const uint32_t renderSlotId) const
424 {
425     if (renderSlotId != INVALID_SM_INDEX) {
426         for (const auto& ref : renderSlotIds_.nameToId) {
427             if (ref.second == renderSlotId) {
428                 return ref.first;
429             }
430         }
431     }
432     return {};
433 }
434 
GetCategoryName(const uint32_t categoryId) const435 string ShaderManager::GetCategoryName(const uint32_t categoryId) const
436 {
437     if (categoryId != INVALID_SM_INDEX) {
438         for (const auto& ref : category_.nameToId) {
439             if (ref.second == categoryId) {
440                 return ref.first;
441             }
442         }
443     }
444     return {};
445 }
446 
SetRenderSlotData(const RenderSlotData & renderSlotData)447 void ShaderManager::SetRenderSlotData(const RenderSlotData& renderSlotData)
448 {
449     const uint32_t rsId = renderSlotData.renderSlotId;
450     if (rsId < static_cast<uint32_t>(renderSlotIds_.data.size())) {
451 #if (RENDER_VALIDATION_ENABLED == 1)
452         const string renderSlotName = GetRenderSlotName(rsId);
453 #endif
454         if (IsAnyShaderFunc(renderSlotData.shader.GetHandle())) {
455 #if (RENDER_VALIDATION_ENABLED == 1)
456             if (renderSlotIds_.data[rsId].shader) {
457                 PLUGIN_LOG_W(
458                     "RENDER_VALIDATION: Overwriting default shader for render slot (%s)", renderSlotName.c_str());
459             }
460 #endif
461             renderSlotIds_.data[rsId].shader = renderSlotData.shader;
462         }
463         if (RenderHandleUtil::GetHandleType(renderSlotData.graphicsState.GetHandle()) ==
464             RenderHandleType::GRAPHICS_STATE) {
465 #if (RENDER_VALIDATION_ENABLED == 1)
466             if (renderSlotIds_.data[rsId].graphicsState) {
467                 PLUGIN_LOG_W(
468                     "RENDER_VALIDATION: Overwriting default gfx state for render slot (%s)", renderSlotName.c_str());
469             }
470 #endif
471             renderSlotIds_.data[rsId].graphicsState = renderSlotData.graphicsState;
472         }
473         if (RenderHandleUtil::GetHandleType(renderSlotData.pipelineLayout.GetHandle()) ==
474             RenderHandleType::PIPELINE_LAYOUT) {
475 #if (RENDER_VALIDATION_ENABLED == 1)
476             if (renderSlotIds_.data[rsId].pipelineLayout) {
477                 PLUGIN_LOG_W("RENDER_VALIDATION: Overwriting default pl for render slot (%s)", renderSlotName.c_str());
478             }
479 #endif
480             renderSlotIds_.data[rsId].pipelineLayout = renderSlotData.pipelineLayout;
481         }
482         if (RenderHandleUtil::GetHandleType(renderSlotData.vertexInputDeclaration.GetHandle()) ==
483             RenderHandleType::VERTEX_INPUT_DECLARATION) {
484 #if (RENDER_VALIDATION_ENABLED == 1)
485             if (renderSlotIds_.data[rsId].vertexInputDeclaration) {
486                 PLUGIN_LOG_W("RENDER_VALIDATION: Overwriting default vid for render slot (%s)", renderSlotName.c_str());
487             }
488 #endif
489             renderSlotIds_.data[rsId].vertexInputDeclaration = renderSlotData.vertexInputDeclaration;
490         }
491     }
492 }
493 
CreateCategoryId(const string_view name)494 uint32_t ShaderManager::CreateCategoryId(const string_view name)
495 {
496     if (name.empty()) {
497         return INVALID_SM_INDEX;
498     }
499 
500     if (const auto iter = category_.nameToId.find(name); iter != category_.nameToId.cend()) {
501         return iter->second;
502     } else { // create new id
503         const auto id = static_cast<uint32_t>(category_.data.size());
504         category_.nameToId[name] = id;
505         category_.data.push_back(string(name));
506         return id;
507     }
508 }
509 
CreateClientData(const string_view path,const RenderHandleType type,const ClientDataIndices & cdi)510 RenderHandle ShaderManager::CreateClientData(
511     const string_view path, const RenderHandleType type, const ClientDataIndices& cdi)
512 {
513     PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
514     PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
515 
516     RenderHandle clientHandle;
517     PLUGIN_ASSERT(
518         (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) || (type == RenderHandleType::SHADER_STATE_OBJECT));
519     const uint64_t frameIndex = device_.GetFrameCount();
520     if (auto iter = nameToClientHandle_.find(path); iter != nameToClientHandle_.end()) {
521         clientHandle = iter->second;
522         // we update the frame index if the shader has been (re)loaded
523         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(clientHandle);
524         if ((type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
525             (arrayIndex < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
526             computeShaderMappings_.clientData[arrayIndex].frameIndex = frameIndex;
527         } else if (arrayIndex < static_cast<uint32_t>(shaderMappings_.clientData.size())) {
528             shaderMappings_.clientData[arrayIndex].frameIndex = frameIndex;
529         }
530     } else {
531         const uint32_t arrayIndex = (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT)
532                                         ? static_cast<uint32_t>(computeShaderMappings_.clientData.size())
533                                         : static_cast<uint32_t>(shaderMappings_.clientData.size());
534         clientHandle = RenderHandleUtil::CreateGpuResourceHandle(type, 0, arrayIndex, 0);
535         RenderHandleReference rhr =
536             RenderHandleReference(clientHandle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter()));
537         if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
538             computeShaderMappings_.clientData.push_back({ move(rhr), {}, {}, cdi.renderSlotIndex,
539                 cdi.pipelineLayoutIndex, cdi.reflectionPipelineLayoutIndex, cdi.categoryIndex, frameIndex });
540             computeShaderMappings_.nameData.push_back({});
541         } else {
542             shaderMappings_.clientData.push_back({ move(rhr), {}, {}, cdi.renderSlotIndex, cdi.pipelineLayoutIndex,
543                 cdi.reflectionPipelineLayoutIndex, INVALID_SM_INDEX, INVALID_SM_INDEX, cdi.categoryIndex, frameIndex });
544             shaderMappings_.nameData.push_back({});
545         }
546         if (!path.empty()) {
547             nameToClientHandle_[path] = clientHandle;
548         }
549     }
550 
551     return clientHandle;
552 }
553 
CreateBaseShaderPathsAndHashes(const uint32_t renderSlotId,const ShaderPathCreateData & pathCreateInfo,const BaseShaderPathCreateData & baseShaderCreateInfo,const RenderHandle clientHandle,RenderHandle & ownBaseShaderUri,RenderHandle & addBaseShaderUri)554 void ShaderManager::CreateBaseShaderPathsAndHashes(const uint32_t renderSlotId,
555     const ShaderPathCreateData& pathCreateInfo, const BaseShaderPathCreateData& baseShaderCreateInfo,
556     const RenderHandle clientHandle, RenderHandle& ownBaseShaderUri, RenderHandle& addBaseShaderUri)
557 {
558     // no render slot -> no valid base shaders and variants based on render slots
559     if (renderSlotId == ~0U) {
560         return;
561     }
562 #if (RENDER_VALIDATION_ENABLED == 1)
563     if (baseShaderCreateInfo.ownBaseShaderUri.empty() && (!baseShaderCreateInfo.addBaseShaderUri.empty())) {
564         PLUGIN_LOG_W(
565             "RENDER_VALIDATION: Shader variant (%s) cannot add additional base shader (%s) when it does not have "
566             "own base shader (%s)",
567             pathCreateInfo.variantName.data(), baseShaderCreateInfo.addBaseShaderUri.data(),
568             baseShaderCreateInfo.ownBaseShaderUri.data());
569     }
570 #endif
571     if (!baseShaderCreateInfo.ownBaseShaderUri.empty()) {
572 #if (RENDER_VALIDATION_ENABLED == 1)
573         if (const auto bsIter = nameToClientHandle_.find(baseShaderCreateInfo.ownBaseShaderUri);
574             (bsIter != nameToClientHandle_.cend()) && RenderHandleUtil::IsValid(bsIter->second)) {
575             RenderHandle baseShaderHandle = bsIter->second;
576             const uint64_t hash = HashHandleAndSlot(baseShaderHandle, renderSlotId);
577             if (hashToShaderVariant_.contains(hash)) {
578                 PLUGIN_LOG_W("RENDER_VALIDATION: Shader variant (%s) has already variant for the slot (%u), uri: %s",
579                     string(pathCreateInfo.variantName.data()).c_str(), renderSlotId,
580                     baseShaderCreateInfo.ownBaseShaderUri.data());
581             }
582         }
583 #endif
584         auto AddBaseShaderSlotVariant = [&](const string_view bsUri, const RenderHandle handle) {
585             RenderHandle bsHandle {};
586             if (const auto bsIter = nameToClientHandle_.find(bsUri);
587                 (bsIter != nameToClientHandle_.cend()) && RenderHandleUtil::IsValid(bsIter->second)) {
588                 bsHandle = bsIter->second;
589                 const uint64_t hash = HashHandleAndSlot(bsHandle, renderSlotId);
590                 hashToShaderVariant_[hash] = handle;
591             } else {
592                 PLUGIN_LOG_W("base shader (%s) NDF (%s)", bsUri.data(), string(pathCreateInfo.variantName).c_str());
593             }
594             return bsHandle;
595         };
596         ownBaseShaderUri = AddBaseShaderSlotVariant(baseShaderCreateInfo.ownBaseShaderUri, clientHandle);
597         if (!baseShaderCreateInfo.addBaseShaderUri.empty()) {
598             addBaseShaderUri = AddBaseShaderSlotVariant(baseShaderCreateInfo.addBaseShaderUri, clientHandle);
599         }
600     }
601 }
602 
Create(const ComputeShaderCreateData & createInfo,const ShaderPathCreateData & pathCreateInfo,const BaseShaderPathCreateData & baseShaderCreateInfo)603 RenderHandleReference ShaderManager::Create(const ComputeShaderCreateData& createInfo,
604     const ShaderPathCreateData& pathCreateInfo, const BaseShaderPathCreateData& baseShaderCreateInfo)
605 {
606     PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
607 
608     const string fullName = createInfo.path + pathCreateInfo.variantName;
609     // reflection pipeline layout
610     uint32_t reflectionPlIndex = INVALID_SM_INDEX;
611     if (const ShaderModule* cs = GetShaderModule(createInfo.shaderModuleIndex); cs) {
612         const RenderHandleReference plRhr = CreatePipelineLayout({ fullName, cs->GetPipelineLayout() });
613         reflectionPlIndex = RenderHandleUtil::GetIndexPart(plRhr.GetHandle());
614     }
615 
616     auto const clientHandle = CreateClientData(fullName, RenderHandleType::COMPUTE_SHADER_STATE_OBJECT,
617         { createInfo.renderSlotId, createInfo.pipelineLayoutIndex, reflectionPlIndex, createInfo.categoryId });
618     if (createInfo.pipelineLayoutIndex != INVALID_SM_INDEX) {
619         pl_.computeShaderToIndex[clientHandle] = createInfo.pipelineLayoutIndex;
620     }
621 
622     {
623         const auto lock = std::lock_guard(pendingMutex_);
624         pendingAllocations_.computeShaders.push_back(
625             { clientHandle, createInfo.shaderModuleIndex, createInfo.pipelineLayoutIndex });
626     }
627     if ((!createInfo.shaderFileStr.empty()) && RenderHandleUtil::IsValid(clientHandle)) {
628         // update shader file always
629         handleToShaderDataFile_.insert_or_assign(clientHandle, string(createInfo.shaderFileStr));
630     }
631     if (!createInfo.materialMetadata.empty()) {
632         MaterialMetadata metadata { string(createInfo.materialMetadata), json::value {} };
633         if (metadata.json = json::parse(metadata.raw.data()); metadata.json) {
634             // update metadata always
635             shaderToMetadata_.insert_or_assign(clientHandle, move(metadata));
636         }
637     }
638 
639     const uint32_t index = RenderHandleUtil::GetIndexPart(clientHandle);
640     if (IsComputeShaderFunc(clientHandle) &&
641         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
642         auto& nameDataRef = computeShaderMappings_.nameData[index];
643         nameDataRef.path = createInfo.path;
644         nameDataRef.variantName = pathCreateInfo.variantName;
645         nameDataRef.displayName = pathCreateInfo.displayName;
646         auto& clientDataRef = computeShaderMappings_.clientData[index];
647         CreateBaseShaderPathsAndHashes(createInfo.renderSlotId, pathCreateInfo, baseShaderCreateInfo, clientHandle,
648             clientDataRef.ownBaseShaderHandle, clientDataRef.addBaseShaderHandle);
649         return clientDataRef.rhr;
650     }
651     return {};
652 }
653 
CreateShaderDataImpl(const ShaderCreateData & createInfo,const ShaderPathCreateData & pathCreateInfo,const BaseShaderPathCreateData & baseShaderCreateInfo,const RenderHandle clientHandle,const uint32_t index)654 RenderHandleReference ShaderManager::CreateShaderDataImpl(const ShaderCreateData& createInfo,
655     const ShaderPathCreateData& pathCreateInfo, const BaseShaderPathCreateData& baseShaderCreateInfo,
656     const RenderHandle clientHandle, const uint32_t index)
657 {
658     auto& nameDataRef = shaderMappings_.nameData[index];
659     nameDataRef.path = createInfo.path;
660     nameDataRef.variantName = pathCreateInfo.variantName;
661     nameDataRef.displayName = pathCreateInfo.displayName;
662     auto& clientDataRef = shaderMappings_.clientData[index];
663     clientDataRef.graphicsStateIndex = createInfo.graphicsStateIndex;
664     clientDataRef.vertexInputDeclarationIndex = createInfo.vertexInputDeclarationIndex;
665 
666     CreateBaseShaderPathsAndHashes(createInfo.renderSlotId, pathCreateInfo, baseShaderCreateInfo, clientHandle,
667         clientDataRef.ownBaseShaderHandle, clientDataRef.addBaseShaderHandle);
668 
669     return clientDataRef.rhr;
670 }
671 
Create(const ShaderCreateData & createInfo,const ShaderPathCreateData & pathCreateInfo,const BaseShaderPathCreateData & baseShaderCreateInfo)672 RenderHandleReference ShaderManager::Create(const ShaderCreateData& createInfo,
673     const ShaderPathCreateData& pathCreateInfo, const BaseShaderPathCreateData& baseShaderCreateInfo)
674 {
675     PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
676 
677     const string fullName = createInfo.path + pathCreateInfo.variantName;
678     // reflection pipeline layout
679     uint32_t reflectionPlIndex = INVALID_SM_INDEX;
680     const ShaderModule* vs = GetShaderModule(createInfo.vertShaderModuleIndex);
681     const ShaderModule* fs = GetShaderModule(createInfo.fragShaderModuleIndex);
682     if (vs && fs) {
683         const PipelineLayout layouts[] { vs->GetPipelineLayout(), fs->GetPipelineLayout() };
684         PipelineLayout pl;
685         GpuProgramUtil::CombinePipelineLayouts({ layouts, 2u }, pl);
686         const RenderHandleReference plRhr = CreatePipelineLayout({ fullName, pl });
687         reflectionPlIndex = RenderHandleUtil::GetIndexPart(plRhr.GetHandle());
688     }
689 
690     auto const clientHandle = CreateClientData(fullName, RenderHandleType::SHADER_STATE_OBJECT,
691         { createInfo.renderSlotId, createInfo.pipelineLayoutIndex, reflectionPlIndex, createInfo.categoryId });
692 
693     if (createInfo.pipelineLayoutIndex != INVALID_SM_INDEX) {
694         pl_.shaderToIndex[clientHandle] = createInfo.pipelineLayoutIndex;
695     }
696     if (createInfo.vertexInputDeclarationIndex != INVALID_SM_INDEX) {
697         shaderVid_.shaderToIndex[clientHandle] = createInfo.vertexInputDeclarationIndex;
698     }
699 
700     {
701         const auto lock = std::lock_guard(pendingMutex_);
702         pendingAllocations_.shaders.push_back({ clientHandle, createInfo.vertShaderModuleIndex,
703             createInfo.fragShaderModuleIndex, createInfo.pipelineLayoutIndex, createInfo.vertexInputDeclarationIndex });
704     }
705 
706     if ((!createInfo.shaderFileStr.empty()) && RenderHandleUtil::IsValid(clientHandle)) {
707         // update shader file always
708         handleToShaderDataFile_.insert_or_assign(clientHandle, string(createInfo.shaderFileStr));
709     }
710     if (!createInfo.materialMetadata.empty()) {
711         MaterialMetadata metadata { string(createInfo.materialMetadata), json::value {} };
712         if (metadata.json = json::parse(metadata.raw.data()); metadata.json) {
713             // update metadata always
714             shaderToMetadata_.insert_or_assign(clientHandle, move(metadata));
715         } else {
716             shaderToMetadata_.erase(clientHandle);
717         }
718     } else {
719         shaderToMetadata_.erase(clientHandle);
720     }
721 
722     const uint32_t index = RenderHandleUtil::GetIndexPart(clientHandle);
723     if (IsShaderFunc(clientHandle) && (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
724         return CreateShaderDataImpl(createInfo, pathCreateInfo, baseShaderCreateInfo, clientHandle, index);
725     }
726     return {};
727 }
728 
AddAdditionalNameForHandle(const RenderHandleReference & handle,const string_view name)729 void ShaderManager::AddAdditionalNameForHandle(const RenderHandleReference& handle, const string_view name)
730 {
731     if (handle) {
732         const RenderHandle rawHandle = handle.GetHandle();
733         const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
734         // add name only if name not used yet
735         if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
736             (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
737             if (!nameToClientHandle_.contains(name)) {
738                 nameToClientHandle_[name] = rawHandle;
739             } else {
740                 PLUGIN_LOG_W("trying to add additional name (%s) for shader handle, but the name is already in use",
741                     name.data());
742             }
743         }
744     }
745 }
746 
CreateComputeShader(const ComputeShaderCreateInfo & createInfo,const string_view additionalBaseShaderPath,const string_view variantName)747 RenderHandleReference ShaderManager::CreateComputeShader(const ComputeShaderCreateInfo& createInfo,
748     const string_view additionalBaseShaderPath, const string_view variantName)
749 {
750     if (!createInfo.shaderPaths.empty()) {
751         if (const uint32_t moduleIdx = GetShaderModuleIndex(createInfo.shaderPaths[0].path);
752             moduleIdx != INVALID_SM_INDEX) {
753             return Create(ComputeShaderCreateData { createInfo.path, createInfo.renderSlotId, createInfo.categoryId,
754                               RenderHandleUtil::GetIndexPart(createInfo.pipelineLayout), moduleIdx, {}, {} },
755                 { variantName, {} }, { createInfo.path, additionalBaseShaderPath });
756         } else {
757             PLUGIN_LOG_E("ShaderManager: compute shader (%s) creation failed, compute shader path (%s) not found",
758                 string(createInfo.path).c_str(), string(createInfo.shaderPaths[0].path).c_str());
759         }
760     } else {
761         PLUGIN_LOG_E("ShaderManager: compute shader (%s) creation failed, no shader module paths given",
762             string(createInfo.path).c_str());
763     }
764     return {};
765 }
766 
CreateComputeShader(const ComputeShaderCreateInfo & createInfo)767 RenderHandleReference ShaderManager::CreateComputeShader(const ComputeShaderCreateInfo& createInfo)
768 {
769     return CreateComputeShader(createInfo, "", "");
770 }
771 
CreateShader(const ShaderCreateInfo & createInfo,const string_view additionalBaseShaderPath,const string_view variantName)772 RenderHandleReference ShaderManager::CreateShader(
773     const ShaderCreateInfo& createInfo, const string_view additionalBaseShaderPath, const string_view variantName)
774 {
775     if (createInfo.shaderPaths.size() >= 2u) {
776         const uint32_t vertShaderModule = GetShaderModuleIndex(createInfo.shaderPaths[0u].path);
777         const uint32_t fragShaderModule = GetShaderModuleIndex(createInfo.shaderPaths[1u].path);
778         if ((vertShaderModule != INVALID_SM_INDEX) && (fragShaderModule != INVALID_SM_INDEX)) {
779             return Create(ShaderCreateData { createInfo.path, createInfo.renderSlotId, createInfo.categoryId,
780                               RenderHandleUtil::GetIndexPart(createInfo.vertexInputDeclaration),
781                               RenderHandleUtil::GetIndexPart(createInfo.pipelineLayout),
782                               RenderHandleUtil::GetIndexPart(createInfo.graphicsState), vertShaderModule,
783                               fragShaderModule, {}, {} },
784                 { variantName, {} }, { createInfo.path, additionalBaseShaderPath });
785         } else {
786             PLUGIN_LOG_E("ShaderManager: shader (%s) creation failed, shader path (vert:%s) (frag:%s) not found",
787                 string(createInfo.path).c_str(), string(createInfo.shaderPaths[0u].path).c_str(),
788                 string(createInfo.shaderPaths[1u].path).c_str());
789         }
790     } else {
791         PLUGIN_LOG_E("ShaderManager: shader (%s) creation failed, no shader module paths given",
792             string(createInfo.path).c_str());
793     }
794     return {};
795 }
796 
CreateShader(const ShaderCreateInfo & createInfo)797 RenderHandleReference ShaderManager::CreateShader(const ShaderCreateInfo& createInfo)
798 {
799     return CreateShader(createInfo, "", "");
800 }
801 
HandlePendingAllocations()802 void ShaderManager::HandlePendingAllocations()
803 {
804     pendingMutex_.lock();
805     decltype(pendingAllocations_) pendingAllocations = move(pendingAllocations_);
806     pendingMutex_.unlock();
807 
808     for (const auto& handleRef : pendingAllocations.destroyHandles) {
809         const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handleRef);
810         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handleRef);
811         if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
812             if (arrayIndex < static_cast<uint32_t>(computeShaders_.size())) {
813                 computeShaders_[arrayIndex] = {};
814             }
815         } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
816             if (arrayIndex < static_cast<uint32_t>(shaders_.size())) {
817                 shaders_[arrayIndex] = {};
818             }
819         }
820     }
821     HandlePendingShaders(pendingAllocations);
822     HandlePendingModules(pendingAllocations);
823 
824     const uint64_t frameCount = device_.GetFrameCount();
825     constexpr uint64_t additionalFrameCount { 2u };
826     const auto minAge = device_.GetCommandBufferingCount() + additionalFrameCount;
827     const auto ageLimit = (frameCount < minAge) ? 0 : (frameCount - minAge);
828     auto CompareForErase = [](const auto ageLimit, auto& vec) {
829         for (auto iter = vec.begin(); iter != vec.end();) {
830             if (iter->frameIndex < ageLimit) {
831                 iter = vec.erase(iter);
832             } else {
833                 ++iter;
834             }
835         }
836     };
837     CompareForErase(ageLimit, deferredDestructions_.shaderModules);
838     CompareForErase(ageLimit, deferredDestructions_.computePrograms);
839     CompareForErase(ageLimit, deferredDestructions_.shaderPrograms);
840 
841     if (!reloadedShaders_.empty()) {
842         lastReloadedShadersFrameIndex_ = device_.GetFrameCount();
843         reloadedShadersForBackend_.push_back({});
844         auto& ref = reloadedShadersForBackend_.back();
845         ref.frameIndex = lastReloadedShadersFrameIndex_;
846         std::swap(ref.shadersForBackend, reloadedShaders_);
847 
848         reloadedShaders_.clear();
849     }
850 }
851 
HandlePendingShaders(Allocs & allocs)852 void ShaderManager::HandlePendingShaders(Allocs& allocs)
853 {
854     const uint64_t frameCount = device_.GetFrameCount();
855     for (const auto& ref : allocs.computeShaders) {
856         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(ref.handle);
857         ShaderModule* shaderModule = GetShaderModule(ref.computeModuleIndex);
858         if (shaderModule) {
859             if (arrayIndex < static_cast<uint32_t>(computeShaders_.size())) {
860                 // replace with new (push old for deferred destruction)
861                 deferredDestructions_.computePrograms.push_back({ frameCount, move(computeShaders_[arrayIndex].gsp) });
862                 computeShaders_[arrayIndex] = { device_.CreateGpuComputeProgram({ shaderModule }),
863                     ref.pipelineLayoutIndex, ref.computeModuleIndex };
864             } else {
865                 // new gpu resource
866                 computeShaders_.push_back({ device_.CreateGpuComputeProgram({ shaderModule }), ref.pipelineLayoutIndex,
867                     ref.computeModuleIndex });
868             }
869         }
870 #if (RENDER_VALIDATION_ENABLED == 1)
871         if (!shaderModule) {
872             PLUGIN_LOG_E("RENDER_VALIDATION: Compute shader module with index:%u, not found", ref.computeModuleIndex);
873         }
874 #endif
875     }
876     for (const auto& ref : allocs.shaders) {
877         uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(ref.handle);
878         ShaderModule* vertShaderModule = GetShaderModule(ref.vertModuleIndex);
879         ShaderModule* fragShaderModule = GetShaderModule(ref.fragModuleIndex);
880         if (vertShaderModule && fragShaderModule) {
881             if ((arrayIndex < static_cast<uint32_t>(shaders_.size()))) {
882                 // replace with new (push old for deferred destruction)
883                 deferredDestructions_.shaderPrograms.push_back({ frameCount, move(shaders_[arrayIndex].gsp) });
884                 shaders_[arrayIndex] = { device_.CreateGpuShaderProgram({ vertShaderModule, fragShaderModule }),
885                     ref.pipelineLayoutIndex, ref.vertexInputDeclIndex, ref.vertModuleIndex, ref.fragModuleIndex };
886             } else { // new gpu resource
887                 shaders_.push_back({ device_.CreateGpuShaderProgram({ vertShaderModule, fragShaderModule }),
888                     ref.pipelineLayoutIndex, ref.vertexInputDeclIndex, ref.vertModuleIndex, ref.fragModuleIndex });
889             }
890         }
891 #if (RENDER_VALIDATION_ENABLED == 1)
892         if ((!vertShaderModule) || (!fragShaderModule)) {
893             PLUGIN_LOG_E("RENDER_VALIDATION: Shader module with index: %u or %u, not found", ref.vertModuleIndex,
894                 ref.fragModuleIndex);
895         }
896 #endif
897     }
898 }
899 
HandlePendingModules(Allocs & allocs)900 void ShaderManager::HandlePendingModules(Allocs& allocs)
901 {
902     const uint64_t frameCount = device_.GetFrameCount();
903     for (const auto modIdx : allocs.recreatedComputeModuleIndices) {
904         for (auto& shaderRef : computeShaders_) {
905             if (modIdx == shaderRef.compModuleIndex) {
906                 if (ShaderModule* compModule = GetShaderModule(shaderRef.compModuleIndex); compModule) {
907                     deferredDestructions_.computePrograms.push_back({ frameCount, move(shaderRef.gsp) });
908                     shaderRef.gsp = device_.CreateGpuComputeProgram({ compModule });
909                 }
910             }
911         }
912     }
913     for (const auto modIdx : allocs.recreatedShaderModuleIndices) {
914         for (auto& shaderRef : shaders_) {
915             if ((modIdx == shaderRef.vertModuleIndex) || (modIdx == shaderRef.fragModuleIndex)) {
916                 ShaderModule* vertModule = GetShaderModule(shaderRef.vertModuleIndex);
917                 ShaderModule* fragModule = GetShaderModule(shaderRef.fragModuleIndex);
918                 if (vertModule && fragModule) {
919                     deferredDestructions_.shaderPrograms.push_back({ frameCount, move(shaderRef.gsp) });
920                     shaderRef.gsp = device_.CreateGpuShaderProgram({ vertModule, fragModule });
921                 }
922             }
923         }
924     }
925 }
926 
GetShaderHandle(const string_view path) const927 RenderHandleReference ShaderManager::GetShaderHandle(const string_view path) const
928 {
929     const RenderHandle handle = GetHandle(path, nameToClientHandle_);
930     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
931     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
932     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
933         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
934         return computeShaderMappings_.clientData[index].rhr;
935     } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
936                (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
937         return shaderMappings_.clientData[index].rhr;
938     } else {
939         PLUGIN_LOG_W("ShaderManager: invalid shader %s", path.data());
940         return {};
941     }
942 }
943 
GetShaderHandle(const string_view path,const string_view variantName) const944 RenderHandleReference ShaderManager::GetShaderHandle(const string_view path, const string_view variantName) const
945 {
946     const string fullName = path + variantName;
947     const RenderHandle handle = GetHandle(fullName, nameToClientHandle_);
948     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
949     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
950     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
951         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
952         return computeShaderMappings_.clientData[index].rhr;
953     } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
954                (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
955         return shaderMappings_.clientData[index].rhr;
956     } else {
957         PLUGIN_LOG_W("ShaderManager: invalid shader (%s) variant (%s)", path.data(), variantName.data());
958         return {};
959     }
960 }
961 
GetShaderHandle(const RenderHandle & handle,const uint32_t renderSlotId) const962 RenderHandleReference ShaderManager::GetShaderHandle(const RenderHandle& handle, const uint32_t renderSlotId) const
963 {
964     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
965     if ((handleType != RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
966         (handleType != RenderHandleType::SHADER_STATE_OBJECT)) {
967         return {}; // early out
968     }
969 
970     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
971     RenderHandle ownBaseShaderHandle;
972     RenderHandle addBaseShaderHandle;
973     // check first for own validity and possible base shader handle
974     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
975         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
976         const auto& ref = computeShaderMappings_.clientData[index];
977         if (ref.renderSlotId == renderSlotId) {
978             return ref.rhr; // early out
979         }
980         ownBaseShaderHandle = ref.ownBaseShaderHandle;
981         addBaseShaderHandle = ref.addBaseShaderHandle;
982     } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
983                (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
984         const auto& ref = shaderMappings_.clientData[index];
985         if (ref.renderSlotId == renderSlotId) {
986             return ref.rhr; // early out
987         }
988         ownBaseShaderHandle = ref.ownBaseShaderHandle;
989         addBaseShaderHandle = ref.addBaseShaderHandle;
990     }
991     // try to find a match through base shader variant
992     auto GetBaseShaderMatchedSlotHandle = [](const auto& hashToShaderVariant, const auto& clData,
993                                               const RenderHandle baseShaderHandle, const uint32_t renderSlotId) {
994         PLUGIN_ASSERT(RenderHandleUtil::IsValid(baseShaderHandle));
995 
996         RenderHandleReference rhr;
997         const uint64_t hash = HashHandleAndSlot(baseShaderHandle, renderSlotId);
998         if (const auto iter = hashToShaderVariant.find(hash); iter != hashToShaderVariant.cend()) {
999             const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(iter->second);
1000             if (arrayIndex < clData.size() && (clData[arrayIndex].renderSlotId == renderSlotId)) {
1001                 rhr = clData[arrayIndex].rhr;
1002             }
1003         }
1004         return rhr;
1005     };
1006 
1007     RenderHandleReference slotHandle {};
1008     if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1009         if (RenderHandleUtil::IsValid(ownBaseShaderHandle)) {
1010             slotHandle = GetBaseShaderMatchedSlotHandle(
1011                 hashToShaderVariant_, computeShaderMappings_.clientData, ownBaseShaderHandle, renderSlotId);
1012         }
1013         if ((!slotHandle) && (RenderHandleUtil::IsValid(addBaseShaderHandle))) {
1014             slotHandle = GetBaseShaderMatchedSlotHandle(
1015                 hashToShaderVariant_, computeShaderMappings_.clientData, addBaseShaderHandle, renderSlotId);
1016         }
1017     } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
1018         if (RenderHandleUtil::IsValid(ownBaseShaderHandle)) {
1019             slotHandle = GetBaseShaderMatchedSlotHandle(
1020                 hashToShaderVariant_, shaderMappings_.clientData, ownBaseShaderHandle, renderSlotId);
1021         }
1022         if ((!slotHandle) && (RenderHandleUtil::IsValid(addBaseShaderHandle))) {
1023             slotHandle = GetBaseShaderMatchedSlotHandle(
1024                 hashToShaderVariant_, shaderMappings_.clientData, addBaseShaderHandle, renderSlotId);
1025         }
1026     }
1027 
1028     return slotHandle;
1029 }
1030 
GetShaderHandle(const RenderHandleReference & handle,const uint32_t renderSlotId) const1031 RenderHandleReference ShaderManager::GetShaderHandle(
1032     const RenderHandleReference& handle, const uint32_t renderSlotId) const
1033 {
1034     return GetShaderHandle(handle.GetHandle(), renderSlotId);
1035 }
1036 
GetShaders(const uint32_t renderSlotId) const1037 vector<RenderHandleReference> ShaderManager::GetShaders(const uint32_t renderSlotId) const
1038 {
1039     vector<RenderHandleReference> shaders;
1040     GetShadersBySlot(renderSlotId, shaderMappings_, shaders);
1041     GetShadersBySlot(renderSlotId, computeShaderMappings_, shaders);
1042     return shaders;
1043 }
1044 
GetShaderRawHandles(const uint32_t renderSlotId) const1045 vector<RenderHandle> ShaderManager::GetShaderRawHandles(const uint32_t renderSlotId) const
1046 {
1047     vector<RenderHandle> shaders;
1048     GetShadersBySlot(renderSlotId, shaderMappings_, shaders);
1049     GetShadersBySlot(renderSlotId, computeShaderMappings_, shaders);
1050     return shaders;
1051 }
1052 
CreateGraphicsState(const GraphicsStateCreateInfo & createInfo,const GraphicsStateVariantCreateInfo & variantCreateInfo)1053 RenderHandleReference ShaderManager::CreateGraphicsState(
1054     const GraphicsStateCreateInfo& createInfo, const GraphicsStateVariantCreateInfo& variantCreateInfo)
1055 {
1056     PLUGIN_ASSERT(graphicsStates_.rhr.size() == graphicsStates_.graphicsStates.size());
1057     PLUGIN_ASSERT(graphicsStates_.rhr.size() == graphicsStates_.data.size());
1058     const uint32_t renderSlotId = CreateRenderSlotId(variantCreateInfo.renderSlot);
1059     // NOTE: No collisions expected if path is used
1060     const string fullName = createInfo.path + variantCreateInfo.variant;
1061     uint32_t arrayIndex = INVALID_SM_INDEX;
1062     if (auto nameIter = graphicsStates_.nameToIndex.find(fullName); nameIter != graphicsStates_.nameToIndex.end()) {
1063         arrayIndex = static_cast<uint32_t>(nameIter->second);
1064     }
1065 
1066     uint32_t baseVariantIndex = INVALID_SM_INDEX;
1067     RenderHandleReference rhr;
1068     if (arrayIndex < graphicsStates_.rhr.size()) {
1069         rhr = graphicsStates_.rhr[arrayIndex];
1070         graphicsStates_.graphicsStates[arrayIndex] = createInfo.graphicsState;
1071         const uint64_t hash = HashGraphicsState(createInfo.graphicsState);
1072         baseVariantIndex = GetBaseGraphicsStateVariantIndex(graphicsStates_, variantCreateInfo);
1073         graphicsStates_.data[arrayIndex] = { hash, renderSlotId, baseVariantIndex, variantCreateInfo.stateFlags };
1074         graphicsStates_.hashToIndex[hash] = arrayIndex;
1075     } else { // new
1076         arrayIndex = static_cast<uint32_t>(graphicsStates_.rhr.size());
1077         // NOTE: these are only updated for new states
1078         if (!fullName.empty()) {
1079             graphicsStates_.nameToIndex[fullName] = arrayIndex;
1080         }
1081         const RenderHandle handle = RenderHandleUtil::CreateHandle(RenderHandleType::GRAPHICS_STATE, arrayIndex);
1082         graphicsStates_.rhr.push_back(
1083             RenderHandleReference(handle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter())));
1084         rhr = graphicsStates_.rhr[arrayIndex];
1085         graphicsStates_.graphicsStates.push_back(createInfo.graphicsState);
1086         const uint64_t hash = HashGraphicsState(createInfo.graphicsState);
1087         // ordering matters, this fetches from nameToIndex
1088         baseVariantIndex = GetBaseGraphicsStateVariantIndex(graphicsStates_, variantCreateInfo);
1089         graphicsStates_.data.push_back({ hash, renderSlotId, baseVariantIndex, variantCreateInfo.stateFlags });
1090         graphicsStates_.hashToIndex[hash] = arrayIndex;
1091     }
1092     if (variantCreateInfo.renderSlotDefault && (arrayIndex < graphicsStates_.rhr.size())) {
1093         SetRenderSlotData({ renderSlotId, {}, graphicsStates_.rhr[arrayIndex], {}, {} });
1094     }
1095 
1096     if (baseVariantIndex < graphicsStates_.rhr.size()) {
1097         const uint64_t variantHash = HashHandleAndSlot(graphicsStates_.rhr[baseVariantIndex].GetHandle(), renderSlotId);
1098         if (variantHash != INVALID_SM_INDEX) {
1099 #if (RENDER_VALIDATION_ENABLED == 1)
1100             if (graphicsStates_.variantHashToIndex.contains(variantHash)) {
1101                 PLUGIN_LOG_W("RENDER_VALIDATION: overwriting variant hash with %s %s", createInfo.path.data(),
1102                     variantCreateInfo.variant.data());
1103             }
1104 #endif
1105             graphicsStates_.variantHashToIndex[variantHash] = RenderHandleUtil::GetIndexPart(rhr.GetHandle());
1106         }
1107     }
1108 
1109     return rhr;
1110 }
1111 
CreateGraphicsState(const GraphicsStateCreateInfo & createInfo)1112 RenderHandleReference ShaderManager::CreateGraphicsState(const GraphicsStateCreateInfo& createInfo)
1113 {
1114     return CreateGraphicsState(createInfo, {});
1115 }
1116 
GetGraphicsStateHandle(const string_view path) const1117 RenderHandleReference ShaderManager::GetGraphicsStateHandle(const string_view path) const
1118 {
1119     if (const auto iter = graphicsStates_.nameToIndex.find(path); iter != graphicsStates_.nameToIndex.cend()) {
1120         PLUGIN_ASSERT(iter->second < graphicsStates_.rhr.size());
1121         return graphicsStates_.rhr[iter->second];
1122     }
1123     PLUGIN_LOG_W("ShaderManager: named graphics state not found: %s", string(path).c_str());
1124     return {};
1125 }
1126 
GetGraphicsStateHandle(const string_view path,const string_view variantName) const1127 RenderHandleReference ShaderManager::GetGraphicsStateHandle(const string_view path, const string_view variantName) const
1128 {
1129     // NOTE: does not call the base GetGraphicsStateHandle due to better error logging
1130     const string fullName = string(path + variantName);
1131     if (const auto iter = graphicsStates_.nameToIndex.find(fullName); iter != graphicsStates_.nameToIndex.cend()) {
1132         PLUGIN_ASSERT(iter->second < graphicsStates_.rhr.size());
1133         return graphicsStates_.rhr[iter->second];
1134     }
1135     PLUGIN_LOG_W(
1136         "ShaderManager: named graphics state not found (name: %s variant: %s)", path.data(), variantName.data());
1137     return {};
1138 }
1139 
GetGraphicsStateHandle(const RenderHandle & handle,const uint32_t renderSlotId) const1140 RenderHandleReference ShaderManager::GetGraphicsStateHandle(
1141     const RenderHandle& handle, const uint32_t renderSlotId) const
1142 {
1143     PLUGIN_ASSERT(graphicsStates_.data.size() == graphicsStates_.rhr.size());
1144 
1145     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1146     if ((RenderHandleUtil::GetHandleType(handle) == RenderHandleType::GRAPHICS_STATE) &&
1147         (arrayIndex < static_cast<uint32_t>(graphicsStates_.data.size()))) {
1148         // check for own validity
1149         const auto& data = graphicsStates_.data[arrayIndex];
1150         if (renderSlotId == data.renderSlotId) {
1151             return graphicsStates_.rhr[arrayIndex];
1152         }
1153         // check for base variant for hashing
1154         if (data.baseVariantIndex < static_cast<uint32_t>(graphicsStates_.rhr.size())) {
1155             const RenderHandle baseHandle = graphicsStates_.rhr[data.baseVariantIndex].GetHandle();
1156             const uint64_t hash = HashHandleAndSlot(baseHandle, renderSlotId);
1157             if (const auto iter = graphicsStates_.variantHashToIndex.find(hash);
1158                 iter != graphicsStates_.variantHashToIndex.cend()) {
1159                 PLUGIN_ASSERT(iter->second < static_cast<uint32_t>(graphicsStates_.rhr.size()));
1160                 return graphicsStates_.rhr[iter->second];
1161             }
1162         }
1163     }
1164     return {};
1165 }
1166 
GetGraphicsStateHandle(const RenderHandleReference & handle,const uint32_t renderSlotId) const1167 RenderHandleReference ShaderManager::GetGraphicsStateHandle(
1168     const RenderHandleReference& handle, const uint32_t renderSlotId) const
1169 {
1170     return GetGraphicsStateHandle(handle.GetHandle(), renderSlotId);
1171 }
1172 
GetGraphicsStateHandleByHash(const uint64_t hash) const1173 RenderHandleReference ShaderManager::GetGraphicsStateHandleByHash(const uint64_t hash) const
1174 {
1175     if (const auto iter = graphicsStates_.hashToIndex.find(hash); iter != graphicsStates_.hashToIndex.cend()) {
1176         if (iter->second < graphicsStates_.rhr.size()) {
1177             return graphicsStates_.rhr[iter->second];
1178         }
1179     }
1180     return {};
1181 }
1182 
GetGraphicsStateHandleByShaderHandle(const RenderHandle & handle) const1183 RenderHandleReference ShaderManager::GetGraphicsStateHandleByShaderHandle(const RenderHandle& handle) const
1184 {
1185     if (RenderHandleUtil::GetHandleType(handle) == RenderHandleType::SHADER_STATE_OBJECT) {
1186         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1187         if (arrayIndex < static_cast<uint32_t>(shaderMappings_.clientData.size())) {
1188             const uint32_t gsIndex = shaderMappings_.clientData[arrayIndex].graphicsStateIndex;
1189             if (gsIndex < static_cast<uint32_t>(graphicsStates_.rhr.size())) {
1190                 return graphicsStates_.rhr[gsIndex];
1191             }
1192 #if (RENDER_VALIDATION_ENABLED == 1)
1193             PLUGIN_ASSERT(gsIndex != INVALID_SM_INDEX); // not and optional index ATM
1194             PLUGIN_ASSERT(gsIndex < graphicsStates_.rhr.size());
1195 #endif
1196         }
1197     }
1198     return {};
1199 }
1200 
GetGraphicsStateHandleByShaderHandle(const RenderHandleReference & handle) const1201 RenderHandleReference ShaderManager::GetGraphicsStateHandleByShaderHandle(const RenderHandleReference& handle) const
1202 {
1203     return GetGraphicsStateHandleByShaderHandle(handle.GetHandle());
1204 }
1205 
GetGraphicsState(const RenderHandleReference & handle) const1206 GraphicsState ShaderManager::GetGraphicsState(const RenderHandleReference& handle) const
1207 {
1208     return GetGraphicsStateRef(handle);
1209 }
1210 
GetGraphicsStates(const uint32_t renderSlotId) const1211 vector<RenderHandleReference> ShaderManager::GetGraphicsStates(const uint32_t renderSlotId) const
1212 {
1213     vector<RenderHandleReference> gfxStates;
1214     GetGraphicsStatesBySlot(renderSlotId, graphicsStates_, gfxStates);
1215     return gfxStates;
1216 }
1217 
GetGraphicsStateRef(const RenderHandle & handle) const1218 const GraphicsState& ShaderManager::GetGraphicsStateRef(const RenderHandle& handle) const
1219 {
1220     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1221     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1222     if ((type == RenderHandleType::GRAPHICS_STATE) &&
1223         (arrayIndex < static_cast<uint32_t>(graphicsStates_.graphicsStates.size()))) {
1224         return graphicsStates_.graphicsStates[arrayIndex];
1225     }
1226 #if (RENDER_VALIDATION_ENABLED == 1)
1227     if (RenderHandleUtil::IsValid(handle) && (type != RenderHandleType::GRAPHICS_STATE)) {
1228         PLUGIN_LOG_W("RENDER_VALIDATION: invalid handle type given to GetGraphicsState()");
1229     }
1230 #endif
1231     return defaultGraphicsState_;
1232 }
1233 
GetGraphicsStateRef(const RenderHandleReference & handle) const1234 const GraphicsState& ShaderManager::GetGraphicsStateRef(const RenderHandleReference& handle) const
1235 {
1236     return GetGraphicsStateRef(handle.GetHandle());
1237 }
1238 
GetRenderSlotId(const string_view renderSlot) const1239 uint32_t ShaderManager::GetRenderSlotId(const string_view renderSlot) const
1240 {
1241     if (const auto iter = renderSlotIds_.nameToId.find(renderSlot); iter != renderSlotIds_.nameToId.cend()) {
1242         return iter->second;
1243     } else {
1244         return INVALID_SM_INDEX;
1245     }
1246 }
1247 
GetRenderSlotId(const RenderHandle & handle) const1248 uint32_t ShaderManager::GetRenderSlotId(const RenderHandle& handle) const
1249 {
1250     uint32_t id = ~0u;
1251     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
1252     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1253     if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1254         if (arrayIndex < computeShaderMappings_.clientData.size()) {
1255             id = computeShaderMappings_.clientData[arrayIndex].renderSlotId;
1256         }
1257     } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
1258         if (arrayIndex < shaderMappings_.clientData.size()) {
1259             id = shaderMappings_.clientData[arrayIndex].renderSlotId;
1260         }
1261     } else if (handleType == RenderHandleType::GRAPHICS_STATE) {
1262         if (arrayIndex < graphicsStates_.data.size()) {
1263             id = graphicsStates_.data[arrayIndex].renderSlotId;
1264         }
1265     }
1266     return id;
1267 }
1268 
GetRenderSlotId(const RenderHandleReference & handle) const1269 uint32_t ShaderManager::GetRenderSlotId(const RenderHandleReference& handle) const
1270 {
1271     return GetRenderSlotId(handle.GetHandle());
1272 }
1273 
GetRenderSlotData(const uint32_t renderSlotId) const1274 IShaderManager::RenderSlotData ShaderManager::GetRenderSlotData(const uint32_t renderSlotId) const
1275 {
1276     if (renderSlotId < static_cast<uint32_t>(renderSlotIds_.data.size())) {
1277         return renderSlotIds_.data[renderSlotId];
1278     } else {
1279         return {};
1280     }
1281 }
1282 
GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle & handle) const1283 RenderHandleReference ShaderManager::GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle& handle) const
1284 {
1285     if (RenderHandleUtil::GetHandleType(handle) == RenderHandleType::SHADER_STATE_OBJECT) {
1286         const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1287         auto& mappings = shaderMappings_;
1288         if (arrayIndex < mappings.clientData.size()) {
1289             const uint32_t vidIndex = mappings.clientData[arrayIndex].vertexInputDeclarationIndex;
1290             if (vidIndex < shaderVid_.rhr.size()) {
1291                 return shaderVid_.rhr[vidIndex];
1292             }
1293         }
1294     }
1295     return {};
1296 }
1297 
GetVertexInputDeclarationHandleByShaderHandle(const RenderHandleReference & handle) const1298 RenderHandleReference ShaderManager::GetVertexInputDeclarationHandleByShaderHandle(
1299     const RenderHandleReference& handle) const
1300 {
1301     return GetVertexInputDeclarationHandleByShaderHandle(handle.GetHandle());
1302 }
1303 
GetVertexInputDeclarationHandle(const string_view path) const1304 RenderHandleReference ShaderManager::GetVertexInputDeclarationHandle(const string_view path) const
1305 {
1306     if (const auto iter = shaderVid_.nameToIndex.find(path); iter != shaderVid_.nameToIndex.cend()) {
1307         if (iter->second < shaderVid_.rhr.size()) {
1308             return shaderVid_.rhr[iter->second];
1309         }
1310     }
1311     PLUGIN_LOG_W("ShaderManager: vertex input declaration not found: %s", path.data());
1312     return {};
1313 }
1314 
GetVertexInputDeclarationView(const RenderHandle & handle) const1315 VertexInputDeclarationView ShaderManager::GetVertexInputDeclarationView(const RenderHandle& handle) const
1316 {
1317     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1318     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1319     if ((type == RenderHandleType::VERTEX_INPUT_DECLARATION) &&
1320         (index < static_cast<uint32_t>(shaderVid_.data.size()))) {
1321         const auto& ref = shaderVid_.data[index];
1322         return {
1323             array_view<const VertexInputDeclaration::VertexInputBindingDescription>(
1324                 ref.bindingDescriptions, ref.bindingDescriptionCount),
1325             array_view<const VertexInputDeclaration::VertexInputAttributeDescription>(
1326                 ref.attributeDescriptions, ref.attributeDescriptionCount),
1327         };
1328     }
1329 #if (RENDER_VALIDATION_ENABLED == 1)
1330     if (RenderHandleUtil::IsValid(handle) && (type != RenderHandleType::VERTEX_INPUT_DECLARATION)) {
1331         PLUGIN_LOG_W("RENDER_VALIDATION: invalid handle type given to GetVertexInputDeclarationView()");
1332     }
1333 #endif
1334     return {};
1335 }
1336 
GetVertexInputDeclarationView(const RenderHandleReference & handle) const1337 VertexInputDeclarationView ShaderManager::GetVertexInputDeclarationView(const RenderHandleReference& handle) const
1338 {
1339     return GetVertexInputDeclarationView(handle.GetHandle());
1340 }
1341 
CreateVertexInputDeclaration(const VertexInputDeclarationCreateInfo & createInfo)1342 RenderHandleReference ShaderManager::CreateVertexInputDeclaration(const VertexInputDeclarationCreateInfo& createInfo)
1343 {
1344     uint32_t arrayIndex = INVALID_SM_INDEX;
1345     if (auto nameIter = shaderVid_.nameToIndex.find(createInfo.path); nameIter != shaderVid_.nameToIndex.end()) {
1346         PLUGIN_ASSERT(nameIter->second < shaderVid_.rhr.size());
1347         arrayIndex = static_cast<uint32_t>(nameIter->second);
1348     }
1349     if (arrayIndex < static_cast<uint32_t>(shaderVid_.data.size())) {
1350         // inside core validation due to being very low info for common users
1351 #if (RENDER_VALIDATION_ENABLED == 1)
1352         PLUGIN_LOG_I("ShaderManager: re-creating vertex input declaration (name %s)", createInfo.path.data());
1353 #endif
1354     } else { // new
1355         arrayIndex = static_cast<uint32_t>(shaderVid_.data.size());
1356         const RenderHandle handle =
1357             RenderHandleUtil::CreateHandle(RenderHandleType::VERTEX_INPUT_DECLARATION, arrayIndex);
1358         shaderVid_.rhr.push_back(
1359             RenderHandleReference(handle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter())));
1360         shaderVid_.data.push_back(VertexInputDeclarationData {});
1361         // NOTE: only updated for new
1362         if (!createInfo.path.empty()) {
1363             shaderVid_.nameToIndex[createInfo.path] = arrayIndex;
1364         }
1365     }
1366 
1367     if (arrayIndex < static_cast<uint32_t>(shaderVid_.data.size())) {
1368         const VertexInputDeclarationView& vertexInputDeclarationView = createInfo.vertexInputDeclarationView;
1369         VertexInputDeclarationData& ref = shaderVid_.data[arrayIndex];
1370         ref.bindingDescriptionCount = (uint32_t)vertexInputDeclarationView.bindingDescriptions.size();
1371         ref.attributeDescriptionCount = (uint32_t)vertexInputDeclarationView.attributeDescriptions.size();
1372 
1373         PLUGIN_ASSERT(ref.bindingDescriptionCount <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
1374         PLUGIN_ASSERT(ref.attributeDescriptionCount <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
1375 
1376         for (uint32_t idx = 0; idx < ref.bindingDescriptionCount; ++idx) {
1377             ref.bindingDescriptions[idx] = vertexInputDeclarationView.bindingDescriptions[idx];
1378         }
1379         for (uint32_t idx = 0; idx < ref.attributeDescriptionCount; ++idx) {
1380             ref.attributeDescriptions[idx] = vertexInputDeclarationView.attributeDescriptions[idx];
1381         }
1382         if (createInfo.renderSlotDefault) {
1383             SetRenderSlotData({ createInfo.renderSlotId, {}, {}, {}, shaderVid_.rhr[arrayIndex] });
1384         }
1385 
1386         PLUGIN_ASSERT(shaderVid_.data.size() == shaderVid_.rhr.size());
1387         return shaderVid_.rhr[arrayIndex];
1388     } else {
1389         return {};
1390     }
1391 }
1392 
GetPipelineLayoutHandleByShaderHandle(const RenderHandle & handle) const1393 RenderHandleReference ShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const
1394 {
1395     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1396     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1397     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1398         auto& mappings = shaderMappings_;
1399         if (arrayIndex < mappings.clientData.size()) {
1400             const uint32_t plIndex = mappings.clientData[arrayIndex].pipelineLayoutIndex;
1401             if (plIndex < static_cast<uint32_t>(pl_.rhr.size())) {
1402                 return pl_.rhr[plIndex];
1403             }
1404         }
1405     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1406         auto& mappings = computeShaderMappings_;
1407         if (arrayIndex < mappings.clientData.size()) {
1408             const uint32_t plIndex = mappings.clientData[arrayIndex].pipelineLayoutIndex;
1409             if (plIndex < static_cast<uint32_t>(pl_.rhr.size())) {
1410                 return pl_.rhr[plIndex];
1411             }
1412         }
1413     }
1414     return {};
1415 }
1416 
GetPipelineLayoutHandleByShaderHandle(const RenderHandleReference & handle) const1417 RenderHandleReference ShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandleReference& handle) const
1418 {
1419     return GetPipelineLayoutHandleByShaderHandle(handle.GetHandle());
1420 }
1421 
GetPipelineLayoutHandle(const string_view path) const1422 RenderHandleReference ShaderManager::GetPipelineLayoutHandle(const string_view path) const
1423 {
1424     if (const auto iter = pl_.nameToIndex.find(path); iter != pl_.nameToIndex.cend()) {
1425         const uint32_t index = iter->second;
1426         if (index < static_cast<uint32_t>(pl_.rhr.size())) {
1427             return pl_.rhr[index];
1428         }
1429     }
1430     PLUGIN_LOG_W("ShaderManager: pipeline layout not found: %s", path.data());
1431     return {};
1432 }
1433 
GetPipelineLayout(const RenderHandle & handle) const1434 PipelineLayout ShaderManager::GetPipelineLayout(const RenderHandle& handle) const
1435 {
1436     return GetPipelineLayoutRef(handle);
1437 }
1438 
GetPipelineLayout(const RenderHandleReference & handle) const1439 PipelineLayout ShaderManager::GetPipelineLayout(const RenderHandleReference& handle) const
1440 {
1441     return GetPipelineLayoutRef(handle.GetHandle());
1442 }
1443 
GetPipelineLayoutRef(const RenderHandle & handle) const1444 const PipelineLayout& ShaderManager::GetPipelineLayoutRef(const RenderHandle& handle) const
1445 {
1446     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1447     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1448     if ((type == RenderHandleType::PIPELINE_LAYOUT) && (index < static_cast<uint32_t>(pl_.data.size()))) {
1449         return pl_.data[index];
1450     } else {
1451 #if (RENDER_VALIDATION_ENABLED == 1)
1452         if (RenderHandleUtil::IsValid(handle) && (type != RenderHandleType::PIPELINE_LAYOUT)) {
1453             PLUGIN_LOG_W("RENDER_VALIDATION: invalid handle type given to GetPipelineLayout()");
1454         }
1455 #endif
1456         return defaultPipelineLayout_;
1457     }
1458 }
1459 
GetReflectionPipelineLayoutHandle(const RenderHandle & handle) const1460 RenderHandleReference ShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const
1461 {
1462     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1463     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1464     uint32_t plIndex = INVALID_SM_INDEX;
1465     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1466         if (arrayIndex < shaderMappings_.clientData.size()) {
1467             plIndex = shaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1468         }
1469     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1470         if (arrayIndex < computeShaderMappings_.clientData.size()) {
1471             plIndex = computeShaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1472         }
1473     }
1474 
1475     if (plIndex < pl_.rhr.size()) {
1476         return pl_.rhr[plIndex];
1477     } else {
1478 #if (RENDER_VALIDATION_ENABLED == 1)
1479         PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionPipelineLayoutHandle");
1480 #endif
1481         return {};
1482     }
1483 }
1484 
GetReflectionPipelineLayoutHandle(const RenderHandleReference & handle) const1485 RenderHandleReference ShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandleReference& handle) const
1486 {
1487     return GetReflectionPipelineLayoutHandle(handle.GetHandle());
1488 }
1489 
GetReflectionPipelineLayout(const RenderHandleReference & handle) const1490 PipelineLayout ShaderManager::GetReflectionPipelineLayout(const RenderHandleReference& handle) const
1491 {
1492     return GetReflectionPipelineLayoutRef(handle.GetHandle());
1493 }
1494 
GetReflectionPipelineLayoutRef(const RenderHandle & handle) const1495 const PipelineLayout& ShaderManager::GetReflectionPipelineLayoutRef(const RenderHandle& handle) const
1496 {
1497     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1498     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1499     uint32_t plIndex = INVALID_SM_INDEX;
1500     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1501         if (arrayIndex < shaderMappings_.clientData.size()) {
1502             plIndex = shaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1503         }
1504     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1505         if (arrayIndex < computeShaderMappings_.clientData.size()) {
1506             plIndex = computeShaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1507         }
1508     }
1509 
1510     if (plIndex < pl_.data.size()) {
1511         return pl_.data[plIndex];
1512     } else {
1513 #if (RENDER_VALIDATION_ENABLED == 1)
1514         PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionPipelineLayout");
1515 #endif
1516         return defaultPipelineLayout_;
1517     }
1518 }
1519 
GetReflectionSpecialization(const RenderHandle & handle) const1520 ShaderSpecializationConstantView ShaderManager::GetReflectionSpecialization(const RenderHandle& handle) const
1521 {
1522     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1523     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1524     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1525         // NOTE: at the moment there might not be availability yet, will be FIXED
1526         if (arrayIndex < shaders_.size()) {
1527             if (shaders_[arrayIndex].gsp) {
1528                 return shaders_[arrayIndex].gsp->GetReflection().shaderSpecializationConstantView;
1529             }
1530         }
1531     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1532         // NOTE: at the moment there might not be availability yet, will be FIXED
1533         if (arrayIndex < computeShaders_.size()) {
1534             if (computeShaders_[arrayIndex].gsp) {
1535                 return computeShaders_[arrayIndex].gsp->GetReflection().shaderSpecializationConstantView;
1536             }
1537         }
1538     }
1539 #if (RENDER_VALIDATION_ENABLED == 1)
1540     PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionSpecialization");
1541 #endif
1542     return defaultSSCV_;
1543 }
1544 
GetReflectionSpecialization(const RenderHandleReference & handle) const1545 ShaderSpecializationConstantView ShaderManager::GetReflectionSpecialization(const RenderHandleReference& handle) const
1546 {
1547     return GetReflectionSpecialization(handle.GetHandle());
1548 }
1549 
GetReflectionVertexInputDeclaration(const RenderHandle & handle) const1550 VertexInputDeclarationView ShaderManager::GetReflectionVertexInputDeclaration(const RenderHandle& handle) const
1551 {
1552     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1553     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1554     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1555         // NOTE: at the moment there might not be availability yet, will be FIXED
1556         if (arrayIndex < shaders_.size()) {
1557             if (shaders_[arrayIndex].gsp) {
1558                 return shaders_[arrayIndex].gsp->GetReflection().vertexInputDeclarationView;
1559             }
1560         }
1561     }
1562 #if (RENDER_VALIDATION_ENABLED == 1)
1563     PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionVertexInputDeclaration");
1564 #endif
1565     return defaultVIDV_;
1566 }
1567 
GetReflectionVertexInputDeclaration(const RenderHandleReference & handle) const1568 VertexInputDeclarationView ShaderManager::GetReflectionVertexInputDeclaration(const RenderHandleReference& handle) const
1569 {
1570     return GetReflectionVertexInputDeclaration(handle.GetHandle());
1571 }
1572 
GetReflectionThreadGroupSize(const RenderHandle & handle) const1573 ShaderThreadGroup ShaderManager::GetReflectionThreadGroupSize(const RenderHandle& handle) const
1574 {
1575     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1576     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1577     if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1578         // NOTE: at the moment there might not be availability yet, will be FIXED
1579         if (arrayIndex < computeShaders_.size()) {
1580             if (computeShaders_[arrayIndex].gsp) {
1581                 const auto& refl = computeShaders_[arrayIndex].gsp->GetReflection();
1582                 return { refl.threadGroupSizeX, refl.threadGroupSizeY, refl.threadGroupSizeZ };
1583             }
1584         }
1585     }
1586 #if (RENDER_VALIDATION_ENABLED == 1)
1587     PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionThreadGroupSize");
1588 #endif
1589     return defaultSTG_;
1590 }
1591 
GetReflectionThreadGroupSize(const RenderHandleReference & handle) const1592 ShaderThreadGroup ShaderManager::GetReflectionThreadGroupSize(const RenderHandleReference& handle) const
1593 {
1594     return GetReflectionThreadGroupSize(handle.GetHandle());
1595 }
1596 
CreatePipelineLayout(const PipelineLayoutCreateInfo & createInfo)1597 RenderHandleReference ShaderManager::CreatePipelineLayout(const PipelineLayoutCreateInfo& createInfo)
1598 {
1599     uint32_t arrayIndex = INVALID_SM_INDEX;
1600     if (auto nameIter = pl_.nameToIndex.find(createInfo.path); nameIter != pl_.nameToIndex.end()) {
1601         if (nameIter->second < pl_.rhr.size()) {
1602             arrayIndex = static_cast<uint32_t>(nameIter->second);
1603         }
1604     }
1605 
1606     if (arrayIndex < static_cast<uint32_t>(pl_.data.size())) { // replace
1607         // inside core validation due to being very low info for common users
1608 #if (RENDER_VALIDATION_ENABLED == 1)
1609         PLUGIN_LOG_I("ShaderManager: re-creating pipeline layout (name %s)", createInfo.path.data());
1610 #endif
1611     } else { // new
1612         arrayIndex = static_cast<uint32_t>(pl_.data.size());
1613         pl_.data.push_back(PipelineLayout {});
1614         // NOTE: only updated for new (should check with re-creation)
1615         if (!createInfo.path.empty()) {
1616             pl_.nameToIndex[createInfo.path] = arrayIndex;
1617         }
1618         pl_.rhr.push_back(RenderHandleReference {});
1619     }
1620 
1621     if (arrayIndex < static_cast<uint32_t>(pl_.data.size())) {
1622         const PipelineLayout& pipelineLayout = createInfo.pipelineLayout;
1623         PipelineLayout& ref = pl_.data[arrayIndex];
1624 #if (RENDER_VALIDATION_ENABLED == 1)
1625         if (pipelineLayout.descriptorSetCount > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT ||
1626             pipelineLayout.pushConstant.byteSize > PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE) {
1627             PLUGIN_LOG_W(
1628                 "Invalid pipeline layout sizes clamped (name:%s). Set count %u <= %u, push constant size %u <= %u",
1629                 createInfo.path.data(), ref.descriptorSetCount, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT,
1630                 pipelineLayout.pushConstant.byteSize, PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE);
1631         }
1632 #endif
1633         ref.pushConstant = pipelineLayout.pushConstant;
1634         ref.descriptorSetCount =
1635             Math::min(PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT, pipelineLayout.descriptorSetCount);
1636         ref.pushConstant.byteSize =
1637             Math::min(PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE, pipelineLayout.pushConstant.byteSize);
1638         uint32_t descriptorSetBitmask = 0;
1639         // can be user generated pipeline layout (i.e. set index might be different than index)
1640         for (const auto& descriptorSetLayout : pipelineLayout.descriptorSetLayouts) {
1641             const uint32_t setIdx = descriptorSetLayout.set;
1642             if (setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
1643                 ref.descriptorSetLayouts[setIdx] = pipelineLayout.descriptorSetLayouts[setIdx];
1644                 descriptorSetBitmask |= (1 << setIdx);
1645             }
1646         }
1647 
1648         const RenderHandle handle =
1649             RenderHandleUtil::CreateHandle(RenderHandleType::PIPELINE_LAYOUT, arrayIndex, 0, descriptorSetBitmask);
1650         pl_.rhr[arrayIndex] = RenderHandleReference(handle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter()));
1651         if (createInfo.renderSlotDefault) {
1652             SetRenderSlotData({ createInfo.renderSlotId, {}, {}, pl_.rhr[arrayIndex], {} });
1653         }
1654         return pl_.rhr[arrayIndex];
1655     } else {
1656         return {};
1657     }
1658 }
1659 
GetGpuComputeProgram(const RenderHandle & handle) const1660 const GpuComputeProgram* ShaderManager::GetGpuComputeProgram(const RenderHandle& handle) const
1661 {
1662     if (!IsComputeShaderFunc(handle)) {
1663         PLUGIN_LOG_E("ShaderManager: invalid compute shader handle");
1664         return nullptr;
1665     }
1666     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1667     if (index < static_cast<uint32_t>(computeShaders_.size())) {
1668         return computeShaders_[index].gsp.get();
1669     } else {
1670         PLUGIN_LOG_E("ShaderManager: invalid compute shader handle");
1671         return nullptr;
1672     }
1673 }
1674 
GetGpuShaderProgram(const RenderHandle & handle) const1675 const GpuShaderProgram* ShaderManager::GetGpuShaderProgram(const RenderHandle& handle) const
1676 {
1677     if (!IsShaderFunc(handle)) {
1678         PLUGIN_LOG_E("ShaderManager: invalid shader handle");
1679         return nullptr;
1680     }
1681     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1682     if (index < static_cast<uint32_t>(shaders_.size())) {
1683         return shaders_[index].gsp.get();
1684     } else {
1685         PLUGIN_LOG_E("ShaderManager: invalid shader handle");
1686         return nullptr;
1687     }
1688 }
1689 
CreateShaderModule(const string_view path,const ShaderModuleCreateInfo & createInfo)1690 uint32_t ShaderManager::CreateShaderModule(const string_view path, const ShaderModuleCreateInfo& createInfo)
1691 {
1692     auto& nameToIdx = shaderModules_.nameToIndex;
1693     auto& modules = shaderModules_.shaderModules;
1694     if (auto iter = nameToIdx.find(path); iter != nameToIdx.end()) {
1695         PLUGIN_ASSERT(iter->second < modules.size());
1696         // inside core validation due to being very low info for common users
1697 #if (RENDER_VALIDATION_ENABLED == 1)
1698         PLUGIN_LOG_I("ShaderManager: re-creating shader module %s", path.data());
1699 #endif
1700         // check that we don't push the same indices multiple times
1701         bool found = false;
1702         for (const auto& ref : pendingAllocations_.recreatedShaderModuleIndices) {
1703             if (ref == iter->second) {
1704                 found = true;
1705                 break;
1706             }
1707         }
1708         if (!found) {
1709             pendingAllocations_.recreatedShaderModuleIndices.push_back(iter->second);
1710         }
1711         deferredDestructions_.shaderModules.push_back({ device_.GetFrameCount(), move(modules[iter->second]) });
1712         modules[iter->second] = device_.CreateShaderModule(createInfo);
1713         return iter->second;
1714     } else {
1715         const auto idx = static_cast<uint32_t>(modules.size());
1716         if (!path.empty()) {
1717             nameToIdx[path] = idx;
1718         }
1719         modules.push_back(device_.CreateShaderModule(createInfo));
1720         return idx;
1721     }
1722 }
1723 
GetShaderModule(const uint32_t index) const1724 ShaderModule* ShaderManager::GetShaderModule(const uint32_t index) const
1725 {
1726     const auto& modules = shaderModules_.shaderModules;
1727     if (index < modules.size()) {
1728         return modules[index].get();
1729     } else {
1730         return nullptr;
1731     }
1732 }
1733 
GetShaderModuleIndex(const string_view path) const1734 uint32_t ShaderManager::GetShaderModuleIndex(const string_view path) const
1735 {
1736     const auto& nameToIdx = shaderModules_.nameToIndex;
1737     if (const auto iter = nameToIdx.find(path); iter != nameToIdx.cend()) {
1738         PLUGIN_ASSERT(iter->second < shaderModules_.shaderModules.size());
1739         return iter->second;
1740     } else {
1741         return INVALID_SM_INDEX;
1742     }
1743 }
1744 
IsComputeShader(const RenderHandleReference & handle) const1745 bool ShaderManager::IsComputeShader(const RenderHandleReference& handle) const
1746 {
1747     return IsComputeShaderFunc(handle.GetHandle());
1748 }
1749 
IsShader(const RenderHandleReference & handle) const1750 bool ShaderManager::IsShader(const RenderHandleReference& handle) const
1751 {
1752     return IsShaderFunc(handle.GetHandle());
1753 }
1754 
LoadShaderFiles(const ShaderFilePathDesc & desc)1755 void ShaderManager::LoadShaderFiles(const ShaderFilePathDesc& desc)
1756 {
1757     if (shaderLoader_) {
1758         shaderLoader_->Load(desc);
1759     }
1760 }
1761 
LoadShaderFile(const string_view uri)1762 void ShaderManager::LoadShaderFile(const string_view uri)
1763 {
1764     if (shaderLoader_ && (!uri.empty())) {
1765         shaderLoader_->LoadFile(uri, false);
1766     }
1767 }
1768 
UnloadShaderFiles(const ShaderFilePathDesc & desc)1769 void ShaderManager::UnloadShaderFiles(const ShaderFilePathDesc& desc) {}
1770 
SaveShaderGraphicsState(const ShaderGraphicsStateSaveInfo & saveInfo)1771 IShaderManager::ShaderOutWriteResult ShaderManager::SaveShaderGraphicsState(const ShaderGraphicsStateSaveInfo& saveInfo)
1772 {
1773     return SaveGraphicsState(saveInfo);
1774 }
1775 
SaveShaderVertexInputDeclaration(const ShaderVertexInputDeclarationsSaveInfo & saveInfo)1776 IShaderManager::ShaderOutWriteResult ShaderManager::SaveShaderVertexInputDeclaration(
1777     const ShaderVertexInputDeclarationsSaveInfo& saveInfo)
1778 {
1779     return SaveVextexInputDeclarations(saveInfo);
1780 }
1781 
SaveShaderPipelineLayout(const ShaderPipelineLayoutSaveInfo & saveInfo)1782 IShaderManager::ShaderOutWriteResult ShaderManager::SaveShaderPipelineLayout(
1783     const ShaderPipelineLayoutSaveInfo& saveInfo)
1784 {
1785     return SavePipelineLayouts(saveInfo);
1786 }
1787 
SaveShaderVariants(const ShaderVariantsSaveInfo & saveInfo)1788 IShaderManager::ShaderOutWriteResult ShaderManager::SaveShaderVariants(const ShaderVariantsSaveInfo& saveInfo)
1789 {
1790     return SaveVariants(saveInfo);
1791 }
1792 
ReloadShaderFile(const string_view uri)1793 void ShaderManager::ReloadShaderFile(const string_view uri)
1794 {
1795     if (shaderLoader_ && (!uri.empty())) {
1796         shaderLoader_->LoadFile(uri, true);
1797         if (const auto iter = nameToClientHandle_.find(uri); iter != nameToClientHandle_.cend()) {
1798             reloadedShaders_.push_back(iter->second);
1799         }
1800     }
1801 }
1802 
GetLastReloadedShaderFrameIndex() const1803 uint64_t ShaderManager::GetLastReloadedShaderFrameIndex() const
1804 {
1805     return lastReloadedShadersFrameIndex_;
1806 }
1807 
GetReloadedShadersForBackend() const1808 BASE_NS::array_view<const ShaderManager::FrameReloadedShaders> ShaderManager::GetReloadedShadersForBackend() const
1809 {
1810     return reloadedShadersForBackend_;
1811 }
1812 
GetShaderFile(const RenderHandleReference & handle) const1813 const BASE_NS::string_view ShaderManager::GetShaderFile(const RenderHandleReference& handle) const
1814 {
1815     if (const auto iter = handleToShaderDataFile_.find(handle.GetHandle()); iter != handleToShaderDataFile_.cend()) {
1816         return iter->second;
1817     }
1818     return {};
1819 }
1820 
GetMaterialMetadata(const RenderHandleReference & handle) const1821 const json::value* ShaderManager::GetMaterialMetadata(const RenderHandleReference& handle) const
1822 {
1823     if (const auto iter = shaderToMetadata_.find(handle.GetHandle()); iter != shaderToMetadata_.end()) {
1824         return &iter->second.json;
1825     }
1826     return nullptr;
1827 }
1828 
DestroyShader(const RenderHandle handle)1829 void ShaderManager::DestroyShader(const RenderHandle handle)
1830 {
1831     PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
1832     PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
1833 
1834     auto eraseIndexData = [](auto& mapStore, const RenderHandle handle) {
1835         if (auto const pos = std::find_if(
1836             mapStore.begin(), mapStore.end(), [handle](auto const& element) { return element.second == handle; });
1837             pos != mapStore.end()) {
1838             mapStore.erase(pos);
1839         }
1840     };
1841 
1842     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1843     if (IsComputeShaderFunc(handle)) {
1844         auto& mappings = computeShaderMappings_;
1845         if ((index < static_cast<uint32_t>(mappings.clientData.size())) &&
1846             (index < static_cast<uint32_t>(mappings.nameData.size()))) {
1847             mappings.clientData[index] = {};
1848             mappings.nameData[index] = {};
1849             eraseIndexData(nameToClientHandle_, handle);
1850             {
1851                 const auto lock = std::lock_guard(pendingMutex_);
1852                 pendingAllocations_.destroyHandles.push_back(handle);
1853             }
1854         }
1855     } else if (IsShaderFunc(handle)) {
1856         auto& mappings = shaderMappings_;
1857         if ((index < static_cast<uint32_t>(mappings.clientData.size())) &&
1858             (index < static_cast<uint32_t>(mappings.nameData.size()))) {
1859             mappings.clientData[index] = {};
1860             mappings.nameData[index] = {};
1861             eraseIndexData(nameToClientHandle_, handle);
1862             {
1863                 const auto lock = std::lock_guard(pendingMutex_);
1864                 pendingAllocations_.destroyHandles.push_back(handle);
1865             }
1866         }
1867     }
1868 }
1869 
Destroy(const RenderHandleReference & handle)1870 void ShaderManager::Destroy(const RenderHandleReference& handle)
1871 {
1872     const RenderHandle rawHandle = handle.GetHandle();
1873     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
1874     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
1875         (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
1876         DestroyShader(rawHandle);
1877     } else if (handleType == RenderHandleType::GRAPHICS_STATE) {
1878         DestroyGraphicsState(rawHandle);
1879     } else if (handleType == RenderHandleType::PIPELINE_LAYOUT) {
1880         DestroyPipelineLayout(rawHandle);
1881     } else if (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) {
1882         DestroyVertexInputDeclaration(rawHandle);
1883     }
1884 }
1885 
DestroyGraphicsState(const RenderHandle handle)1886 void ShaderManager::DestroyGraphicsState(const RenderHandle handle)
1887 {
1888     PLUGIN_ASSERT(graphicsStates_.data.size() == graphicsStates_.rhr.size());
1889     PLUGIN_ASSERT(graphicsStates_.data.size() == graphicsStates_.graphicsStates.size());
1890 
1891     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1892     if ((index < static_cast<uint32_t>(graphicsStates_.rhr.size())) &&
1893         (index < static_cast<uint32_t>(graphicsStates_.data.size())) &&
1894         (index < static_cast<uint32_t>(graphicsStates_.graphicsStates.size()))) {
1895         graphicsStates_.rhr[index] = {};
1896         graphicsStates_.data[index] = {};
1897         graphicsStates_.graphicsStates[index] = {};
1898 
1899         auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
1900             if (auto const pos = std::find_if(
1901                 mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
1902                 pos != mapStore.end()) {
1903                 mapStore.erase(pos);
1904             }
1905         };
1906         eraseIndexData(graphicsStates_.nameToIndex, index);
1907         eraseIndexData(graphicsStates_.hashToIndex, index);
1908         // NOTE: shaderToStates needs to be added
1909     }
1910 }
1911 
DestroyPipelineLayout(const RenderHandle handle)1912 void ShaderManager::DestroyPipelineLayout(const RenderHandle handle)
1913 {
1914     PLUGIN_ASSERT(pl_.data.size() == pl_.rhr.size());
1915 
1916     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1917     if ((index < static_cast<uint32_t>(pl_.rhr.size())) && (index < static_cast<uint32_t>(pl_.data.size()))) {
1918         pl_.rhr[index] = {};
1919         pl_.data[index] = {};
1920 
1921         auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
1922             if (auto const pos = std::find_if(
1923                 mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
1924                 pos != mapStore.end()) {
1925                 mapStore.erase(pos);
1926             }
1927         };
1928         eraseIndexData(pl_.nameToIndex, index);
1929         eraseIndexData(pl_.computeShaderToIndex, index);
1930         eraseIndexData(pl_.shaderToIndex, index);
1931     }
1932 }
1933 
DestroyVertexInputDeclaration(const RenderHandle handle)1934 void ShaderManager::DestroyVertexInputDeclaration(const RenderHandle handle)
1935 {
1936     PLUGIN_ASSERT(shaderVid_.data.size() == shaderVid_.rhr.size());
1937 
1938     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1939     if ((index < static_cast<uint32_t>(shaderVid_.rhr.size())) &&
1940         (index < static_cast<uint32_t>(shaderVid_.data.size()))) {
1941         shaderVid_.rhr[index] = {};
1942         shaderVid_.data[index] = {};
1943 
1944         auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
1945             if (auto const pos = std::find_if(
1946                 mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
1947                 pos != mapStore.end()) {
1948                 mapStore.erase(pos);
1949             }
1950         };
1951         eraseIndexData(shaderVid_.nameToIndex, index);
1952         eraseIndexData(shaderVid_.shaderToIndex, index);
1953     }
1954 }
1955 
GetShaders(const RenderHandleReference & handle,const ShaderStageFlags shaderStageFlags) const1956 vector<RenderHandleReference> ShaderManager::GetShaders(
1957     const RenderHandleReference& handle, const ShaderStageFlags shaderStageFlags) const
1958 {
1959     vector<RenderHandleReference> shaders;
1960     if ((shaderStageFlags &
1961             (CORE_SHADER_STAGE_VERTEX_BIT | CORE_SHADER_STAGE_FRAGMENT_BIT | CORE_SHADER_STAGE_COMPUTE_BIT)) == 0) {
1962         return shaders;
1963     }
1964     const RenderHandleType handleType = handle.GetHandleType();
1965     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(handle.GetHandle());
1966     if (handleType == RenderHandleType::GRAPHICS_STATE) {
1967 #if (RENDER_VALIDATION_ENABLED == 1)
1968         PLUGIN_LOG_W("RENDER_VALIDATION: GetShaders with graphics state handle not supported");
1969 #endif
1970     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) ||
1971                (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION)) {
1972         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT) {
1973             for (const auto& ref : computeShaderMappings_.clientData) {
1974                 if (ref.pipelineLayoutIndex == handleIndex) {
1975                     shaders.push_back(ref.rhr);
1976                 }
1977             }
1978         }
1979         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_ALL_GRAPHICS) {
1980             for (const auto& ref : shaderMappings_.clientData) {
1981                 if (ref.vertexInputDeclarationIndex == handleIndex) {
1982                     shaders.push_back(ref.rhr);
1983                 }
1984             }
1985         }
1986     }
1987     return shaders;
1988 }
1989 
GetShaders(const RenderHandle & handle,const ShaderStageFlags shaderStageFlags) const1990 vector<RenderHandle> ShaderManager::GetShaders(
1991     const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const
1992 {
1993     vector<RenderHandle> shaders;
1994     if ((shaderStageFlags &
1995             (CORE_SHADER_STAGE_VERTEX_BIT | CORE_SHADER_STAGE_FRAGMENT_BIT | CORE_SHADER_STAGE_COMPUTE_BIT)) == 0) {
1996         return shaders;
1997     }
1998     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
1999     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(handle);
2000     if (handleType == RenderHandleType::GRAPHICS_STATE) {
2001 #if (RENDER_VALIDATION_ENABLED == 1)
2002         PLUGIN_LOG_W("RENDER_VALIDATION: GetShaders with graphics state handle not supported");
2003 #endif
2004     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) ||
2005                (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION)) {
2006         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT) {
2007             for (const auto& ref : computeShaderMappings_.clientData) {
2008                 if (ref.pipelineLayoutIndex == handleIndex) {
2009                     shaders.push_back(ref.rhr.GetHandle());
2010                 }
2011             }
2012         }
2013         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_ALL_GRAPHICS) {
2014             for (const auto& ref : shaderMappings_.clientData) {
2015                 if (ref.vertexInputDeclarationIndex == handleIndex) {
2016                     shaders.push_back(ref.rhr.GetHandle());
2017                 }
2018             }
2019         }
2020     }
2021     return shaders;
2022 }
2023 
GetShaders() const2024 vector<RenderHandleReference> ShaderManager::GetShaders() const
2025 {
2026     vector<RenderHandleReference> shaders;
2027     shaders.reserve(computeShaderMappings_.clientData.size() + shaderMappings_.clientData.size());
2028     for (const auto& ref : computeShaderMappings_.clientData) {
2029         if (ref.rhr) {
2030             shaders.push_back(ref.rhr);
2031         }
2032     }
2033     for (const auto& ref : shaderMappings_.clientData) {
2034         if (ref.rhr) {
2035             shaders.push_back(ref.rhr);
2036         }
2037     }
2038     return shaders;
2039 }
2040 
GetGraphicsStates() const2041 vector<RenderHandleReference> ShaderManager::GetGraphicsStates() const
2042 {
2043     vector<RenderHandleReference> states;
2044     states.reserve(graphicsStates_.rhr.size());
2045     for (const auto& ref : graphicsStates_.rhr) {
2046         if (ref) {
2047             states.push_back(ref);
2048         }
2049     }
2050     return states;
2051 }
2052 
GetPipelineLayouts() const2053 vector<RenderHandleReference> ShaderManager::GetPipelineLayouts() const
2054 {
2055     vector<RenderHandleReference> pls;
2056     pls.reserve(pl_.rhr.size());
2057     for (const auto& ref : pl_.rhr) {
2058         if (ref) {
2059             pls.push_back(ref);
2060         }
2061     }
2062     return pls;
2063 }
2064 
GetVertexInputDeclarations() const2065 vector<RenderHandleReference> ShaderManager::GetVertexInputDeclarations() const
2066 {
2067     vector<RenderHandleReference> vids;
2068     vids.reserve(shaderVid_.rhr.size());
2069     for (const auto& ref : shaderVid_.rhr) {
2070         if (ref) {
2071             vids.push_back(ref);
2072         }
2073     }
2074     return vids;
2075 }
2076 
GetShaderIdDesc(const RenderHandle handle) const2077 IShaderManager::IdDesc ShaderManager::GetShaderIdDesc(const RenderHandle handle) const
2078 {
2079     PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
2080     PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
2081     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
2082     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
2083     IdDesc desc;
2084     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
2085         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size())) &&
2086         (index < static_cast<uint32_t>(computeShaderMappings_.nameData.size()))) {
2087         const auto& cdRef = computeShaderMappings_.clientData[index];
2088         const auto& nameRef = computeShaderMappings_.nameData[index];
2089         desc.frameIndex = cdRef.frameIndex;
2090         desc.renderSlot = GetRenderSlotName(cdRef.renderSlotId);
2091         desc.category = GetCategoryName(cdRef.categoryId);
2092         desc.displayName = nameRef.displayName;
2093         desc.path = nameRef.path;
2094         desc.variant = nameRef.variantName;
2095     } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
2096                (index < static_cast<uint32_t>(shaderMappings_.clientData.size())) &&
2097                (index < static_cast<uint32_t>(shaderMappings_.nameData.size()))) {
2098         const auto& cdRef = shaderMappings_.clientData[index];
2099         const auto& nameRef = shaderMappings_.nameData[index];
2100         desc.frameIndex = cdRef.frameIndex;
2101         desc.renderSlot = GetRenderSlotName(cdRef.renderSlotId);
2102         desc.category = GetCategoryName(cdRef.categoryId);
2103         desc.displayName = nameRef.displayName;
2104         desc.path = nameRef.path;
2105         desc.variant = nameRef.variantName;
2106     }
2107     return desc;
2108 }
2109 
GetShaderFrameIndex(const RenderHandle handle) const2110 uint64_t ShaderManager::GetShaderFrameIndex(const RenderHandle handle) const
2111 {
2112     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
2113     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
2114     uint64_t frameIndex = 0;
2115     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
2116         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
2117         frameIndex = computeShaderMappings_.clientData[index].frameIndex;
2118     } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
2119                (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
2120         frameIndex = shaderMappings_.clientData[index].frameIndex;
2121     }
2122     return frameIndex;
2123 }
2124 
GetIdDesc(const RenderHandleReference & handle) const2125 IShaderManager::IdDesc ShaderManager::GetIdDesc(const RenderHandleReference& handle) const
2126 {
2127     auto GetIdDesc = [](const auto& nameToIndex, const auto handleIndex) {
2128         IdDesc desc;
2129         for (const auto& ref : nameToIndex) {
2130             if (ref.second == handleIndex) {
2131                 desc.path = ref.first;
2132             }
2133         }
2134         return desc;
2135     };
2136     const RenderHandle rawHandle = handle.GetHandle();
2137     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
2138     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(rawHandle);
2139     IdDesc desc;
2140     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
2141         (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
2142         desc = GetShaderIdDesc(rawHandle);
2143     } else if ((handleType == RenderHandleType::GRAPHICS_STATE) && (handleIndex < graphicsStates_.rhr.size())) {
2144         desc = GetIdDesc(graphicsStates_.nameToIndex, handleIndex);
2145     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) && (handleIndex < pl_.rhr.size())) {
2146         desc = GetIdDesc(pl_.nameToIndex, handleIndex);
2147     } else if ((handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) && (handleIndex < shaderVid_.rhr.size())) {
2148         desc = GetIdDesc(shaderVid_.nameToIndex, handleIndex);
2149     }
2150     return desc;
2151 }
2152 
GetFrameIndex(const RenderHandleReference & handle) const2153 uint64_t ShaderManager::GetFrameIndex(const RenderHandleReference& handle) const
2154 {
2155     const RenderHandle rawHandle = handle.GetHandle();
2156     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
2157     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(rawHandle);
2158     uint64_t frameIndex = 0;
2159     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
2160         (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
2161         frameIndex = GetShaderFrameIndex(rawHandle);
2162     } else if ((handleType == RenderHandleType::GRAPHICS_STATE) && (handleIndex < graphicsStates_.rhr.size())) {
2163         frameIndex = 0;
2164     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) && (handleIndex < pl_.rhr.size())) {
2165         frameIndex = 0;
2166     } else if ((handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) && (handleIndex < shaderVid_.rhr.size())) {
2167         frameIndex = 0;
2168     }
2169     return frameIndex;
2170 }
2171 
CreateShaderPipelineBinder(const RenderHandleReference & handle,const PipelineLayout & pipelineLayout) const2172 IShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(
2173     const RenderHandleReference& handle, const PipelineLayout& pipelineLayout) const
2174 {
2175     const RenderHandleType type = handle.GetHandleType();
2176     if (handle &&
2177         ((type == RenderHandleType::SHADER_STATE_OBJECT) || (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT))) {
2178         return IShaderPipelineBinder::Ptr { new ShaderPipelineBinder((IShaderManager&)*this, handle, pipelineLayout) };
2179     }
2180     return nullptr;
2181 }
2182 
CreateShaderPipelineBinder(const RenderHandleReference & handle,const RenderHandleReference & plHandle) const2183 IShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(
2184     const RenderHandleReference& handle, const RenderHandleReference& plHandle) const
2185 {
2186     RenderHandleReference finalPlHandle = plHandle;
2187     if (!finalPlHandle) {
2188         finalPlHandle = GetPipelineLayoutHandleByShaderHandle(handle.GetHandle());
2189         if (!finalPlHandle) {
2190             finalPlHandle = GetReflectionPipelineLayoutHandle(handle.GetHandle());
2191         }
2192     }
2193     return CreateShaderPipelineBinder(handle, GetPipelineLayout(finalPlHandle));
2194 }
2195 
CreateShaderPipelineBinder(const RenderHandleReference & handle) const2196 IShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(const RenderHandleReference& handle) const
2197 {
2198     return CreateShaderPipelineBinder(handle, RenderHandleReference {});
2199 }
2200 
GetCompatibilityFlags(const RenderHandle & lhs,const RenderHandle & rhs) const2201 ShaderManager::CompatibilityFlags ShaderManager::GetCompatibilityFlags(
2202     const RenderHandle& lhs, const RenderHandle& rhs) const
2203 {
2204     const RenderHandleType lType = RenderHandleUtil::GetHandleType(lhs);
2205     const RenderHandleType rType = RenderHandleUtil::GetHandleType(rhs);
2206     CompatibilityFlags flags = 0;
2207     // NOTE: only same types supported at the moment
2208     if (lType != rType) {
2209         return flags;
2210     }
2211     if (lType == RenderHandleType::PIPELINE_LAYOUT) {
2212         const PipelineLayout lpl = GetPipelineLayout(lhs);
2213         const PipelineLayout rpl = GetPipelineLayout(rhs);
2214         flags = GetPipelineLayoutCompatibilityFlags(lpl, rpl);
2215     } else if ((lType == RenderHandleType::SHADER_STATE_OBJECT) ||
2216                (lType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT)) {
2217         // first check that given pipeline layout is valid to own reflection
2218         const RenderHandle shaderPlHandle = GetPipelineLayoutHandleByShaderHandle(rhs).GetHandle();
2219         if (RenderHandleUtil::IsValid(shaderPlHandle)) {
2220             const PipelineLayout rpl = GetReflectionPipelineLayoutRef(rhs);
2221             if (rpl.descriptorSetCount > 0) {
2222                 const PipelineLayout shaderPl = GetPipelineLayout(shaderPlHandle);
2223                 flags = GetPipelineLayoutCompatibilityFlags(rpl, shaderPl);
2224             }
2225         } else {
2226             // some shaders do not specify actual pipeline layout, only shader reflection pipeline layout
2227             flags = 1u;
2228         }
2229         // then, compare to lhs with rhs reflection
2230         if (flags != 0) {
2231             const RenderHandle lShaderPlHandle = GetPipelineLayoutHandleByShaderHandle(lhs).GetHandle();
2232             const PipelineLayout lpl = RenderHandleUtil::IsValid(lShaderPlHandle) ? GetPipelineLayout(lShaderPlHandle)
2233                                                                                   : GetReflectionPipelineLayoutRef(lhs);
2234             flags = GetPipelineLayoutCompatibilityFlags(lpl, GetReflectionPipelineLayoutRef(rhs));
2235         }
2236     }
2237     return flags;
2238 }
2239 
GetCompatibilityFlags(const RenderHandleReference & lhs,const RenderHandleReference & rhs) const2240 ShaderManager::CompatibilityFlags ShaderManager::GetCompatibilityFlags(
2241     const RenderHandleReference& lhs, const RenderHandleReference& rhs) const
2242 {
2243     if (lhs && rhs) {
2244         return GetCompatibilityFlags(lhs.GetHandle(), rhs.GetHandle());
2245     } else {
2246         return CompatibilityFlags { 0 };
2247     }
2248 }
2249 
GetForcedGraphicsStateFlags(const RenderHandle & handle) const2250 GraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const RenderHandle& handle) const
2251 {
2252     if (!RenderHandleUtil::IsValid(handle)) {
2253         return 0U; // early out
2254     }
2255 
2256     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
2257     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
2258     GraphicsStateFlags flags { 0u };
2259 
2260     uint32_t graphicsStateIndex = ~0u;
2261     if (type == RenderHandleType::GRAPHICS_STATE) {
2262         graphicsStateIndex = arrayIndex;
2263     } else if ((type == RenderHandleType::SHADER_STATE_OBJECT) &&
2264                (arrayIndex < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
2265         graphicsStateIndex = shaderMappings_.clientData[arrayIndex].graphicsStateIndex;
2266     }
2267 
2268     if (graphicsStateIndex < static_cast<uint32_t>(graphicsStates_.graphicsStates.size())) {
2269         flags = graphicsStates_.data[arrayIndex].stateFlags;
2270     }
2271     return flags;
2272 }
2273 
GetForcedGraphicsStateFlags(const RenderHandleReference & handle) const2274 GraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const RenderHandleReference& handle) const
2275 {
2276     return GetForcedGraphicsStateFlags(handle.GetHandle());
2277 }
2278 
GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const2279 GraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const
2280 {
2281     if (renderSlotId < static_cast<uint32_t>(renderSlotIds_.data.size())) {
2282         return GetForcedGraphicsStateFlags(renderSlotIds_.data[renderSlotId].graphicsState.GetHandle());
2283     }
2284     return 0u;
2285 }
2286 
SetFileManager(IFileManager & fileMgr)2287 void ShaderManager::SetFileManager(IFileManager& fileMgr)
2288 {
2289     fileMgr_ = &fileMgr;
2290     shaderLoader_ = make_unique<ShaderLoader>(*fileMgr_, *this, device_.GetBackendType());
2291 }
2292 
RenderNodeShaderManager(const ShaderManager & shaderMgr)2293 RenderNodeShaderManager::RenderNodeShaderManager(const ShaderManager& shaderMgr) : shaderMgr_(shaderMgr) {}
2294 
GetShaderHandle(const string_view path) const2295 RenderHandle RenderNodeShaderManager::GetShaderHandle(const string_view path) const
2296 {
2297     return shaderMgr_.GetShaderHandle(path).GetHandle();
2298 }
2299 
GetShaderHandle(const string_view path,const string_view variantName) const2300 RenderHandle RenderNodeShaderManager::GetShaderHandle(const string_view path, const string_view variantName) const
2301 {
2302     return shaderMgr_.GetShaderHandle(path, variantName).GetHandle();
2303 }
2304 
GetShaderHandle(const RenderHandle & handle,const uint32_t renderSlotId) const2305 RenderHandle RenderNodeShaderManager::GetShaderHandle(const RenderHandle& handle, const uint32_t renderSlotId) const
2306 {
2307     return shaderMgr_.GetShaderHandle(handle, renderSlotId).GetHandle();
2308 }
2309 
GetShaders(const uint32_t renderSlotId) const2310 vector<RenderHandle> RenderNodeShaderManager::GetShaders(const uint32_t renderSlotId) const
2311 {
2312     return shaderMgr_.GetShaderRawHandles(renderSlotId);
2313 }
2314 
GetGraphicsStateHandle(const string_view path) const2315 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(const string_view path) const
2316 {
2317     return shaderMgr_.GetGraphicsStateHandle(path).GetHandle();
2318 }
2319 
GetGraphicsStateHandle(const string_view path,const string_view variantName) const2320 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(
2321     const string_view path, const string_view variantName) const
2322 {
2323     return shaderMgr_.GetGraphicsStateHandle(path, variantName).GetHandle();
2324 }
2325 
GetGraphicsStateHandle(const RenderHandle & handle,const uint32_t renderSlotId) const2326 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(
2327     const RenderHandle& handle, const uint32_t renderSlotId) const
2328 {
2329     return shaderMgr_.GetGraphicsStateHandle(handle, renderSlotId).GetHandle();
2330 }
2331 
GetGraphicsStateHandleByHash(const uint64_t hash) const2332 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandleByHash(const uint64_t hash) const
2333 {
2334     return shaderMgr_.GetGraphicsStateHandleByHash(hash).GetHandle();
2335 }
2336 
GetGraphicsStateHandleByShaderHandle(const RenderHandle & handle) const2337 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandleByShaderHandle(const RenderHandle& handle) const
2338 {
2339     return shaderMgr_.GetGraphicsStateHandleByShaderHandle(handle).GetHandle();
2340 }
2341 
GetGraphicsState(const RenderHandle & handle) const2342 const GraphicsState& RenderNodeShaderManager::GetGraphicsState(const RenderHandle& handle) const
2343 {
2344     return shaderMgr_.GetGraphicsStateRef(handle);
2345 }
2346 
GetRenderSlotId(const string_view renderSlot) const2347 uint32_t RenderNodeShaderManager::GetRenderSlotId(const string_view renderSlot) const
2348 {
2349     return shaderMgr_.GetRenderSlotId(renderSlot);
2350 }
2351 
GetRenderSlotId(const RenderHandle & handle) const2352 uint32_t RenderNodeShaderManager::GetRenderSlotId(const RenderHandle& handle) const
2353 {
2354     return shaderMgr_.GetRenderSlotId(handle);
2355 }
2356 
GetRenderSlotData(const uint32_t renderSlotId) const2357 IShaderManager::RenderSlotData RenderNodeShaderManager::GetRenderSlotData(const uint32_t renderSlotId) const
2358 {
2359     return shaderMgr_.GetRenderSlotData(renderSlotId);
2360 }
2361 
GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle & handle) const2362 RenderHandle RenderNodeShaderManager::GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle& handle) const
2363 {
2364     return shaderMgr_.GetVertexInputDeclarationHandleByShaderHandle(handle).GetHandle();
2365 }
2366 
GetVertexInputDeclarationHandle(const string_view path) const2367 RenderHandle RenderNodeShaderManager::GetVertexInputDeclarationHandle(const string_view path) const
2368 {
2369     return shaderMgr_.GetVertexInputDeclarationHandle(path).GetHandle();
2370 }
2371 
GetVertexInputDeclarationView(const RenderHandle & handle) const2372 VertexInputDeclarationView RenderNodeShaderManager::GetVertexInputDeclarationView(const RenderHandle& handle) const
2373 {
2374     return shaderMgr_.GetVertexInputDeclarationView(handle);
2375 }
2376 
GetPipelineLayoutHandleByShaderHandle(const RenderHandle & handle) const2377 RenderHandle RenderNodeShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const
2378 {
2379     return shaderMgr_.GetPipelineLayoutHandleByShaderHandle(handle).GetHandle();
2380 }
2381 
GetPipelineLayout(const RenderHandle & handle) const2382 const PipelineLayout& RenderNodeShaderManager::GetPipelineLayout(const RenderHandle& handle) const
2383 {
2384     return shaderMgr_.GetPipelineLayoutRef(handle);
2385 }
2386 
GetPipelineLayoutHandle(const string_view path) const2387 RenderHandle RenderNodeShaderManager::GetPipelineLayoutHandle(const string_view path) const
2388 {
2389     return shaderMgr_.GetPipelineLayoutHandle(path).GetHandle();
2390 }
2391 
GetReflectionPipelineLayoutHandle(const RenderHandle & handle) const2392 RenderHandle RenderNodeShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const
2393 {
2394     return shaderMgr_.GetReflectionPipelineLayoutHandle(handle).GetHandle();
2395 }
2396 
GetReflectionPipelineLayout(const RenderHandle & handle) const2397 const PipelineLayout& RenderNodeShaderManager::GetReflectionPipelineLayout(const RenderHandle& handle) const
2398 {
2399     return shaderMgr_.GetReflectionPipelineLayoutRef(handle);
2400 }
2401 
GetReflectionSpecialization(const RenderHandle & handle) const2402 ShaderSpecializationConstantView RenderNodeShaderManager::GetReflectionSpecialization(const RenderHandle& handle) const
2403 {
2404     return shaderMgr_.GetReflectionSpecialization(handle);
2405 }
2406 
GetReflectionVertexInputDeclaration(const RenderHandle & handle) const2407 VertexInputDeclarationView RenderNodeShaderManager::GetReflectionVertexInputDeclaration(
2408     const RenderHandle& handle) const
2409 {
2410     return shaderMgr_.GetReflectionVertexInputDeclaration(handle);
2411 }
2412 
GetReflectionThreadGroupSize(const RenderHandle & handle) const2413 ShaderThreadGroup RenderNodeShaderManager::GetReflectionThreadGroupSize(const RenderHandle& handle) const
2414 {
2415     return shaderMgr_.GetReflectionThreadGroupSize(handle);
2416 }
2417 
HashGraphicsState(const GraphicsState & graphicsState) const2418 uint64_t RenderNodeShaderManager::HashGraphicsState(const GraphicsState& graphicsState) const
2419 {
2420     return shaderMgr_.HashGraphicsState(graphicsState);
2421 }
2422 
IsValid(const RenderHandle & handle) const2423 bool RenderNodeShaderManager::IsValid(const RenderHandle& handle) const
2424 {
2425     return RenderHandleUtil::IsValid(handle);
2426 }
2427 
IsComputeShader(const RenderHandle & handle) const2428 bool RenderNodeShaderManager::IsComputeShader(const RenderHandle& handle) const
2429 {
2430     return IsComputeShaderFunc(handle);
2431 }
2432 
IsShader(const RenderHandle & handle) const2433 bool RenderNodeShaderManager::IsShader(const RenderHandle& handle) const
2434 {
2435     return IsShaderFunc(handle);
2436 }
2437 
GetShaders(const RenderHandle & handle,const ShaderStageFlags shaderStageFlags) const2438 vector<RenderHandle> RenderNodeShaderManager::GetShaders(
2439     const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const
2440 {
2441     return shaderMgr_.GetShaders(handle, shaderStageFlags);
2442 }
2443 
GetCompatibilityFlags(const RenderHandle & lhs,const RenderHandle & rhs) const2444 IShaderManager::CompatibilityFlags RenderNodeShaderManager::GetCompatibilityFlags(
2445     const RenderHandle& lhs, const RenderHandle& rhs) const
2446 {
2447     return shaderMgr_.GetCompatibilityFlags(lhs, rhs);
2448 }
2449 
GetForcedGraphicsStateFlags(const RenderHandle & handle) const2450 GraphicsStateFlags RenderNodeShaderManager::GetForcedGraphicsStateFlags(const RenderHandle& handle) const
2451 {
2452     return shaderMgr_.GetForcedGraphicsStateFlags(handle);
2453 }
2454 
GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const2455 GraphicsStateFlags RenderNodeShaderManager::GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const
2456 {
2457     return shaderMgr_.GetForcedGraphicsStateFlags(renderSlotId);
2458 }
2459 
GetShaderDataByShaderName(const string_view name) const2460 IShaderManager::ShaderData RenderNodeShaderManager::GetShaderDataByShaderName(const string_view name) const
2461 {
2462     IShaderManager::ShaderData sd;
2463     sd.shader = shaderMgr_.GetShaderHandle(name).GetHandle();
2464     sd.pipelineLayout = shaderMgr_.GetPipelineLayoutHandleByShaderHandle(sd.shader).GetHandle();
2465     if (!RenderHandleUtil::IsValid(sd.pipelineLayout)) {
2466         sd.pipelineLayout = shaderMgr_.GetReflectionPipelineLayoutHandle(sd.shader).GetHandle();
2467     }
2468     sd.pipelineLayoutData = shaderMgr_.GetPipelineLayout(sd.pipelineLayout);
2469     return sd;
2470 }
2471 
GetShaderDataByShaderHandle(const RenderHandle handle) const2472 IShaderManager::ShaderData RenderNodeShaderManager::GetShaderDataByShaderHandle(const RenderHandle handle) const
2473 {
2474     IShaderManager::ShaderData sd;
2475     sd.shader = handle;
2476     sd.pipelineLayout = shaderMgr_.GetPipelineLayoutHandleByShaderHandle(sd.shader).GetHandle();
2477     if (!RenderHandleUtil::IsValid(sd.pipelineLayout)) {
2478         sd.pipelineLayout = shaderMgr_.GetReflectionPipelineLayoutHandle(sd.shader).GetHandle();
2479     }
2480     sd.pipelineLayoutData = shaderMgr_.GetPipelineLayout(sd.pipelineLayout);
2481     return sd;
2482 }
2483 
GetGraphicsShaderDataByShaderHandle(const RenderHandle handle) const2484 IShaderManager::GraphicsShaderData RenderNodeShaderManager::GetGraphicsShaderDataByShaderHandle(
2485     const RenderHandle handle) const
2486 {
2487     IShaderManager::GraphicsShaderData sd;
2488     sd.shader = handle;
2489     sd.graphicsState = shaderMgr_.GetGraphicsStateHandleByShaderHandle(sd.shader).GetHandle();
2490     sd.vertexInputDeclaration = shaderMgr_.GetVertexInputDeclarationHandleByShaderHandle(sd.shader).GetHandle();
2491     sd.pipelineLayout = shaderMgr_.GetPipelineLayoutHandleByShaderHandle(sd.shader).GetHandle();
2492     if (!RenderHandleUtil::IsValid(sd.pipelineLayout)) {
2493         sd.pipelineLayout = shaderMgr_.GetReflectionPipelineLayoutHandle(sd.shader).GetHandle();
2494     }
2495     sd.pipelineLayoutData = shaderMgr_.GetPipelineLayout(sd.pipelineLayout);
2496     return sd;
2497 }
2498 
GetIdDesc(const RenderHandle & handle) const2499 IShaderManager::IdDesc RenderNodeShaderManager::GetIdDesc(const RenderHandle& handle) const
2500 {
2501     return shaderMgr_.GetIdDesc(shaderMgr_.Get(handle));
2502 }
2503 RENDER_END_NAMESPACE()
2504