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