• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "shader_manager.h"
17 
18 #include <algorithm>
19 #include <cinttypes>
20 #include <cstring>
21 
22 #include <base/containers/array_view.h>
23 #include <core/io/intf_file_manager.h>
24 #include <render/device/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 = (uint32_t)vertexInputDeclarationView.bindingDescriptions.size();
1249         ref.attributeDescriptionCount = (uint32_t)vertexInputDeclarationView.attributeDescriptions.size();
1250 
1251         PLUGIN_ASSERT(ref.bindingDescriptionCount <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
1252         PLUGIN_ASSERT(ref.attributeDescriptionCount <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
1253 
1254         for (uint32_t idx = 0; idx < ref.bindingDescriptionCount; ++idx) {
1255             ref.bindingDescriptions[idx] = vertexInputDeclarationView.bindingDescriptions[idx];
1256         }
1257         for (uint32_t idx = 0; idx < ref.attributeDescriptionCount; ++idx) {
1258             ref.attributeDescriptions[idx] = vertexInputDeclarationView.attributeDescriptions[idx];
1259         }
1260         return shaderVid_.rhr[arrayIndex];
1261     } else {
1262         return {};
1263     }
1264 }
1265 
GetPipelineLayoutHandleByShaderHandle(const RenderHandle & handle) const1266 RenderHandleReference ShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const
1267 {
1268     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1269     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1270     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1271         auto& mappings = shaderMappings_;
1272         if (arrayIndex < mappings.clientData.size()) {
1273             const uint32_t plIndex = mappings.clientData[arrayIndex].pipelineLayoutIndex;
1274             if (plIndex < static_cast<uint32_t>(pl_.rhr.size())) {
1275                 PLUGIN_ASSERT(plIndex < static_cast<uint32_t>(pl_.rhr.size()));
1276                 return pl_.rhr[plIndex];
1277             }
1278         }
1279     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1280         auto& mappings = computeShaderMappings_;
1281         if (arrayIndex < mappings.clientData.size()) {
1282             const uint32_t plIndex = mappings.clientData[arrayIndex].pipelineLayoutIndex;
1283             if (plIndex < static_cast<uint32_t>(pl_.rhr.size())) {
1284                 PLUGIN_ASSERT(plIndex < static_cast<uint32_t>(pl_.rhr.size()));
1285                 return pl_.rhr[plIndex];
1286             }
1287         }
1288     }
1289     return {};
1290 }
1291 
GetPipelineLayoutHandleByShaderHandle(const RenderHandleReference & handle) const1292 RenderHandleReference ShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandleReference& handle) const
1293 {
1294     return GetPipelineLayoutHandleByShaderHandle(handle.GetHandle());
1295 }
1296 
GetPipelineLayoutHandle(const string_view path) const1297 RenderHandleReference ShaderManager::GetPipelineLayoutHandle(const string_view path) const
1298 {
1299     if (const auto iter = pl_.nameToIndex.find(path); iter != pl_.nameToIndex.cend()) {
1300         const uint32_t index = iter->second;
1301         PLUGIN_ASSERT(index < static_cast<uint32_t>(pl_.rhr.size()));
1302         return pl_.rhr[index];
1303     } else {
1304         PLUGIN_LOG_W("ShaderManager: pipeline layout not found: %s", path.data());
1305         return {};
1306     }
1307 }
1308 
GetPipelineLayout(const RenderHandle & handle) const1309 PipelineLayout ShaderManager::GetPipelineLayout(const RenderHandle& handle) const
1310 {
1311     return GetPipelineLayoutRef(handle);
1312 }
1313 
GetPipelineLayout(const RenderHandleReference & handle) const1314 PipelineLayout ShaderManager::GetPipelineLayout(const RenderHandleReference& handle) const
1315 {
1316     return GetPipelineLayoutRef(handle.GetHandle());
1317 }
1318 
GetPipelineLayoutRef(const RenderHandle & handle) const1319 const PipelineLayout& ShaderManager::GetPipelineLayoutRef(const RenderHandle& handle) const
1320 {
1321     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1322     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1323     if ((type == RenderHandleType::PIPELINE_LAYOUT) && (index < static_cast<uint32_t>(pl_.data.size()))) {
1324         return pl_.data[index];
1325     } else {
1326 #if (RENDER_VALIDATION_ENABLED == 1)
1327         if (RenderHandleUtil::IsValid(handle) && (type != RenderHandleType::PIPELINE_LAYOUT)) {
1328             PLUGIN_LOG_W("RENDER_VALIDATION: invalid handle type given to GetPipelineLayout()");
1329         }
1330 #endif
1331         return defaultPipelineLayout_;
1332     }
1333 }
1334 
GetReflectionPipelineLayoutHandle(const RenderHandle & handle) const1335 RenderHandleReference ShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const
1336 {
1337     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1338     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1339     uint32_t plIndex = INVALID_SM_INDEX;
1340     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1341         if (arrayIndex < shaderMappings_.clientData.size()) {
1342             plIndex = shaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1343         }
1344     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1345         if (arrayIndex < computeShaderMappings_.clientData.size()) {
1346             plIndex = computeShaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1347         }
1348     }
1349 
1350     if (plIndex < pl_.data.size()) {
1351         return pl_.rhr[plIndex];
1352     } else {
1353 #if (RENDER_VALIDATION_ENABLED == 1)
1354         PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionPipelineLayoutHandle");
1355 #endif
1356         return {};
1357     }
1358 }
1359 
GetReflectionPipelineLayoutHandle(const RenderHandleReference & handle) const1360 RenderHandleReference ShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandleReference& handle) const
1361 {
1362     return GetReflectionPipelineLayoutHandle(handle.GetHandle());
1363 }
1364 
GetReflectionPipelineLayout(const RenderHandleReference & handle) const1365 PipelineLayout ShaderManager::GetReflectionPipelineLayout(const RenderHandleReference& handle) const
1366 {
1367     return GetReflectionPipelineLayoutRef(handle.GetHandle());
1368 }
1369 
GetReflectionPipelineLayoutRef(const RenderHandle & handle) const1370 const PipelineLayout& ShaderManager::GetReflectionPipelineLayoutRef(const RenderHandle& handle) const
1371 {
1372     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1373     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1374     uint32_t plIndex = INVALID_SM_INDEX;
1375     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1376         if (arrayIndex < shaderMappings_.clientData.size()) {
1377             plIndex = shaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1378         }
1379     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1380         if (arrayIndex < computeShaderMappings_.clientData.size()) {
1381             plIndex = computeShaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
1382         }
1383     }
1384 
1385     if (plIndex < pl_.data.size()) {
1386         return pl_.data[plIndex];
1387     } else {
1388 #if (RENDER_VALIDATION_ENABLED == 1)
1389         PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionPipelineLayout");
1390 #endif
1391         return defaultPipelineLayout_;
1392     }
1393 }
1394 
GetReflectionSpecialization(const RenderHandle & handle) const1395 ShaderSpecializationConstantView ShaderManager::GetReflectionSpecialization(const RenderHandle& handle) const
1396 {
1397     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1398     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1399     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1400         // NOTE: at the moment there might not be availability yet, will be FIXED
1401         if (arrayIndex < shaders_.size()) {
1402             if (shaders_[arrayIndex].gsp) {
1403                 return shaders_[arrayIndex].gsp->GetReflection().shaderSpecializationConstantView;
1404             }
1405         }
1406     } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1407         // NOTE: at the moment there might not be availability yet, will be FIXED
1408         if (arrayIndex < computeShaders_.size()) {
1409             if (computeShaders_[arrayIndex].gsp) {
1410                 return computeShaders_[arrayIndex].gsp->GetReflection().shaderSpecializationConstantView;
1411             }
1412         }
1413     }
1414 #if (RENDER_VALIDATION_ENABLED == 1)
1415     PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionSpecialization");
1416 #endif
1417     return defaultSSCV_;
1418 }
1419 
GetReflectionSpecialization(const RenderHandleReference & handle) const1420 ShaderSpecializationConstantView ShaderManager::GetReflectionSpecialization(const RenderHandleReference& handle) const
1421 {
1422     return GetReflectionSpecialization(handle.GetHandle());
1423 }
1424 
GetReflectionVertexInputDeclaration(const RenderHandle & handle) const1425 VertexInputDeclarationView ShaderManager::GetReflectionVertexInputDeclaration(const RenderHandle& handle) const
1426 {
1427     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1428     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1429     if (type == RenderHandleType::SHADER_STATE_OBJECT) {
1430         // NOTE: at the moment there might not be availability yet, will be FIXED
1431         if (arrayIndex < shaders_.size()) {
1432             if (shaders_[arrayIndex].gsp) {
1433                 return shaders_[arrayIndex].gsp->GetReflection().vertexInputDeclarationView;
1434             }
1435         }
1436     }
1437 #if (RENDER_VALIDATION_ENABLED == 1)
1438     PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionVertexInputDeclaration");
1439 #endif
1440     return defaultVIDV_;
1441 }
1442 
GetReflectionVertexInputDeclaration(const RenderHandleReference & handle) const1443 VertexInputDeclarationView ShaderManager::GetReflectionVertexInputDeclaration(const RenderHandleReference& handle) const
1444 {
1445     return GetReflectionVertexInputDeclaration(handle.GetHandle());
1446 }
1447 
GetReflectionThreadGroupSize(const RenderHandle & handle) const1448 ShaderThreadGroup ShaderManager::GetReflectionThreadGroupSize(const RenderHandle& handle) const
1449 {
1450     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
1451     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
1452     if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
1453         // NOTE: at the moment there might not be availability yet, will be FIXED
1454         if (arrayIndex < computeShaders_.size()) {
1455             if (computeShaders_[arrayIndex].gsp) {
1456                 const auto& refl = computeShaders_[arrayIndex].gsp->GetReflection();
1457                 return { refl.threadGroupSizeX, refl.threadGroupSizeY, refl.threadGroupSizeZ };
1458             }
1459         }
1460     }
1461 #if (RENDER_VALIDATION_ENABLED == 1)
1462     PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionThreadGroupSize");
1463 #endif
1464     return defaultSTG_;
1465 }
1466 
GetReflectionThreadGroupSize(const RenderHandleReference & handle) const1467 ShaderThreadGroup ShaderManager::GetReflectionThreadGroupSize(const RenderHandleReference& handle) const
1468 {
1469     return GetReflectionThreadGroupSize(handle.GetHandle());
1470 }
1471 
CreatePipelineLayout(const PipelineLayoutCreateInfo & createInfo)1472 RenderHandleReference ShaderManager::CreatePipelineLayout(const PipelineLayoutCreateInfo& createInfo)
1473 {
1474     uint32_t arrayIndex = INVALID_SM_INDEX;
1475     if (auto nameIter = pl_.nameToIndex.find(createInfo.path); nameIter != pl_.nameToIndex.end()) {
1476         PLUGIN_ASSERT(nameIter->second < pl_.rhr.size());
1477         arrayIndex = static_cast<uint32_t>(nameIter->second);
1478     }
1479 
1480     if (arrayIndex < static_cast<uint32_t>(pl_.data.size())) { // replace
1481         // inside core validation due to being very low info for common users
1482 #if (RENDER_VALIDATION_ENABLED == 1)
1483         PLUGIN_LOG_I("ShaderManager: re-creating pipeline layout (name %s)", createInfo.path.data());
1484 #endif
1485     } else { // new
1486         arrayIndex = static_cast<uint32_t>(pl_.data.size());
1487         pl_.data.push_back(PipelineLayout {});
1488         // NOTE: only updated for new (should check with re-creation)
1489         if (!createInfo.path.empty()) {
1490             pl_.nameToIndex[createInfo.path] = arrayIndex;
1491         }
1492         pl_.rhr.push_back(RenderHandleReference {});
1493     }
1494 
1495     if (arrayIndex < static_cast<uint32_t>(pl_.data.size())) {
1496         const PipelineLayout& pipelineLayout = createInfo.pipelineLayout;
1497         PipelineLayout& ref = pl_.data[arrayIndex];
1498 #if (RENDER_VALIDATION_ENABLED == 1)
1499         if (pipelineLayout.descriptorSetCount > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT ||
1500             pipelineLayout.pushConstant.byteSize > PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE) {
1501             PLUGIN_LOG_W(
1502                 "Invalid pipeline layout sizes clamped (name:%s). Set count %u <= %u, push constant size %u <= %u",
1503                 createInfo.path.data(), ref.descriptorSetCount, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT,
1504                 pipelineLayout.pushConstant.byteSize, PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE);
1505         }
1506 #endif
1507         ref.pushConstant = pipelineLayout.pushConstant;
1508         ref.descriptorSetCount =
1509             Math::min(PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT, pipelineLayout.descriptorSetCount);
1510         ref.pushConstant.byteSize =
1511             Math::min(PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE, pipelineLayout.pushConstant.byteSize);
1512         uint32_t descriptorSetBitmask = 0;
1513         // can be user generated pipeline layout (i.e. set index might be different than index)
1514         for (uint32_t idx = 0; idx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++idx) {
1515             const uint32_t setIdx = pipelineLayout.descriptorSetLayouts[idx].set;
1516             if (setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
1517                 ref.descriptorSetLayouts[setIdx] = pipelineLayout.descriptorSetLayouts[setIdx];
1518                 descriptorSetBitmask |= (1 << setIdx);
1519             }
1520         }
1521 
1522         const RenderHandle handle =
1523             RenderHandleUtil::CreateHandle(RenderHandleType::PIPELINE_LAYOUT, arrayIndex, 0, descriptorSetBitmask);
1524         pl_.rhr[arrayIndex] = RenderHandleReference(handle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter()));
1525         return pl_.rhr[arrayIndex];
1526     } else {
1527         return {};
1528     }
1529 }
1530 
GetGpuComputeProgram(const RenderHandle & handle) const1531 const GpuComputeProgram* ShaderManager::GetGpuComputeProgram(const RenderHandle& handle) const
1532 {
1533     if (!IsComputeShaderFunc(handle)) {
1534         PLUGIN_LOG_E("ShaderManager: invalid compute shader handle");
1535         return nullptr;
1536     }
1537     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1538     if (index < static_cast<uint32_t>(computeShaders_.size())) {
1539         return computeShaders_[index].gsp.get();
1540     } else {
1541         PLUGIN_LOG_E("ShaderManager: invalid compute shader handle");
1542         return nullptr;
1543     }
1544 }
1545 
GetGpuShaderProgram(const RenderHandle & handle) const1546 const GpuShaderProgram* ShaderManager::GetGpuShaderProgram(const RenderHandle& handle) const
1547 {
1548     if (!IsShaderFunc(handle)) {
1549         PLUGIN_LOG_E("ShaderManager: invalid shader handle");
1550         return nullptr;
1551     }
1552     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1553     if (index < static_cast<uint32_t>(shaders_.size())) {
1554         return shaders_[index].gsp.get();
1555     } else {
1556         PLUGIN_LOG_E("ShaderManager: invalid shader handle");
1557         return nullptr;
1558     }
1559 }
1560 
CreateShaderModule(const string_view path,const ShaderModuleCreateInfo & createInfo)1561 uint32_t ShaderManager::CreateShaderModule(const string_view path, const ShaderModuleCreateInfo& createInfo)
1562 {
1563     auto& nameToIdx = shaderModules_.nameToIndex;
1564     auto& modules = shaderModules_.shaderModules;
1565     if (auto iter = nameToIdx.find(path); iter != nameToIdx.end()) {
1566         PLUGIN_ASSERT(iter->second < modules.size());
1567         // inside core validation due to being very low info for common users
1568 #if (RENDER_VALIDATION_ENABLED == 1)
1569         PLUGIN_LOG_I("ShaderManager: re-creating shader module %s", path.data());
1570 #endif
1571         // check that we don't push the same indices multiple times
1572         bool found = false;
1573         for (const auto& ref : pendingAllocations_.recreatedShaderModuleIndices) {
1574             if (ref == iter->second) {
1575                 found = true;
1576                 break;
1577             }
1578         }
1579         if (!found) {
1580             pendingAllocations_.recreatedShaderModuleIndices.push_back(iter->second);
1581         }
1582         deferredDestructions_.shaderModules.push_back({ device_.GetFrameCount(), move(modules[iter->second]) });
1583         modules[iter->second] = device_.CreateShaderModule(createInfo);
1584         return iter->second;
1585     } else {
1586         const uint32_t idx = static_cast<uint32_t>(modules.size());
1587         if (!path.empty()) {
1588             nameToIdx[path] = idx;
1589         }
1590         modules.push_back(device_.CreateShaderModule(createInfo));
1591         return idx;
1592     }
1593 }
1594 
GetShaderModule(const uint32_t index) const1595 ShaderModule* ShaderManager::GetShaderModule(const uint32_t index) const
1596 {
1597     const auto& modules = shaderModules_.shaderModules;
1598     if (index < modules.size()) {
1599         return modules[index].get();
1600     } else {
1601         return nullptr;
1602     }
1603 }
1604 
GetShaderModuleIndex(const string_view path) const1605 uint32_t ShaderManager::GetShaderModuleIndex(const string_view path) const
1606 {
1607     const auto& nameToIdx = shaderModules_.nameToIndex;
1608     if (const auto iter = nameToIdx.find(path); iter != nameToIdx.cend()) {
1609         PLUGIN_ASSERT(iter->second < shaderModules_.shaderModules.size());
1610         return iter->second;
1611     } else {
1612         return INVALID_SM_INDEX;
1613     }
1614 }
1615 
IsComputeShader(const RenderHandleReference & handle) const1616 bool ShaderManager::IsComputeShader(const RenderHandleReference& handle) const
1617 {
1618     return IsComputeShaderFunc(handle.GetHandle());
1619 }
1620 
IsShader(const RenderHandleReference & handle) const1621 bool ShaderManager::IsShader(const RenderHandleReference& handle) const
1622 {
1623     return IsShaderFunc(handle.GetHandle());
1624 }
1625 
LoadShaderFiles(const ShaderFilePathDesc & desc)1626 void ShaderManager::LoadShaderFiles(const ShaderFilePathDesc& desc)
1627 {
1628     if (shaderLoader_) {
1629         shaderLoader_->Load(desc);
1630     }
1631 }
1632 
LoadShaderFile(const string_view uri)1633 void ShaderManager::LoadShaderFile(const string_view uri)
1634 {
1635     if (shaderLoader_ && (!uri.empty())) {
1636         shaderLoader_->LoadFile(uri, false);
1637     }
1638 }
1639 
UnloadShaderFiles(const ShaderFilePathDesc & desc)1640 void ShaderManager::UnloadShaderFiles(const ShaderFilePathDesc& desc) {}
1641 
ReloadShaderFile(const string_view uri)1642 void ShaderManager::ReloadShaderFile(const string_view uri)
1643 {
1644     if (shaderLoader_ && (!uri.empty())) {
1645         shaderLoader_->LoadFile(uri, true);
1646         if (const auto iter = nameToClientHandle_.find(uri); iter != nameToClientHandle_.cend()) {
1647             reloadedShaders_.push_back(iter->second);
1648         }
1649     }
1650 }
1651 
HasReloadedShaderForBackend() const1652 bool ShaderManager::HasReloadedShaderForBackend() const
1653 {
1654     return !reloadedShadersForBackend_.empty();
1655 }
1656 
GetReloadedShadersForBackend() const1657 BASE_NS::array_view<const RenderHandle> ShaderManager::GetReloadedShadersForBackend() const
1658 {
1659     return reloadedShadersForBackend_;
1660 }
1661 
GetShaderFile(const RenderHandleReference & handle) const1662 const BASE_NS::string_view ShaderManager::GetShaderFile(const RenderHandleReference& handle) const
1663 {
1664     if (const auto iter = handleToShaderDataFile_.find(handle.GetHandle()); iter != handleToShaderDataFile_.cend()) {
1665         return iter->second;
1666     }
1667     return {};
1668 }
1669 
GetMaterialMetadata(const RenderHandleReference & handle) const1670 const json::value* ShaderManager::GetMaterialMetadata(const RenderHandleReference& handle) const
1671 {
1672     if (const auto iter = shaderToMetadata_.find(handle.GetHandle()); iter != shaderToMetadata_.end()) {
1673         return &iter->second.json;
1674     }
1675     return nullptr;
1676 }
1677 
DestroyShader(const RenderHandle handle)1678 void ShaderManager::DestroyShader(const RenderHandle handle)
1679 {
1680     PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
1681     PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
1682 
1683     auto eraseIndexData = [](auto& mapStore, const RenderHandle handle) {
1684         if (auto const pos = std::find_if(
1685             mapStore.begin(), mapStore.end(), [handle](auto const& element) { return element.second == handle; });
1686             pos != mapStore.end()) {
1687             mapStore.erase(pos);
1688         }
1689     };
1690 
1691     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1692     if (IsComputeShaderFunc(handle)) {
1693         auto& mappings = computeShaderMappings_;
1694         if (index < static_cast<uint32_t>(mappings.clientData.size())) {
1695             mappings.clientData[index] = {};
1696             mappings.nameData[index] = {};
1697             eraseIndexData(nameToClientHandle_, handle);
1698             {
1699                 const auto lock = std::lock_guard(pendingMutex_);
1700                 pendingAllocations_.destroyHandles.push_back(handle);
1701             }
1702         }
1703     } else if (IsShaderFunc(handle)) {
1704         auto& mappings = shaderMappings_;
1705         if (index < static_cast<uint32_t>(mappings.clientData.size())) {
1706             mappings.clientData[index] = {};
1707             mappings.nameData[index] = {};
1708             eraseIndexData(nameToClientHandle_, handle);
1709             {
1710                 const auto lock = std::lock_guard(pendingMutex_);
1711                 pendingAllocations_.destroyHandles.push_back(handle);
1712             }
1713         }
1714     }
1715 }
1716 
Destroy(const RenderHandleReference & handle)1717 void ShaderManager::Destroy(const RenderHandleReference& handle)
1718 {
1719     const RenderHandle rawHandle = handle.GetHandle();
1720     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
1721     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
1722         (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
1723         DestroyShader(rawHandle);
1724     } else if (handleType == RenderHandleType::GRAPHICS_STATE) {
1725         DestroyGraphicsState(rawHandle);
1726     } else if (handleType == RenderHandleType::PIPELINE_LAYOUT) {
1727         DestroyPipelineLayout(rawHandle);
1728     } else if (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) {
1729         DestroyVertexInputDeclaration(rawHandle);
1730     }
1731 }
1732 
DestroyGraphicsState(const RenderHandle handle)1733 void ShaderManager::DestroyGraphicsState(const RenderHandle handle)
1734 {
1735     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1736     if (index < static_cast<uint32_t>(graphicsStates_.rhr.size())) {
1737         graphicsStates_.rhr[index] = {};
1738         graphicsStates_.data[index] = {};
1739         graphicsStates_.graphicsStates[index] = {};
1740 
1741         auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
1742             if (auto const pos = std::find_if(
1743                 mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
1744                 pos != mapStore.end()) {
1745                 mapStore.erase(pos);
1746             }
1747         };
1748         eraseIndexData(graphicsStates_.nameToIndex, index);
1749         eraseIndexData(graphicsStates_.hashToIndex, index);
1750         // NOTE: shaderToStates needs to be added
1751     }
1752 }
1753 
DestroyPipelineLayout(const RenderHandle handle)1754 void ShaderManager::DestroyPipelineLayout(const RenderHandle handle)
1755 {
1756     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1757     if (index < static_cast<uint32_t>(pl_.rhr.size())) {
1758         pl_.rhr[index] = {};
1759         pl_.data[index] = {};
1760 
1761         auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
1762             if (auto const pos = std::find_if(
1763                 mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
1764                 pos != mapStore.end()) {
1765                 mapStore.erase(pos);
1766             }
1767         };
1768         eraseIndexData(pl_.nameToIndex, index);
1769         eraseIndexData(pl_.computeShaderToIndex, index);
1770         eraseIndexData(pl_.shaderToIndex, index);
1771     }
1772 }
1773 
DestroyVertexInputDeclaration(const RenderHandle handle)1774 void ShaderManager::DestroyVertexInputDeclaration(const RenderHandle handle)
1775 {
1776     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1777     if (index < static_cast<uint32_t>(shaderVid_.rhr.size())) {
1778         shaderVid_.rhr[index] = {};
1779         shaderVid_.data[index] = {};
1780 
1781         auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
1782             if (auto const pos = std::find_if(
1783                 mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
1784                 pos != mapStore.end()) {
1785                 mapStore.erase(pos);
1786             }
1787         };
1788         eraseIndexData(shaderVid_.nameToIndex, index);
1789         eraseIndexData(shaderVid_.shaderToIndex, index);
1790     }
1791 }
1792 
GetShaders(const RenderHandleReference & handle,const ShaderStageFlags shaderStageFlags) const1793 vector<RenderHandleReference> ShaderManager::GetShaders(
1794     const RenderHandleReference& handle, const ShaderStageFlags shaderStageFlags) const
1795 {
1796     vector<RenderHandleReference> shaders;
1797     if ((shaderStageFlags &
1798             (CORE_SHADER_STAGE_VERTEX_BIT | CORE_SHADER_STAGE_FRAGMENT_BIT | CORE_SHADER_STAGE_COMPUTE_BIT)) == 0) {
1799         return shaders;
1800     }
1801     const RenderHandleType handleType = handle.GetHandleType();
1802     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(handle.GetHandle());
1803     if (handleType == RenderHandleType::GRAPHICS_STATE) {
1804 #if (RENDER_VALIDATION_ENABLED == 1)
1805         PLUGIN_LOG_W("RENDER_VALIDATION: GetShaders with graphics state handle not supported");
1806 #endif
1807     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) ||
1808                (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION)) {
1809         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT) {
1810             for (const auto& ref : computeShaderMappings_.clientData) {
1811                 if (ref.pipelineLayoutIndex == handleIndex) {
1812                     shaders.push_back(ref.rhr);
1813                 }
1814             }
1815         }
1816         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_ALL_GRAPHICS) {
1817             for (const auto& ref : shaderMappings_.clientData) {
1818                 if (ref.vertexInputDeclarationIndex == handleIndex) {
1819                     shaders.push_back(ref.rhr);
1820                 }
1821             }
1822         }
1823     }
1824     return shaders;
1825 }
1826 
GetShaders(const RenderHandle & handle,const ShaderStageFlags shaderStageFlags) const1827 vector<RenderHandle> ShaderManager::GetShaders(
1828     const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const
1829 {
1830     vector<RenderHandle> shaders;
1831     if ((shaderStageFlags &
1832             (CORE_SHADER_STAGE_VERTEX_BIT | CORE_SHADER_STAGE_FRAGMENT_BIT | CORE_SHADER_STAGE_COMPUTE_BIT)) == 0) {
1833         return shaders;
1834     }
1835     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
1836     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(handle);
1837     if (handleType == RenderHandleType::GRAPHICS_STATE) {
1838 #if (RENDER_VALIDATION_ENABLED == 1)
1839         PLUGIN_LOG_W("RENDER_VALIDATION: GetShaders with graphics state handle not supported");
1840 #endif
1841     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) ||
1842                (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION)) {
1843         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT) {
1844             for (const auto& ref : computeShaderMappings_.clientData) {
1845                 if (ref.pipelineLayoutIndex == handleIndex) {
1846                     shaders.push_back(ref.rhr.GetHandle());
1847                 }
1848             }
1849         }
1850         if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_ALL_GRAPHICS) {
1851             for (const auto& ref : shaderMappings_.clientData) {
1852                 if (ref.vertexInputDeclarationIndex == handleIndex) {
1853                     shaders.push_back(ref.rhr.GetHandle());
1854                 }
1855             }
1856         }
1857     }
1858     return shaders;
1859 }
1860 
GetShaders() const1861 vector<RenderHandleReference> ShaderManager::GetShaders() const
1862 {
1863     vector<RenderHandleReference> shaders;
1864     shaders.reserve(computeShaderMappings_.clientData.size() + shaderMappings_.clientData.size());
1865     for (const auto& ref : computeShaderMappings_.clientData) {
1866         if (ref.rhr) {
1867             shaders.push_back(ref.rhr);
1868         }
1869     }
1870     for (const auto& ref : shaderMappings_.clientData) {
1871         if (ref.rhr) {
1872             shaders.push_back(ref.rhr);
1873         }
1874     }
1875     return shaders;
1876 }
1877 
GetGraphicsStates() const1878 vector<RenderHandleReference> ShaderManager::GetGraphicsStates() const
1879 {
1880     vector<RenderHandleReference> states;
1881     states.reserve(graphicsStates_.rhr.size());
1882     for (const auto& ref : graphicsStates_.rhr) {
1883         if (ref) {
1884             states.push_back(ref);
1885         }
1886     }
1887     return states;
1888 }
1889 
GetPipelineLayouts() const1890 vector<RenderHandleReference> ShaderManager::GetPipelineLayouts() const
1891 {
1892     vector<RenderHandleReference> pls;
1893     pls.reserve(pl_.rhr.size());
1894     for (const auto& ref : pl_.rhr) {
1895         if (ref) {
1896             pls.push_back(ref);
1897         }
1898     }
1899     return pls;
1900 }
1901 
GetVertexInputDeclarations() const1902 vector<RenderHandleReference> ShaderManager::GetVertexInputDeclarations() const
1903 {
1904     vector<RenderHandleReference> vids;
1905     vids.reserve(shaderVid_.rhr.size());
1906     for (const auto& ref : shaderVid_.rhr) {
1907         if (ref) {
1908             vids.push_back(ref);
1909         }
1910     }
1911     return vids;
1912 }
1913 
GetShaderIdDesc(const RenderHandle handle) const1914 IShaderManager::IdDesc ShaderManager::GetShaderIdDesc(const RenderHandle handle) const
1915 {
1916     PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
1917     PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
1918     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
1919     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1920     IdDesc desc;
1921     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
1922         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
1923         const auto& cdRef = computeShaderMappings_.clientData[index];
1924         const auto& nameRef = computeShaderMappings_.nameData[index];
1925         desc.frameIndex = cdRef.frameIndex;
1926         desc.renderSlot = GetRenderSlotName(cdRef.renderSlotId);
1927         desc.category = GetCategoryName(cdRef.categoryId);
1928         desc.displayName = nameRef.displayName;
1929         desc.path = nameRef.path;
1930         desc.variant = nameRef.variantName;
1931     } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
1932                (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
1933         const auto& cdRef = shaderMappings_.clientData[index];
1934         const auto& nameRef = shaderMappings_.nameData[index];
1935         desc.frameIndex = cdRef.frameIndex;
1936         desc.renderSlot = GetRenderSlotName(cdRef.renderSlotId);
1937         desc.category = GetCategoryName(cdRef.categoryId);
1938         desc.displayName = nameRef.displayName;
1939         desc.path = nameRef.path;
1940         desc.variant = nameRef.variantName;
1941     }
1942     return desc;
1943 }
1944 
GetShaderFrameIndex(const RenderHandle handle) const1945 uint64_t ShaderManager::GetShaderFrameIndex(const RenderHandle handle) const
1946 {
1947     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
1948     const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
1949     uint64_t frameIndex = 0;
1950     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
1951         (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
1952         frameIndex = computeShaderMappings_.clientData[index].frameIndex;
1953     } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
1954                (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
1955         frameIndex = shaderMappings_.clientData[index].frameIndex;
1956     }
1957     return frameIndex;
1958 }
1959 
GetIdDesc(const RenderHandleReference & handle) const1960 IShaderManager::IdDesc ShaderManager::GetIdDesc(const RenderHandleReference& handle) const
1961 {
1962     auto GetIdDesc = [](const auto& nameToIndex, const auto handleIndex) {
1963         IdDesc desc;
1964         for (const auto& ref : nameToIndex) {
1965             if (ref.second == handleIndex) {
1966                 desc.path = ref.first;
1967             }
1968         }
1969         return desc;
1970     };
1971     const RenderHandle rawHandle = handle.GetHandle();
1972     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
1973     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(rawHandle);
1974     IdDesc desc;
1975     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
1976         (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
1977         desc = GetShaderIdDesc(rawHandle);
1978     } else if ((handleType == RenderHandleType::GRAPHICS_STATE) && (handleIndex < graphicsStates_.rhr.size())) {
1979         desc = GetIdDesc(graphicsStates_.nameToIndex, handleIndex);
1980     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) && (handleIndex < pl_.rhr.size())) {
1981         desc = GetIdDesc(pl_.nameToIndex, handleIndex);
1982     } else if ((handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) && (handleIndex < shaderVid_.rhr.size())) {
1983         desc = GetIdDesc(shaderVid_.nameToIndex, handleIndex);
1984     }
1985     return desc;
1986 }
1987 
GetFrameIndex(const RenderHandleReference & handle) const1988 uint64_t ShaderManager::GetFrameIndex(const RenderHandleReference& handle) const
1989 {
1990     const RenderHandle rawHandle = handle.GetHandle();
1991     const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
1992     const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(rawHandle);
1993     uint64_t frameIndex = 0;
1994     if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
1995         (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
1996         frameIndex = GetShaderFrameIndex(rawHandle);
1997     } else if ((handleType == RenderHandleType::GRAPHICS_STATE) && (handleIndex < graphicsStates_.rhr.size())) {
1998         frameIndex = 0;
1999     } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) && (handleIndex < pl_.rhr.size())) {
2000         frameIndex = 0;
2001     } else if ((handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) && (handleIndex < shaderVid_.rhr.size())) {
2002         frameIndex = 0;
2003     }
2004     return frameIndex;
2005 }
2006 
CreateShaderPipelineBinder(const RenderHandleReference & handle,const PipelineLayout & pipelineLayout) const2007 IShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(
2008     const RenderHandleReference& handle, const PipelineLayout& pipelineLayout) const
2009 {
2010     const RenderHandleType type = handle.GetHandleType();
2011     if (handle &&
2012         ((type == RenderHandleType::SHADER_STATE_OBJECT) || (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT))) {
2013         return IShaderPipelineBinder::Ptr { new ShaderPipelineBinder((IShaderManager&)*this, handle, pipelineLayout) };
2014     }
2015     return nullptr;
2016 }
2017 
CreateShaderPipelineBinder(const RenderHandleReference & handle,const RenderHandleReference & plHandle) const2018 IShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(
2019     const RenderHandleReference& handle, const RenderHandleReference& plHandle) const
2020 {
2021     RenderHandleReference finalPlHandle = plHandle;
2022     if (!finalPlHandle) {
2023         finalPlHandle = GetPipelineLayoutHandleByShaderHandle(handle.GetHandle());
2024         if (!finalPlHandle) {
2025             finalPlHandle = GetReflectionPipelineLayoutHandle(handle.GetHandle());
2026         }
2027     }
2028     return CreateShaderPipelineBinder(handle, GetPipelineLayout(finalPlHandle));
2029 }
2030 
CreateShaderPipelineBinder(const RenderHandleReference & handle) const2031 IShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(const RenderHandleReference& handle) const
2032 {
2033     return CreateShaderPipelineBinder(handle, RenderHandleReference {});
2034 }
2035 
GetCompatibilityFlags(const RenderHandle & lhs,const RenderHandle & rhs) const2036 ShaderManager::CompatibilityFlags ShaderManager::GetCompatibilityFlags(
2037     const RenderHandle& lhs, const RenderHandle& rhs) const
2038 {
2039     const RenderHandleType lType = RenderHandleUtil::GetHandleType(lhs);
2040     const RenderHandleType rType = RenderHandleUtil::GetHandleType(rhs);
2041     CompatibilityFlags flags = 0;
2042     // NOTE: only same types supported at the moment
2043     if (lType == rType) {
2044         if (lType == RenderHandleType::PIPELINE_LAYOUT) {
2045             const PipelineLayout lpl = GetPipelineLayout(lhs);
2046             const PipelineLayout rpl = GetPipelineLayout(rhs);
2047             flags = GetPipelineLayoutCompatibilityFlags(lpl, rpl);
2048         } else if ((lType == RenderHandleType::SHADER_STATE_OBJECT) ||
2049                    (lType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT)) {
2050             // first check that given pipeline layout is valid to own reflection
2051             const RenderHandle shaderPlHandle = GetPipelineLayoutHandleByShaderHandle(rhs).GetHandle();
2052             if (RenderHandleUtil::IsValid(shaderPlHandle)) {
2053                 const PipelineLayout shaderPl = GetPipelineLayout(shaderPlHandle);
2054                 const PipelineLayout rpl = GetReflectionPipelineLayoutRef(rhs);
2055                 if (rpl.descriptorSetCount > 0) {
2056                     flags = GetPipelineLayoutCompatibilityFlags(rpl, shaderPl);
2057                 }
2058             } else {
2059                 // some shaders do not specify actual pipeline layout, only shader reflection pipeline layout
2060                 flags = 1u;
2061             }
2062             // then, compare to lhs with rhs reflection
2063             if (flags != 0) {
2064                 const RenderHandle lShaderPlHandle = GetPipelineLayoutHandleByShaderHandle(lhs).GetHandle();
2065                 const PipelineLayout lpl = RenderHandleUtil::IsValid(lShaderPlHandle)
2066                                                ? GetPipelineLayout(lShaderPlHandle)
2067                                                : GetReflectionPipelineLayoutRef(lhs);
2068                 flags = GetPipelineLayoutCompatibilityFlags(lpl, GetReflectionPipelineLayoutRef(rhs));
2069             }
2070         }
2071     }
2072     return flags;
2073 }
2074 
GetCompatibilityFlags(const RenderHandleReference & lhs,const RenderHandleReference & rhs) const2075 ShaderManager::CompatibilityFlags ShaderManager::GetCompatibilityFlags(
2076     const RenderHandleReference& lhs, const RenderHandleReference& rhs) const
2077 {
2078     if (lhs && rhs) {
2079         return GetCompatibilityFlags(lhs.GetHandle(), rhs.GetHandle());
2080     } else {
2081         return CompatibilityFlags { 0 };
2082     }
2083 }
2084 
GetForcedGraphicsStateFlags(const RenderHandle & handle) const2085 GraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const RenderHandle& handle) const
2086 {
2087     if (!RenderHandleUtil::IsValid(handle)) {
2088         return 0U; // early out
2089     }
2090 
2091     const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
2092     const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
2093     GraphicsStateFlags flags { 0u };
2094 
2095     uint32_t graphicsStateIndex = ~0u;
2096     if (type == RenderHandleType::GRAPHICS_STATE) {
2097         graphicsStateIndex = arrayIndex;
2098     } else if ((type == RenderHandleType::SHADER_STATE_OBJECT) &&
2099                (arrayIndex < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
2100         graphicsStateIndex = shaderMappings_.clientData[arrayIndex].graphicsStateIndex;
2101     }
2102 
2103     if (graphicsStateIndex < static_cast<uint32_t>(graphicsStates_.graphicsStates.size())) {
2104         flags = graphicsStates_.data[arrayIndex].stateFlags;
2105     }
2106     return flags;
2107 }
2108 
GetForcedGraphicsStateFlags(const RenderHandleReference & handle) const2109 GraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const RenderHandleReference& handle) const
2110 {
2111     return GetForcedGraphicsStateFlags(handle.GetHandle());
2112 }
2113 
GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const2114 GraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const
2115 {
2116     if (renderSlotId < static_cast<uint32_t>(renderSlotIds_.data.size())) {
2117         return GetForcedGraphicsStateFlags(renderSlotIds_.data[renderSlotId].graphicsState.GetHandle());
2118     }
2119     return 0u;
2120 }
2121 
SetFileManager(IFileManager & fileMgr)2122 void ShaderManager::SetFileManager(IFileManager& fileMgr)
2123 {
2124     fileMgr_ = &fileMgr;
2125     shaderLoader_ = make_unique<ShaderLoader>(*fileMgr_, *this, device_.GetBackendType());
2126 }
2127 
2128 constexpr uint8_t REFLECTION_TAG[] = { 'r', 'f', 'l', 0 };
2129 struct ReflectionHeader {
2130     uint8_t tag[sizeof(REFLECTION_TAG)];
2131     uint16_t type;
2132     uint16_t offsetPushConstants;
2133     uint16_t offsetSpecializationConstants;
2134     uint16_t offsetDescriptorSets;
2135     uint16_t offsetInputs;
2136     uint16_t offsetLocalSize;
2137 };
2138 
IsValid() const2139 bool ShaderReflectionData::IsValid() const
2140 {
2141     if (reflectionData.size() < sizeof(ReflectionHeader)) {
2142         return false;
2143     }
2144     const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
2145     return memcmp(header.tag, REFLECTION_TAG, sizeof(REFLECTION_TAG)) == 0;
2146 }
2147 
GetStageFlags() const2148 ShaderStageFlags ShaderReflectionData::GetStageFlags() const
2149 {
2150     ShaderStageFlags flags;
2151     const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
2152     flags = header.type;
2153     return flags;
2154 }
2155 
GetPipelineLayout() const2156 PipelineLayout ShaderReflectionData::GetPipelineLayout() const
2157 {
2158     PipelineLayout pipelineLayout;
2159     const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
2160     if (header.offsetPushConstants && header.offsetPushConstants < reflectionData.size()) {
2161         auto ptr = reflectionData.data() + header.offsetPushConstants;
2162         const auto constants = *ptr;
2163         if (constants) {
2164             pipelineLayout.pushConstant.shaderStageFlags = header.type;
2165             pipelineLayout.pushConstant.byteSize = static_cast<uint32_t>(*(ptr + 1) | (*(ptr + 2) << 8));
2166         }
2167     }
2168     if (header.offsetDescriptorSets && header.offsetDescriptorSets < reflectionData.size()) {
2169         auto ptr = reflectionData.data() + header.offsetDescriptorSets;
2170         pipelineLayout.descriptorSetCount = static_cast<uint32_t>(*(ptr) | (*(ptr + 1) << 8));
2171         ptr += 2;
2172         for (auto i = 0u; i < pipelineLayout.descriptorSetCount; ++i) {
2173             // write to correct set location
2174             const uint32_t set = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
2175             PLUGIN_ASSERT(set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT);
2176             auto& layout = pipelineLayout.descriptorSetLayouts[set];
2177             layout.set = set;
2178             ptr += 2;
2179             const auto bindings = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
2180             ptr += 2;
2181             for (auto j = 0u; j < bindings; ++j) {
2182                 DescriptorSetLayoutBinding binding;
2183                 binding.binding = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
2184                 ptr += 2;
2185                 binding.descriptorType = static_cast<DescriptorType>(*ptr | (*(ptr + 1) << 8));
2186                 if ((binding.descriptorType > DescriptorType::CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) &&
2187                     (binding.descriptorType ==
2188                         (DescriptorType::CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE & 0xffff))) {
2189                     binding.descriptorType = DescriptorType::CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE;
2190                 }
2191                 ptr += 2;
2192                 binding.descriptorCount = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
2193                 ptr += 2;
2194                 binding.shaderStageFlags = header.type;
2195                 layout.bindings.push_back(binding);
2196             }
2197         }
2198     }
2199     return pipelineLayout;
2200 }
2201 
GetSpecializationConstants() const2202 vector<ShaderSpecialization::Constant> ShaderReflectionData::GetSpecializationConstants() const
2203 {
2204     vector<ShaderSpecialization::Constant> constants;
2205     const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
2206     if (header.offsetSpecializationConstants && header.offsetSpecializationConstants < reflectionData.size()) {
2207         auto ptr = reflectionData.data() + header.offsetSpecializationConstants;
2208         const auto size = *ptr | *(ptr + 1) << 8 | *(ptr + 2) << 16 | *(ptr + 3) << 24;
2209         ptr += 4;
2210         for (auto i = 0; i < size; ++i) {
2211             ShaderSpecialization::Constant constant;
2212             constant.shaderStage = header.type;
2213             constant.id = static_cast<uint32_t>(*ptr | *(ptr + 1) << 8 | *(ptr + 2) << 16 | *(ptr + 3) << 24);
2214             ptr += 4;
2215             constant.type = static_cast<ShaderSpecialization::Constant::Type>(
2216                 *ptr | *(ptr + 1) << 8 | *(ptr + 2) << 16 | *(ptr + 3) << 24);
2217             ptr += 4;
2218             constant.offset = 0;
2219             constants.push_back(constant);
2220         }
2221     }
2222     return constants;
2223 }
2224 
GetInputDescriptions() const2225 vector<VertexInputDeclaration::VertexInputAttributeDescription> ShaderReflectionData::GetInputDescriptions() const
2226 {
2227     vector<VertexInputDeclaration::VertexInputAttributeDescription> inputs;
2228     const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
2229     if (header.offsetInputs && header.offsetInputs < reflectionData.size()) {
2230         auto ptr = reflectionData.data() + header.offsetInputs;
2231         const auto size = *(ptr) | (*(ptr + 1) << 8);
2232         ptr += 2;
2233         for (auto i = 0; i < size; ++i) {
2234             VertexInputDeclaration::VertexInputAttributeDescription desc;
2235             desc.location = static_cast<uint32_t>(*(ptr) | (*(ptr + 1) << 8));
2236             ptr += 2;
2237             desc.binding = desc.location;
2238             desc.format = static_cast<Format>(*(ptr) | (*(ptr + 1) << 8));
2239             ptr += 2;
2240             desc.offset = 0;
2241             inputs.push_back(desc);
2242         }
2243     }
2244     return inputs;
2245 }
2246 
GetLocalSize() const2247 Math::UVec3 ShaderReflectionData::GetLocalSize() const
2248 {
2249     Math::UVec3 sizes;
2250     const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
2251     if (header.offsetLocalSize && header.offsetLocalSize < reflectionData.size()) {
2252         auto ptr = reflectionData.data() + header.offsetLocalSize;
2253         sizes.x = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8) | (*(ptr + 2)) << 16 | (*(ptr + 3)) << 24);
2254         ptr += 4;
2255         sizes.y = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8) | (*(ptr + 2)) << 16 | (*(ptr + 3)) << 24);
2256         ptr += 4;
2257         sizes.z = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8) | (*(ptr + 2)) << 16 | (*(ptr + 3)) << 24);
2258     }
2259     return sizes;
2260 }
2261 
GetPushConstants() const2262 const uint8_t* ShaderReflectionData::GetPushConstants() const
2263 {
2264     const uint8_t* ptr = nullptr;
2265     const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
2266     if (header.offsetPushConstants && header.offsetPushConstants < reflectionData.size()) {
2267         const auto constants = *(reflectionData.data() + header.offsetPushConstants);
2268         if (constants) {
2269             // number of constants is uint8 and the size of the constant is uint16
2270             ptr = reflectionData.data() + header.offsetPushConstants + sizeof(uint8_t) + sizeof(uint16_t);
2271         }
2272     }
2273     return ptr;
2274 }
2275 
RenderNodeShaderManager(const ShaderManager & shaderMgr)2276 RenderNodeShaderManager::RenderNodeShaderManager(const ShaderManager& shaderMgr) : shaderMgr_(shaderMgr) {}
2277 
GetShaderHandle(const string_view path) const2278 RenderHandle RenderNodeShaderManager::GetShaderHandle(const string_view path) const
2279 {
2280     return shaderMgr_.GetShaderHandle(path).GetHandle();
2281 }
2282 
GetShaderHandle(const string_view path,const string_view variantName) const2283 RenderHandle RenderNodeShaderManager::GetShaderHandle(const string_view path, const string_view variantName) const
2284 {
2285     return shaderMgr_.GetShaderHandle(path, variantName).GetHandle();
2286 }
2287 
GetShaderHandle(const RenderHandle & handle,const uint32_t renderSlotId) const2288 RenderHandle RenderNodeShaderManager::GetShaderHandle(const RenderHandle& handle, const uint32_t renderSlotId) const
2289 {
2290     return shaderMgr_.GetShaderHandle(handle, renderSlotId).GetHandle();
2291 }
2292 
GetShaders(const uint32_t renderSlotId) const2293 vector<RenderHandle> RenderNodeShaderManager::GetShaders(const uint32_t renderSlotId) const
2294 {
2295     return shaderMgr_.GetShaderRawHandles(renderSlotId);
2296 }
2297 
GetGraphicsStateHandle(const string_view path) const2298 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(const string_view path) const
2299 {
2300     return shaderMgr_.GetGraphicsStateHandle(path).GetHandle();
2301 }
2302 
GetGraphicsStateHandle(const string_view path,const string_view variantName) const2303 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(
2304     const string_view path, const string_view variantName) const
2305 {
2306     return shaderMgr_.GetGraphicsStateHandle(path, variantName).GetHandle();
2307 }
2308 
GetGraphicsStateHandle(const RenderHandle & handle,const uint32_t renderSlotId) const2309 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(
2310     const RenderHandle& handle, const uint32_t renderSlotId) const
2311 {
2312     return shaderMgr_.GetGraphicsStateHandle(handle, renderSlotId).GetHandle();
2313 }
2314 
GetGraphicsStateHandleByHash(const uint64_t hash) const2315 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandleByHash(const uint64_t hash) const
2316 {
2317     return shaderMgr_.GetGraphicsStateHandleByHash(hash).GetHandle();
2318 }
2319 
GetGraphicsStateHandleByShaderHandle(const RenderHandle & handle) const2320 RenderHandle RenderNodeShaderManager::GetGraphicsStateHandleByShaderHandle(const RenderHandle& handle) const
2321 {
2322     return shaderMgr_.GetGraphicsStateHandleByShaderHandle(handle).GetHandle();
2323 }
2324 
GetGraphicsState(const RenderHandle & handle) const2325 const GraphicsState& RenderNodeShaderManager::GetGraphicsState(const RenderHandle& handle) const
2326 {
2327     return shaderMgr_.GetGraphicsStateRef(handle);
2328 }
2329 
GetRenderSlotId(const string_view renderSlot) const2330 uint32_t RenderNodeShaderManager::GetRenderSlotId(const string_view renderSlot) const
2331 {
2332     return shaderMgr_.GetRenderSlotId(renderSlot);
2333 }
2334 
GetRenderSlotId(const RenderHandle & handle) const2335 uint32_t RenderNodeShaderManager::GetRenderSlotId(const RenderHandle& handle) const
2336 {
2337     return shaderMgr_.GetRenderSlotId(handle);
2338 }
2339 
GetRenderSlotData(const uint32_t renderSlotId) const2340 IShaderManager::RenderSlotData RenderNodeShaderManager::GetRenderSlotData(const uint32_t renderSlotId) const
2341 {
2342     return shaderMgr_.GetRenderSlotData(renderSlotId);
2343 }
2344 
GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle & handle) const2345 RenderHandle RenderNodeShaderManager::GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle& handle) const
2346 {
2347     return shaderMgr_.GetVertexInputDeclarationHandleByShaderHandle(handle).GetHandle();
2348 }
2349 
GetVertexInputDeclarationHandle(const string_view path) const2350 RenderHandle RenderNodeShaderManager::GetVertexInputDeclarationHandle(const string_view path) const
2351 {
2352     return shaderMgr_.GetVertexInputDeclarationHandle(path).GetHandle();
2353 }
2354 
GetVertexInputDeclarationView(const RenderHandle & handle) const2355 VertexInputDeclarationView RenderNodeShaderManager::GetVertexInputDeclarationView(const RenderHandle& handle) const
2356 {
2357     return shaderMgr_.GetVertexInputDeclarationView(handle);
2358 }
2359 
GetPipelineLayoutHandleByShaderHandle(const RenderHandle & handle) const2360 RenderHandle RenderNodeShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const
2361 {
2362     return shaderMgr_.GetPipelineLayoutHandleByShaderHandle(handle).GetHandle();
2363 }
2364 
GetPipelineLayout(const RenderHandle & handle) const2365 const PipelineLayout& RenderNodeShaderManager::GetPipelineLayout(const RenderHandle& handle) const
2366 {
2367     return shaderMgr_.GetPipelineLayoutRef(handle);
2368 }
2369 
GetPipelineLayoutHandle(const string_view path) const2370 RenderHandle RenderNodeShaderManager::GetPipelineLayoutHandle(const string_view path) const
2371 {
2372     return shaderMgr_.GetPipelineLayoutHandle(path).GetHandle();
2373 }
2374 
GetReflectionPipelineLayoutHandle(const RenderHandle & handle) const2375 RenderHandle RenderNodeShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const
2376 {
2377     return shaderMgr_.GetReflectionPipelineLayoutHandle(handle).GetHandle();
2378 }
2379 
GetReflectionPipelineLayout(const RenderHandle & handle) const2380 const PipelineLayout& RenderNodeShaderManager::GetReflectionPipelineLayout(const RenderHandle& handle) const
2381 {
2382     return shaderMgr_.GetReflectionPipelineLayoutRef(handle);
2383 }
2384 
GetReflectionSpecialization(const RenderHandle & handle) const2385 ShaderSpecializationConstantView RenderNodeShaderManager::GetReflectionSpecialization(const RenderHandle& handle) const
2386 {
2387     return shaderMgr_.GetReflectionSpecialization(handle);
2388 }
2389 
GetReflectionVertexInputDeclaration(const RenderHandle & handle) const2390 VertexInputDeclarationView RenderNodeShaderManager::GetReflectionVertexInputDeclaration(
2391     const RenderHandle& handle) const
2392 {
2393     return shaderMgr_.GetReflectionVertexInputDeclaration(handle);
2394 }
2395 
GetReflectionThreadGroupSize(const RenderHandle & handle) const2396 ShaderThreadGroup RenderNodeShaderManager::GetReflectionThreadGroupSize(const RenderHandle& handle) const
2397 {
2398     return shaderMgr_.GetReflectionThreadGroupSize(handle);
2399 }
2400 
HashGraphicsState(const GraphicsState & graphicsState) const2401 uint64_t RenderNodeShaderManager::HashGraphicsState(const GraphicsState& graphicsState) const
2402 {
2403     return shaderMgr_.HashGraphicsState(graphicsState);
2404 }
2405 
IsValid(const RenderHandle & handle) const2406 bool RenderNodeShaderManager::IsValid(const RenderHandle& handle) const
2407 {
2408     return RenderHandleUtil::IsValid(handle);
2409 }
2410 
IsComputeShader(const RenderHandle & handle) const2411 bool RenderNodeShaderManager::IsComputeShader(const RenderHandle& handle) const
2412 {
2413     return IsComputeShaderFunc(handle);
2414 }
2415 
IsShader(const RenderHandle & handle) const2416 bool RenderNodeShaderManager::IsShader(const RenderHandle& handle) const
2417 {
2418     return IsShaderFunc(handle);
2419 }
2420 
GetShaders(const RenderHandle & handle,const ShaderStageFlags shaderStageFlags) const2421 vector<RenderHandle> RenderNodeShaderManager::GetShaders(
2422     const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const
2423 {
2424     return shaderMgr_.GetShaders(handle, shaderStageFlags);
2425 }
2426 
GetCompatibilityFlags(const RenderHandle & lhs,const RenderHandle & rhs) const2427 IShaderManager::CompatibilityFlags RenderNodeShaderManager::GetCompatibilityFlags(
2428     const RenderHandle& lhs, const RenderHandle& rhs) const
2429 {
2430     return shaderMgr_.GetCompatibilityFlags(lhs, rhs);
2431 }
2432 
GetForcedGraphicsStateFlags(const RenderHandle & handle) const2433 GraphicsStateFlags RenderNodeShaderManager::GetForcedGraphicsStateFlags(const RenderHandle& handle) const
2434 {
2435     return shaderMgr_.GetForcedGraphicsStateFlags(handle);
2436 }
2437 
GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const2438 GraphicsStateFlags RenderNodeShaderManager::GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const
2439 {
2440     return shaderMgr_.GetForcedGraphicsStateFlags(renderSlotId);
2441 }
2442 RENDER_END_NAMESPACE()
2443