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