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