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