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