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