18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci
168bf80f4bSopenharmony_ci#include "shader_manager.h"
178bf80f4bSopenharmony_ci
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci#include <cinttypes>
208bf80f4bSopenharmony_ci#include <cstring>
218bf80f4bSopenharmony_ci
228bf80f4bSopenharmony_ci#include <base/containers/array_view.h>
238bf80f4bSopenharmony_ci#include <core/io/intf_file_manager.h>
248bf80f4bSopenharmony_ci#include <render/device/gpu_resource_desc.h>
258bf80f4bSopenharmony_ci#include <render/device/pipeline_layout_desc.h>
268bf80f4bSopenharmony_ci#include <render/namespace.h>
278bf80f4bSopenharmony_ci
288bf80f4bSopenharmony_ci#include "device/device.h"
298bf80f4bSopenharmony_ci#include "device/gpu_program.h"
308bf80f4bSopenharmony_ci#include "device/gpu_program_util.h"
318bf80f4bSopenharmony_ci#include "device/gpu_resource_handle_util.h"
328bf80f4bSopenharmony_ci#include "device/shader_module.h"
338bf80f4bSopenharmony_ci#include "device/shader_pipeline_binder.h"
348bf80f4bSopenharmony_ci#include "loader/shader_loader.h"
358bf80f4bSopenharmony_ci#include "resource_handle_impl.h"
368bf80f4bSopenharmony_ci#include "util/log.h"
378bf80f4bSopenharmony_ci
388bf80f4bSopenharmony_ciusing namespace BASE_NS;
398bf80f4bSopenharmony_ciusing namespace CORE_NS;
408bf80f4bSopenharmony_ci
418bf80f4bSopenharmony_ciconstexpr uint64_t IA_HASH_PRIMITIVE_TOPOLOGY_SHIFT = 1;
428bf80f4bSopenharmony_ci
438bf80f4bSopenharmony_ciconstexpr uint64_t RS_HASH_POLYGON_MODE_SHIFT = 4;
448bf80f4bSopenharmony_ciconstexpr uint64_t RS_HASH_CULL_MODE_SHIFT = 8;
458bf80f4bSopenharmony_ciconstexpr uint64_t RS_HASH_FRONT_FACE_SHIFT = 12;
468bf80f4bSopenharmony_ci
478bf80f4bSopenharmony_ciconstexpr uint64_t DSS_HASH_DEPTH_COMPARE_SHIFT = 4;
488bf80f4bSopenharmony_ci
498bf80f4bSopenharmony_ciconstexpr uint64_t HASH_RS_SHIFT = 0;
508bf80f4bSopenharmony_ciconstexpr uint64_t HASH_DS_SHIFT = 32;
518bf80f4bSopenharmony_ciconstexpr uint64_t HASH_IA_SHIFT = 56;
528bf80f4bSopenharmony_ci
538bf80f4bSopenharmony_ciunion FloatAsUint32 {
548bf80f4bSopenharmony_ci    float f;
558bf80f4bSopenharmony_ci    uint32_t ui;
568bf80f4bSopenharmony_ci};
578bf80f4bSopenharmony_ci
588bf80f4bSopenharmony_citemplate<>
598bf80f4bSopenharmony_ciuint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::InputAssembly& inputAssembly)
608bf80f4bSopenharmony_ci{
618bf80f4bSopenharmony_ci    uint64_t hash = 0;
628bf80f4bSopenharmony_ci    hash |= static_cast<uint64_t>(inputAssembly.enablePrimitiveRestart);
638bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(inputAssembly.primitiveTopology) << IA_HASH_PRIMITIVE_TOPOLOGY_SHIFT);
648bf80f4bSopenharmony_ci    return hash;
658bf80f4bSopenharmony_ci}
668bf80f4bSopenharmony_ci
678bf80f4bSopenharmony_citemplate<>
688bf80f4bSopenharmony_ciuint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::RasterizationState& state)
698bf80f4bSopenharmony_ci{
708bf80f4bSopenharmony_ci    uint64_t hash = 0;
718bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.enableRasterizerDiscard) << 2u) |
728bf80f4bSopenharmony_ci            (static_cast<uint64_t>(state.enableDepthBias) << 1u) | static_cast<uint64_t>(state.enableDepthClamp);
738bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.polygonMode) << RS_HASH_POLYGON_MODE_SHIFT);
748bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.cullModeFlags) << RS_HASH_CULL_MODE_SHIFT);
758bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.frontFace) << RS_HASH_FRONT_FACE_SHIFT);
768bf80f4bSopenharmony_ci    return hash;
778bf80f4bSopenharmony_ci}
788bf80f4bSopenharmony_ci
798bf80f4bSopenharmony_citemplate<>
808bf80f4bSopenharmony_ciuint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::DepthStencilState& state)
818bf80f4bSopenharmony_ci{
828bf80f4bSopenharmony_ci    uint64_t hash = 0;
838bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.enableStencilTest) << 3u) |
848bf80f4bSopenharmony_ci            (static_cast<uint64_t>(state.enableDepthBoundsTest) << 2u) |
858bf80f4bSopenharmony_ci            (static_cast<uint64_t>(state.enableDepthWrite) << 1u) | static_cast<uint64_t>(state.enableDepthTest);
868bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.depthCompareOp) << DSS_HASH_DEPTH_COMPARE_SHIFT);
878bf80f4bSopenharmony_ci    return hash;
888bf80f4bSopenharmony_ci}
898bf80f4bSopenharmony_ci
908bf80f4bSopenharmony_citemplate<>
918bf80f4bSopenharmony_ciuint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::ColorBlendState::Attachment& state)
928bf80f4bSopenharmony_ci{
938bf80f4bSopenharmony_ci    uint64_t hash = 0;
948bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.enableBlend) << 0u);
958bf80f4bSopenharmony_ci    // blend factor values 0 - 18, 0x1f for exact (5 bits)
968bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.srcColorBlendFactor) << 1u);
978bf80f4bSopenharmony_ci    hash |= ((static_cast<uint64_t>(state.dstColorBlendFactor) & 0x1f) << 6u);
988bf80f4bSopenharmony_ci    hash |= ((static_cast<uint64_t>(state.srcAlphaBlendFactor) & 0x1f) << 12u);
998bf80f4bSopenharmony_ci    hash |= ((static_cast<uint64_t>(state.dstAlphaBlendFactor) & 0x1f) << 18u);
1008bf80f4bSopenharmony_ci    // blend op values 0 - 4, 0x7 for exact (3 bits)
1018bf80f4bSopenharmony_ci    hash |= ((static_cast<uint64_t>(state.colorBlendOp) & 0x7) << 24u);
1028bf80f4bSopenharmony_ci    hash |= ((static_cast<uint64_t>(state.alphaBlendOp) & 0x7) << 28u);
1038bf80f4bSopenharmony_ci    return hash;
1048bf80f4bSopenharmony_ci}
1058bf80f4bSopenharmony_ci
1068bf80f4bSopenharmony_citemplate<>
1078bf80f4bSopenharmony_ciuint64_t BASE_NS::hash(const RENDER_NS::GraphicsState::ColorBlendState& state)
1088bf80f4bSopenharmony_ci{
1098bf80f4bSopenharmony_ci    uint64_t hash = 0;
1108bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.enableLogicOp) << 0u);
1118bf80f4bSopenharmony_ci    hash |= (static_cast<uint64_t>(state.logicOp) << 1u);
1128bf80f4bSopenharmony_ci
1138bf80f4bSopenharmony_ci    FloatAsUint32 vec[4u] = { { state.colorBlendConstants[0u] }, { state.colorBlendConstants[1u] },
1148bf80f4bSopenharmony_ci        { state.colorBlendConstants[2u] }, { state.colorBlendConstants[3u] } };
1158bf80f4bSopenharmony_ci    const uint64_t hashRG = (static_cast<uint64_t>(vec[0u].ui) << 32) | (vec[1u].ui);
1168bf80f4bSopenharmony_ci    const uint64_t hashBA = (static_cast<uint64_t>(vec[2u].ui) << 32) | (vec[3u].ui);
1178bf80f4bSopenharmony_ci    HashCombine(hash, hashRG, hashBA);
1188bf80f4bSopenharmony_ci    for (uint32_t idx = 0; idx < state.colorAttachmentCount; ++idx) {
1198bf80f4bSopenharmony_ci        HashCombine(hash, state.colorAttachments[idx]);
1208bf80f4bSopenharmony_ci    }
1218bf80f4bSopenharmony_ci    return hash;
1228bf80f4bSopenharmony_ci}
1238bf80f4bSopenharmony_ci
1248bf80f4bSopenharmony_citemplate<>
1258bf80f4bSopenharmony_ciuint64_t BASE_NS::hash(const RENDER_NS::GraphicsState& state)
1268bf80f4bSopenharmony_ci{
1278bf80f4bSopenharmony_ci    const uint64_t iaHash = hash(state.inputAssembly);
1288bf80f4bSopenharmony_ci    const uint64_t rsHash = hash(state.rasterizationState);
1298bf80f4bSopenharmony_ci    const uint64_t dsHash = hash(state.depthStencilState);
1308bf80f4bSopenharmony_ci    const uint64_t cbsHash = hash(state.colorBlendState);
1318bf80f4bSopenharmony_ci    uint64_t finalHash = (iaHash << HASH_IA_SHIFT) | (rsHash << HASH_RS_SHIFT) | (dsHash << HASH_DS_SHIFT);
1328bf80f4bSopenharmony_ci    HashCombine(finalHash, cbsHash);
1338bf80f4bSopenharmony_ci    return finalHash;
1348bf80f4bSopenharmony_ci}
1358bf80f4bSopenharmony_ci
1368bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE()
1378bf80f4bSopenharmony_cinamespace {
1388bf80f4bSopenharmony_ciconstexpr inline bool IsUniformBuffer(const DescriptorType descriptorType)
1398bf80f4bSopenharmony_ci{
1408bf80f4bSopenharmony_ci    return ((descriptorType == CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
1418bf80f4bSopenharmony_ci            (descriptorType == CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER));
1428bf80f4bSopenharmony_ci}
1438bf80f4bSopenharmony_ciconstexpr inline bool IsStorageBuffer(const DescriptorType descriptorType)
1448bf80f4bSopenharmony_ci{
1458bf80f4bSopenharmony_ci    return ((descriptorType == CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) ||
1468bf80f4bSopenharmony_ci            (descriptorType == CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER));
1478bf80f4bSopenharmony_ci}
1488bf80f4bSopenharmony_ci
1498bf80f4bSopenharmony_ciShaderManager::CompatibilityFlags GetPipelineLayoutCompatibilityFlags(
1508bf80f4bSopenharmony_ci    const PipelineLayout& lhs, const PipelineLayout& rhs)
1518bf80f4bSopenharmony_ci{
1528bf80f4bSopenharmony_ci    ShaderManager::CompatibilityFlags flags = ShaderManager::CompatibilityFlagBits::COMPATIBLE_BIT;
1538bf80f4bSopenharmony_ci    for (uint32_t setIdx = 0; setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++setIdx) {
1548bf80f4bSopenharmony_ci        const auto& lSet = lhs.descriptorSetLayouts[setIdx];
1558bf80f4bSopenharmony_ci        const auto& rSet = rhs.descriptorSetLayouts[setIdx];
1568bf80f4bSopenharmony_ci        if (lSet.set == rSet.set) {
1578bf80f4bSopenharmony_ci            for (uint32_t lIdx = 0; lIdx < lSet.bindings.size(); ++lIdx) {
1588bf80f4bSopenharmony_ci                const auto& lBind = lSet.bindings[lIdx];
1598bf80f4bSopenharmony_ci                for (uint32_t rIdx = 0; rIdx < rSet.bindings.size(); ++rIdx) {
1608bf80f4bSopenharmony_ci                    const auto& rBind = rSet.bindings[rIdx];
1618bf80f4bSopenharmony_ci                    if (lBind.binding == rBind.binding) {
1628bf80f4bSopenharmony_ci                        if ((lBind.descriptorCount != rBind.descriptorCount) ||
1638bf80f4bSopenharmony_ci                            (lBind.descriptorType != rBind.descriptorType)) {
1648bf80f4bSopenharmony_ci                            // re-check dynamic offsets
1658bf80f4bSopenharmony_ci                            if ((IsUniformBuffer(lBind.descriptorType) != IsUniformBuffer(rBind.descriptorType)) &&
1668bf80f4bSopenharmony_ci                                (IsStorageBuffer(lBind.descriptorType) != IsStorageBuffer(rBind.descriptorType))) {
1678bf80f4bSopenharmony_ci                                flags = 0;
1688bf80f4bSopenharmony_ci                            }
1698bf80f4bSopenharmony_ci                        }
1708bf80f4bSopenharmony_ci                    }
1718bf80f4bSopenharmony_ci                }
1728bf80f4bSopenharmony_ci            }
1738bf80f4bSopenharmony_ci        }
1748bf80f4bSopenharmony_ci    }
1758bf80f4bSopenharmony_ci    if (flags != 0) {
1768bf80f4bSopenharmony_ci        // check for exact match
1778bf80f4bSopenharmony_ci        bool isExact = true;
1788bf80f4bSopenharmony_ci        for (uint32_t setIdx = 0; setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++setIdx) {
1798bf80f4bSopenharmony_ci            const auto& lSet = lhs.descriptorSetLayouts[setIdx];
1808bf80f4bSopenharmony_ci            const auto& rSet = rhs.descriptorSetLayouts[setIdx];
1818bf80f4bSopenharmony_ci            if (lSet.set == rSet.set) {
1828bf80f4bSopenharmony_ci                if (lSet.bindings.size() == rSet.bindings.size()) {
1838bf80f4bSopenharmony_ci                    for (size_t idx = 0; idx < lSet.bindings.size(); ++idx) {
1848bf80f4bSopenharmony_ci                        const int cmpRes =
1858bf80f4bSopenharmony_ci                            std::memcmp(&(lSet.bindings[idx]), &(rSet.bindings[idx]), sizeof(lSet.bindings[idx]));
1868bf80f4bSopenharmony_ci                        if (cmpRes != 0) {
1878bf80f4bSopenharmony_ci                            isExact = false;
1888bf80f4bSopenharmony_ci                            break;
1898bf80f4bSopenharmony_ci                        }
1908bf80f4bSopenharmony_ci                    }
1918bf80f4bSopenharmony_ci                } else {
1928bf80f4bSopenharmony_ci                    isExact = false;
1938bf80f4bSopenharmony_ci                    break;
1948bf80f4bSopenharmony_ci                }
1958bf80f4bSopenharmony_ci            }
1968bf80f4bSopenharmony_ci        }
1978bf80f4bSopenharmony_ci        if (isExact) {
1988bf80f4bSopenharmony_ci            flags |= ShaderManager::CompatibilityFlagBits::EXACT_BIT;
1998bf80f4bSopenharmony_ci        }
2008bf80f4bSopenharmony_ci    }
2018bf80f4bSopenharmony_ci    return flags;
2028bf80f4bSopenharmony_ci}
2038bf80f4bSopenharmony_ci
2048bf80f4bSopenharmony_ci// NOTE: checking the type for validity is enough
2058bf80f4bSopenharmony_ciinline bool IsComputeShaderFunc(RenderHandle handle)
2068bf80f4bSopenharmony_ci{
2078bf80f4bSopenharmony_ci    return RenderHandleType::COMPUTE_SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle);
2088bf80f4bSopenharmony_ci}
2098bf80f4bSopenharmony_ci
2108bf80f4bSopenharmony_ciinline bool IsShaderFunc(RenderHandle handle)
2118bf80f4bSopenharmony_ci{
2128bf80f4bSopenharmony_ci    return RenderHandleType::SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle);
2138bf80f4bSopenharmony_ci}
2148bf80f4bSopenharmony_ci
2158bf80f4bSopenharmony_ciinline bool IsAnyShaderFunc(RenderHandle handle)
2168bf80f4bSopenharmony_ci{
2178bf80f4bSopenharmony_ci    return (RenderHandleType::COMPUTE_SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle)) ||
2188bf80f4bSopenharmony_ci           (RenderHandleType::SHADER_STATE_OBJECT == RenderHandleUtil::GetHandleType(handle));
2198bf80f4bSopenharmony_ci}
2208bf80f4bSopenharmony_ci
2218bf80f4bSopenharmony_ciinline void GetShadersBySlot(
2228bf80f4bSopenharmony_ci    const uint32_t renderSlotId, const ShaderManager::ComputeMappings& mappings, vector<RenderHandleReference>& shaders)
2238bf80f4bSopenharmony_ci{
2248bf80f4bSopenharmony_ci    for (const auto& ref : mappings.clientData) {
2258bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
2268bf80f4bSopenharmony_ci            shaders.push_back(ref.rhr);
2278bf80f4bSopenharmony_ci        }
2288bf80f4bSopenharmony_ci    }
2298bf80f4bSopenharmony_ci}
2308bf80f4bSopenharmony_ci
2318bf80f4bSopenharmony_ciinline void GetShadersBySlot(const uint32_t renderSlotId, const ShaderManager::GraphicsMappings& mappings,
2328bf80f4bSopenharmony_ci    vector<RenderHandleReference>& shaders)
2338bf80f4bSopenharmony_ci{
2348bf80f4bSopenharmony_ci    for (const auto& ref : mappings.clientData) {
2358bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
2368bf80f4bSopenharmony_ci            shaders.push_back(ref.rhr);
2378bf80f4bSopenharmony_ci        }
2388bf80f4bSopenharmony_ci    }
2398bf80f4bSopenharmony_ci}
2408bf80f4bSopenharmony_ci
2418bf80f4bSopenharmony_ciinline void GetShadersBySlot(
2428bf80f4bSopenharmony_ci    const uint32_t renderSlotId, const ShaderManager::ComputeMappings& mappings, vector<RenderHandle>& shaders)
2438bf80f4bSopenharmony_ci{
2448bf80f4bSopenharmony_ci    for (const auto& ref : mappings.clientData) {
2458bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
2468bf80f4bSopenharmony_ci            shaders.push_back(ref.rhr.GetHandle());
2478bf80f4bSopenharmony_ci        }
2488bf80f4bSopenharmony_ci    }
2498bf80f4bSopenharmony_ci}
2508bf80f4bSopenharmony_ci
2518bf80f4bSopenharmony_ciinline void GetShadersBySlot(
2528bf80f4bSopenharmony_ci    const uint32_t renderSlotId, const ShaderManager::GraphicsMappings& mappings, vector<RenderHandle>& shaders)
2538bf80f4bSopenharmony_ci{
2548bf80f4bSopenharmony_ci    for (const auto& ref : mappings.clientData) {
2558bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
2568bf80f4bSopenharmony_ci            shaders.push_back(ref.rhr.GetHandle());
2578bf80f4bSopenharmony_ci        }
2588bf80f4bSopenharmony_ci    }
2598bf80f4bSopenharmony_ci}
2608bf80f4bSopenharmony_ci
2618bf80f4bSopenharmony_ciinline void GetGraphicsStatesBySlot(
2628bf80f4bSopenharmony_ci    const uint32_t renderSlotId, const ShaderManager::GraphicsStateData& gsd, vector<RenderHandleReference>& states)
2638bf80f4bSopenharmony_ci{
2648bf80f4bSopenharmony_ci    PLUGIN_ASSERT(gsd.data.size() == gsd.rhr.size());
2658bf80f4bSopenharmony_ci    for (size_t idx = 0; idx < gsd.data.size(); ++idx) {
2668bf80f4bSopenharmony_ci        const auto& ref = gsd.data[idx];
2678bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
2688bf80f4bSopenharmony_ci            states.push_back(gsd.rhr[idx]);
2698bf80f4bSopenharmony_ci        }
2708bf80f4bSopenharmony_ci    }
2718bf80f4bSopenharmony_ci}
2728bf80f4bSopenharmony_ci
2738bf80f4bSopenharmony_ciinline void GetGraphicsStatesBySlot(
2748bf80f4bSopenharmony_ci    const uint32_t renderSlotId, const ShaderManager::GraphicsStateData& gsd, vector<RenderHandle>& states)
2758bf80f4bSopenharmony_ci{
2768bf80f4bSopenharmony_ci    PLUGIN_ASSERT(gsd.data.size() == gsd.rhr.size());
2778bf80f4bSopenharmony_ci    for (size_t idx = 0; idx < gsd.data.size(); ++idx) {
2788bf80f4bSopenharmony_ci        const auto& ref = gsd.data[idx];
2798bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
2808bf80f4bSopenharmony_ci            states.push_back(gsd.rhr[idx].GetHandle());
2818bf80f4bSopenharmony_ci        }
2828bf80f4bSopenharmony_ci    }
2838bf80f4bSopenharmony_ci}
2848bf80f4bSopenharmony_ci
2858bf80f4bSopenharmony_ciinline RenderHandle GetHandle(const string_view path, const unordered_map<string, RenderHandle>& nameToClientHandle)
2868bf80f4bSopenharmony_ci{
2878bf80f4bSopenharmony_ci    if (auto const pos = nameToClientHandle.find(path); pos != nameToClientHandle.end()) {
2888bf80f4bSopenharmony_ci        return pos->second;
2898bf80f4bSopenharmony_ci    }
2908bf80f4bSopenharmony_ci    return {};
2918bf80f4bSopenharmony_ci}
2928bf80f4bSopenharmony_ci
2938bf80f4bSopenharmony_ciconstexpr inline uint64_t HashHandleAndSlot(const RenderHandle& handle, const uint32_t renderSlotId)
2948bf80f4bSopenharmony_ci{
2958bf80f4bSopenharmony_ci    // normally there are < 16 render slot ids used which way less than 0xffff
2968bf80f4bSopenharmony_ci    // NOTE: the render slot id might be an invalid index
2978bf80f4bSopenharmony_ci    return (handle.id << 16ull) | (renderSlotId & 0xffff);
2988bf80f4bSopenharmony_ci}
2998bf80f4bSopenharmony_ci
3008bf80f4bSopenharmony_ciuint32_t GetBaseGraphicsStateVariantIndex(
3018bf80f4bSopenharmony_ci    const ShaderManager::GraphicsStateData& graphicsStates, const ShaderManager::GraphicsStateVariantCreateInfo& vci)
3028bf80f4bSopenharmony_ci{
3038bf80f4bSopenharmony_ci    uint32_t baseVariantIndex = INVALID_SM_INDEX;
3048bf80f4bSopenharmony_ci    if (!vci.baseShaderState.empty()) {
3058bf80f4bSopenharmony_ci        const string fullBaseName = vci.baseShaderState + vci.baseVariant;
3068bf80f4bSopenharmony_ci        if (const auto bhIter = graphicsStates.nameToIndex.find(fullBaseName);
3078bf80f4bSopenharmony_ci            bhIter != graphicsStates.nameToIndex.cend()) {
3088bf80f4bSopenharmony_ci            PLUGIN_ASSERT(bhIter->second < graphicsStates.rhr.size());
3098bf80f4bSopenharmony_ci            if ((bhIter->second < graphicsStates.rhr.size()) && graphicsStates.rhr[bhIter->second]) {
3108bf80f4bSopenharmony_ci                const RenderHandle baseHandle = graphicsStates.rhr[bhIter->second].GetHandle();
3118bf80f4bSopenharmony_ci                baseVariantIndex = RenderHandleUtil::GetIndexPart(baseHandle);
3128bf80f4bSopenharmony_ci            }
3138bf80f4bSopenharmony_ci        } else {
3148bf80f4bSopenharmony_ci            PLUGIN_LOG_W("base state not found (%s %s)", vci.baseShaderState.data(), vci.baseVariant.data());
3158bf80f4bSopenharmony_ci        }
3168bf80f4bSopenharmony_ci    }
3178bf80f4bSopenharmony_ci    return baseVariantIndex;
3188bf80f4bSopenharmony_ci}
3198bf80f4bSopenharmony_ci} // namespace
3208bf80f4bSopenharmony_ci
3218bf80f4bSopenharmony_ciShaderManager::ShaderManager(Device& device) : device_(device) {}
3228bf80f4bSopenharmony_ci
3238bf80f4bSopenharmony_ciShaderManager::~ShaderManager() = default;
3248bf80f4bSopenharmony_ci
3258bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::Get(const RenderHandle& handle) const
3268bf80f4bSopenharmony_ci{
3278bf80f4bSopenharmony_ci    if (RenderHandleUtil::IsValid(handle)) {
3288bf80f4bSopenharmony_ci        const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
3298bf80f4bSopenharmony_ci        const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
3308bf80f4bSopenharmony_ci        if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
3318bf80f4bSopenharmony_ci            if (arrayIndex < computeShaderMappings_.clientData.size()) {
3328bf80f4bSopenharmony_ci                return computeShaderMappings_.clientData[arrayIndex].rhr;
3338bf80f4bSopenharmony_ci            }
3348bf80f4bSopenharmony_ci        } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
3358bf80f4bSopenharmony_ci            if (arrayIndex < shaderMappings_.clientData.size()) {
3368bf80f4bSopenharmony_ci                return shaderMappings_.clientData[arrayIndex].rhr;
3378bf80f4bSopenharmony_ci            }
3388bf80f4bSopenharmony_ci        } else if (handleType == RenderHandleType::GRAPHICS_STATE) {
3398bf80f4bSopenharmony_ci            if (arrayIndex < graphicsStates_.rhr.size()) {
3408bf80f4bSopenharmony_ci                return graphicsStates_.rhr[arrayIndex];
3418bf80f4bSopenharmony_ci            }
3428bf80f4bSopenharmony_ci        } else if (handleType == RenderHandleType::PIPELINE_LAYOUT) {
3438bf80f4bSopenharmony_ci            if (arrayIndex < pl_.rhr.size()) {
3448bf80f4bSopenharmony_ci                return pl_.rhr[arrayIndex];
3458bf80f4bSopenharmony_ci            }
3468bf80f4bSopenharmony_ci        }
3478bf80f4bSopenharmony_ci        PLUGIN_LOG_I("invalid render handle (id: %" PRIu64 ", type: %u)", handle.id, static_cast<uint32_t>(handleType));
3488bf80f4bSopenharmony_ci    }
3498bf80f4bSopenharmony_ci    return RenderHandleReference {};
3508bf80f4bSopenharmony_ci}
3518bf80f4bSopenharmony_ci
3528bf80f4bSopenharmony_ciuint64_t ShaderManager::HashGraphicsState(const GraphicsState& graphicsState) const
3538bf80f4bSopenharmony_ci{
3548bf80f4bSopenharmony_ci    return BASE_NS::hash(graphicsState);
3558bf80f4bSopenharmony_ci}
3568bf80f4bSopenharmony_ci
3578bf80f4bSopenharmony_ciuint32_t ShaderManager::CreateRenderSlotId(const string_view renderSlot)
3588bf80f4bSopenharmony_ci{
3598bf80f4bSopenharmony_ci    if (renderSlot.empty()) {
3608bf80f4bSopenharmony_ci        return INVALID_SM_INDEX;
3618bf80f4bSopenharmony_ci    }
3628bf80f4bSopenharmony_ci
3638bf80f4bSopenharmony_ci    if (const auto iter = renderSlotIds_.nameToId.find(renderSlot); iter != renderSlotIds_.nameToId.cend()) {
3648bf80f4bSopenharmony_ci        return iter->second;
3658bf80f4bSopenharmony_ci    } else { // create new id
3668bf80f4bSopenharmony_ci        const uint32_t renderSlotId = static_cast<uint32_t>(renderSlotIds_.data.size());
3678bf80f4bSopenharmony_ci        renderSlotIds_.nameToId[renderSlot] = renderSlotId;
3688bf80f4bSopenharmony_ci        renderSlotIds_.data.push_back(RenderSlotData { renderSlotId, {}, {} });
3698bf80f4bSopenharmony_ci        return renderSlotId;
3708bf80f4bSopenharmony_ci    }
3718bf80f4bSopenharmony_ci}
3728bf80f4bSopenharmony_ci
3738bf80f4bSopenharmony_cistring ShaderManager::GetRenderSlotName(const uint32_t renderSlotId) const
3748bf80f4bSopenharmony_ci{
3758bf80f4bSopenharmony_ci    if (renderSlotId != INVALID_SM_INDEX) {
3768bf80f4bSopenharmony_ci        for (const auto& ref : renderSlotIds_.nameToId) {
3778bf80f4bSopenharmony_ci            if (ref.second == renderSlotId) {
3788bf80f4bSopenharmony_ci                return ref.first;
3798bf80f4bSopenharmony_ci            }
3808bf80f4bSopenharmony_ci        }
3818bf80f4bSopenharmony_ci    }
3828bf80f4bSopenharmony_ci    return {};
3838bf80f4bSopenharmony_ci}
3848bf80f4bSopenharmony_ci
3858bf80f4bSopenharmony_cistring ShaderManager::GetCategoryName(const uint32_t categoryId) const
3868bf80f4bSopenharmony_ci{
3878bf80f4bSopenharmony_ci    if (categoryId != INVALID_SM_INDEX) {
3888bf80f4bSopenharmony_ci        for (const auto& ref : category_.nameToId) {
3898bf80f4bSopenharmony_ci            if (ref.second == categoryId) {
3908bf80f4bSopenharmony_ci                return ref.first;
3918bf80f4bSopenharmony_ci            }
3928bf80f4bSopenharmony_ci        }
3938bf80f4bSopenharmony_ci    }
3948bf80f4bSopenharmony_ci    return {};
3958bf80f4bSopenharmony_ci}
3968bf80f4bSopenharmony_ci
3978bf80f4bSopenharmony_civoid ShaderManager::SetRenderSlotData(
3988bf80f4bSopenharmony_ci    const uint32_t renderSlotId, const RenderHandleReference& shaderHandle, const RenderHandleReference& stateHandle)
3998bf80f4bSopenharmony_ci{
4008bf80f4bSopenharmony_ci    if (renderSlotId < static_cast<uint32_t>(renderSlotIds_.data.size())) {
4018bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
4028bf80f4bSopenharmony_ci        string renderSlotName = GetRenderSlotName(renderSlotId);
4038bf80f4bSopenharmony_ci#endif
4048bf80f4bSopenharmony_ci        if (IsAnyShaderFunc(shaderHandle.GetHandle())) {
4058bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
4068bf80f4bSopenharmony_ci            if (renderSlotIds_.data[renderSlotId].shader) {
4078bf80f4bSopenharmony_ci                renderSlotName = GetRenderSlotName(renderSlotId);
4088bf80f4bSopenharmony_ci                PLUGIN_LOG_W(
4098bf80f4bSopenharmony_ci                    "RENDER_VALIDATION: Overwriting default shader for render slot (%s)", renderSlotName.c_str());
4108bf80f4bSopenharmony_ci            }
4118bf80f4bSopenharmony_ci#endif
4128bf80f4bSopenharmony_ci            renderSlotIds_.data[renderSlotId].shader = shaderHandle;
4138bf80f4bSopenharmony_ci        }
4148bf80f4bSopenharmony_ci        if (RenderHandleUtil::GetHandleType(stateHandle.GetHandle()) == RenderHandleType::GRAPHICS_STATE) {
4158bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
4168bf80f4bSopenharmony_ci            if (renderSlotIds_.data[renderSlotId].graphicsState) {
4178bf80f4bSopenharmony_ci                renderSlotName = renderSlotName.empty() ? GetRenderSlotName(renderSlotId) : renderSlotName;
4188bf80f4bSopenharmony_ci                PLUGIN_LOG_W(
4198bf80f4bSopenharmony_ci                    "RENDER_VALIDATION: Overwriting default shader for render slot (%s)", renderSlotName.c_str());
4208bf80f4bSopenharmony_ci            }
4218bf80f4bSopenharmony_ci#endif
4228bf80f4bSopenharmony_ci            renderSlotIds_.data[renderSlotId].graphicsState = stateHandle;
4238bf80f4bSopenharmony_ci        }
4248bf80f4bSopenharmony_ci    }
4258bf80f4bSopenharmony_ci}
4268bf80f4bSopenharmony_ci
4278bf80f4bSopenharmony_ciuint32_t ShaderManager::CreateCategoryId(const string_view name)
4288bf80f4bSopenharmony_ci{
4298bf80f4bSopenharmony_ci    if (name.empty()) {
4308bf80f4bSopenharmony_ci        return INVALID_SM_INDEX;
4318bf80f4bSopenharmony_ci    }
4328bf80f4bSopenharmony_ci
4338bf80f4bSopenharmony_ci    if (const auto iter = category_.nameToId.find(name); iter != category_.nameToId.cend()) {
4348bf80f4bSopenharmony_ci        return iter->second;
4358bf80f4bSopenharmony_ci    } else { // create new id
4368bf80f4bSopenharmony_ci        const uint32_t id = static_cast<uint32_t>(category_.data.size());
4378bf80f4bSopenharmony_ci        category_.nameToId[name] = id;
4388bf80f4bSopenharmony_ci        category_.data.push_back(string(name));
4398bf80f4bSopenharmony_ci        return id;
4408bf80f4bSopenharmony_ci    }
4418bf80f4bSopenharmony_ci}
4428bf80f4bSopenharmony_ci
4438bf80f4bSopenharmony_ciRenderHandle ShaderManager::CreateClientData(
4448bf80f4bSopenharmony_ci    const string_view path, const RenderHandleType type, const ClientDataIndices& cdi)
4458bf80f4bSopenharmony_ci{
4468bf80f4bSopenharmony_ci    PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
4478bf80f4bSopenharmony_ci    PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
4488bf80f4bSopenharmony_ci
4498bf80f4bSopenharmony_ci    RenderHandle clientHandle;
4508bf80f4bSopenharmony_ci    PLUGIN_ASSERT(
4518bf80f4bSopenharmony_ci        (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) || (type == RenderHandleType::SHADER_STATE_OBJECT));
4528bf80f4bSopenharmony_ci    const uint64_t frameIndex = device_.GetFrameCount();
4538bf80f4bSopenharmony_ci    if (auto iter = nameToClientHandle_.find(path); iter != nameToClientHandle_.end()) {
4548bf80f4bSopenharmony_ci        clientHandle = iter->second;
4558bf80f4bSopenharmony_ci        // we update the frame index if the shader has been (re)loaded
4568bf80f4bSopenharmony_ci        const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(clientHandle);
4578bf80f4bSopenharmony_ci        if ((type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
4588bf80f4bSopenharmony_ci            (arrayIndex < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
4598bf80f4bSopenharmony_ci            computeShaderMappings_.clientData[arrayIndex].frameIndex = frameIndex;
4608bf80f4bSopenharmony_ci        } else if (arrayIndex < static_cast<uint32_t>(shaderMappings_.clientData.size())) {
4618bf80f4bSopenharmony_ci            shaderMappings_.clientData[arrayIndex].frameIndex = frameIndex;
4628bf80f4bSopenharmony_ci        }
4638bf80f4bSopenharmony_ci    } else {
4648bf80f4bSopenharmony_ci        const uint32_t arrayIndex = (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT)
4658bf80f4bSopenharmony_ci                                        ? static_cast<uint32_t>(computeShaderMappings_.clientData.size())
4668bf80f4bSopenharmony_ci                                        : static_cast<uint32_t>(shaderMappings_.clientData.size());
4678bf80f4bSopenharmony_ci        clientHandle = RenderHandleUtil::CreateGpuResourceHandle(type, 0, arrayIndex, 0);
4688bf80f4bSopenharmony_ci        RenderHandleReference rhr =
4698bf80f4bSopenharmony_ci            RenderHandleReference(clientHandle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter()));
4708bf80f4bSopenharmony_ci        if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
4718bf80f4bSopenharmony_ci            computeShaderMappings_.clientData.push_back({ move(rhr), {}, cdi.renderSlotIndex, cdi.pipelineLayoutIndex,
4728bf80f4bSopenharmony_ci                cdi.reflectionPipelineLayoutIndex, cdi.categoryIndex, frameIndex });
4738bf80f4bSopenharmony_ci            computeShaderMappings_.nameData.push_back({});
4748bf80f4bSopenharmony_ci        } else {
4758bf80f4bSopenharmony_ci            shaderMappings_.clientData.push_back({ move(rhr), {}, cdi.renderSlotIndex, cdi.pipelineLayoutIndex,
4768bf80f4bSopenharmony_ci                cdi.reflectionPipelineLayoutIndex, INVALID_SM_INDEX, INVALID_SM_INDEX, cdi.categoryIndex, frameIndex });
4778bf80f4bSopenharmony_ci            shaderMappings_.nameData.push_back({});
4788bf80f4bSopenharmony_ci        }
4798bf80f4bSopenharmony_ci        if (!path.empty()) {
4808bf80f4bSopenharmony_ci            nameToClientHandle_[path] = clientHandle;
4818bf80f4bSopenharmony_ci        }
4828bf80f4bSopenharmony_ci    }
4838bf80f4bSopenharmony_ci
4848bf80f4bSopenharmony_ci    return clientHandle;
4858bf80f4bSopenharmony_ci}
4868bf80f4bSopenharmony_ci
4878bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::Create(
4888bf80f4bSopenharmony_ci    const ComputeShaderCreateData& createInfo, const ShaderPathCreateData& pathCreateInfo)
4898bf80f4bSopenharmony_ci{
4908bf80f4bSopenharmony_ci    PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
4918bf80f4bSopenharmony_ci
4928bf80f4bSopenharmony_ci    const string fullName = createInfo.path + pathCreateInfo.variantName;
4938bf80f4bSopenharmony_ci    // reflection pipeline layout
4948bf80f4bSopenharmony_ci    uint32_t reflectionPlIndex = INVALID_SM_INDEX;
4958bf80f4bSopenharmony_ci    if (const ShaderModule* cs = GetShaderModule(createInfo.shaderModuleIndex); cs) {
4968bf80f4bSopenharmony_ci        const RenderHandleReference plRhr = CreatePipelineLayout({ fullName, cs->GetPipelineLayout() });
4978bf80f4bSopenharmony_ci        reflectionPlIndex = RenderHandleUtil::GetIndexPart(plRhr.GetHandle());
4988bf80f4bSopenharmony_ci    }
4998bf80f4bSopenharmony_ci
5008bf80f4bSopenharmony_ci    auto const clientHandle = CreateClientData(fullName, RenderHandleType::COMPUTE_SHADER_STATE_OBJECT,
5018bf80f4bSopenharmony_ci        { createInfo.renderSlotId, createInfo.pipelineLayoutIndex, reflectionPlIndex, createInfo.categoryId });
5028bf80f4bSopenharmony_ci    if (createInfo.pipelineLayoutIndex != INVALID_SM_INDEX) {
5038bf80f4bSopenharmony_ci        pl_.computeShaderToIndex[clientHandle] = createInfo.pipelineLayoutIndex;
5048bf80f4bSopenharmony_ci    }
5058bf80f4bSopenharmony_ci
5068bf80f4bSopenharmony_ci    {
5078bf80f4bSopenharmony_ci        const auto lock = std::lock_guard(pendingMutex_);
5088bf80f4bSopenharmony_ci        pendingAllocations_.computeShaders.push_back(
5098bf80f4bSopenharmony_ci            { clientHandle, createInfo.shaderModuleIndex, createInfo.pipelineLayoutIndex });
5108bf80f4bSopenharmony_ci    }
5118bf80f4bSopenharmony_ci    if ((!createInfo.shaderFileStr.empty()) && RenderHandleUtil::IsValid(clientHandle)) {
5128bf80f4bSopenharmony_ci        // update shader file always
5138bf80f4bSopenharmony_ci        handleToShaderDataFile_.insert_or_assign(clientHandle, string(createInfo.shaderFileStr));
5148bf80f4bSopenharmony_ci    }
5158bf80f4bSopenharmony_ci    if (!createInfo.materialMetadata.empty()) {
5168bf80f4bSopenharmony_ci        MaterialMetadata metadata { string(createInfo.materialMetadata), json::value {} };
5178bf80f4bSopenharmony_ci        if (metadata.json = json::parse(metadata.raw.data()); metadata.json) {
5188bf80f4bSopenharmony_ci            // update metadata always
5198bf80f4bSopenharmony_ci            shaderToMetadata_.insert_or_assign(clientHandle, move(metadata));
5208bf80f4bSopenharmony_ci        }
5218bf80f4bSopenharmony_ci    }
5228bf80f4bSopenharmony_ci
5238bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(clientHandle);
5248bf80f4bSopenharmony_ci    if (IsComputeShaderFunc(clientHandle) &&
5258bf80f4bSopenharmony_ci        (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
5268bf80f4bSopenharmony_ci        auto& nameDataRef = computeShaderMappings_.nameData[index];
5278bf80f4bSopenharmony_ci        nameDataRef.path = createInfo.path;
5288bf80f4bSopenharmony_ci        nameDataRef.variantName = pathCreateInfo.variantName;
5298bf80f4bSopenharmony_ci        nameDataRef.displayName = pathCreateInfo.displayName;
5308bf80f4bSopenharmony_ci        auto& clientDataRef = computeShaderMappings_.clientData[index];
5318bf80f4bSopenharmony_ci        // add base shader if given
5328bf80f4bSopenharmony_ci        if (!pathCreateInfo.baseShaderPath.empty()) {
5338bf80f4bSopenharmony_ci            if (const auto baseHandleIter = nameToClientHandle_.find(pathCreateInfo.baseShaderPath);
5348bf80f4bSopenharmony_ci                baseHandleIter != nameToClientHandle_.cend()) {
5358bf80f4bSopenharmony_ci                if (RenderHandleUtil::IsValid(baseHandleIter->second)) {
5368bf80f4bSopenharmony_ci                    clientDataRef.baseShaderHandle = baseHandleIter->second;
5378bf80f4bSopenharmony_ci                    const uint64_t hash = HashHandleAndSlot(clientDataRef.baseShaderHandle, createInfo.renderSlotId);
5388bf80f4bSopenharmony_ci                    hashToShaderVariant_[hash] = clientHandle;
5398bf80f4bSopenharmony_ci                }
5408bf80f4bSopenharmony_ci            } else {
5418bf80f4bSopenharmony_ci                PLUGIN_LOG_W("base shader (%s) not found for (%s)", pathCreateInfo.baseShaderPath.data(),
5428bf80f4bSopenharmony_ci                    createInfo.path.data());
5438bf80f4bSopenharmony_ci            }
5448bf80f4bSopenharmony_ci        }
5458bf80f4bSopenharmony_ci        return clientDataRef.rhr;
5468bf80f4bSopenharmony_ci    } else {
5478bf80f4bSopenharmony_ci        return {};
5488bf80f4bSopenharmony_ci    }
5498bf80f4bSopenharmony_ci}
5508bf80f4bSopenharmony_ci
5518bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::Create(
5528bf80f4bSopenharmony_ci    const ShaderCreateData& createInfo, const ShaderPathCreateData& pathCreateInfo)
5538bf80f4bSopenharmony_ci{
5548bf80f4bSopenharmony_ci    PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
5558bf80f4bSopenharmony_ci
5568bf80f4bSopenharmony_ci    const string fullName = createInfo.path + pathCreateInfo.variantName;
5578bf80f4bSopenharmony_ci    // reflection pipeline layout
5588bf80f4bSopenharmony_ci    uint32_t reflectionPlIndex = INVALID_SM_INDEX;
5598bf80f4bSopenharmony_ci    {
5608bf80f4bSopenharmony_ci        const ShaderModule* vs = GetShaderModule(createInfo.vertShaderModuleIndex);
5618bf80f4bSopenharmony_ci        const ShaderModule* fs = GetShaderModule(createInfo.fragShaderModuleIndex);
5628bf80f4bSopenharmony_ci        if (vs && fs) {
5638bf80f4bSopenharmony_ci            const PipelineLayout layouts[] { vs->GetPipelineLayout(), fs->GetPipelineLayout() };
5648bf80f4bSopenharmony_ci            PipelineLayout pl;
5658bf80f4bSopenharmony_ci            GpuProgramUtil::CombinePipelineLayouts({ layouts, 2u }, pl);
5668bf80f4bSopenharmony_ci            const RenderHandleReference plRhr = CreatePipelineLayout({ fullName, pl });
5678bf80f4bSopenharmony_ci            reflectionPlIndex = RenderHandleUtil::GetIndexPart(plRhr.GetHandle());
5688bf80f4bSopenharmony_ci        }
5698bf80f4bSopenharmony_ci    }
5708bf80f4bSopenharmony_ci
5718bf80f4bSopenharmony_ci    auto const clientHandle = CreateClientData(fullName, RenderHandleType::SHADER_STATE_OBJECT,
5728bf80f4bSopenharmony_ci        { createInfo.renderSlotId, createInfo.pipelineLayoutIndex, reflectionPlIndex, createInfo.categoryId });
5738bf80f4bSopenharmony_ci
5748bf80f4bSopenharmony_ci    if (createInfo.pipelineLayoutIndex != INVALID_SM_INDEX) {
5758bf80f4bSopenharmony_ci        pl_.shaderToIndex[clientHandle] = createInfo.pipelineLayoutIndex;
5768bf80f4bSopenharmony_ci    }
5778bf80f4bSopenharmony_ci    if (createInfo.vertexInputDeclarationIndex != INVALID_SM_INDEX) {
5788bf80f4bSopenharmony_ci        shaderVid_.shaderToIndex[clientHandle] = createInfo.vertexInputDeclarationIndex;
5798bf80f4bSopenharmony_ci    }
5808bf80f4bSopenharmony_ci
5818bf80f4bSopenharmony_ci    {
5828bf80f4bSopenharmony_ci        const auto lock = std::lock_guard(pendingMutex_);
5838bf80f4bSopenharmony_ci        pendingAllocations_.shaders.push_back({ clientHandle, createInfo.vertShaderModuleIndex,
5848bf80f4bSopenharmony_ci            createInfo.fragShaderModuleIndex, createInfo.pipelineLayoutIndex, createInfo.vertexInputDeclarationIndex });
5858bf80f4bSopenharmony_ci    }
5868bf80f4bSopenharmony_ci
5878bf80f4bSopenharmony_ci    if ((!createInfo.shaderFileStr.empty()) && RenderHandleUtil::IsValid(clientHandle)) {
5888bf80f4bSopenharmony_ci        // update shader file always
5898bf80f4bSopenharmony_ci        handleToShaderDataFile_.insert_or_assign(clientHandle, string(createInfo.shaderFileStr));
5908bf80f4bSopenharmony_ci    }
5918bf80f4bSopenharmony_ci    if (!createInfo.materialMetadata.empty()) {
5928bf80f4bSopenharmony_ci        MaterialMetadata metadata { string(createInfo.materialMetadata), json::value {} };
5938bf80f4bSopenharmony_ci        if (metadata.json = json::parse(metadata.raw.data()); metadata.json) {
5948bf80f4bSopenharmony_ci            // update metadata always
5958bf80f4bSopenharmony_ci            shaderToMetadata_.insert_or_assign(clientHandle, move(metadata));
5968bf80f4bSopenharmony_ci        } else {
5978bf80f4bSopenharmony_ci            shaderToMetadata_.erase(clientHandle);
5988bf80f4bSopenharmony_ci        }
5998bf80f4bSopenharmony_ci    } else {
6008bf80f4bSopenharmony_ci        shaderToMetadata_.erase(clientHandle);
6018bf80f4bSopenharmony_ci    }
6028bf80f4bSopenharmony_ci
6038bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(clientHandle);
6048bf80f4bSopenharmony_ci    if (IsShaderFunc(clientHandle) && (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
6058bf80f4bSopenharmony_ci        auto& nameDataRef = shaderMappings_.nameData[index];
6068bf80f4bSopenharmony_ci        nameDataRef.path = createInfo.path;
6078bf80f4bSopenharmony_ci        nameDataRef.variantName = pathCreateInfo.variantName;
6088bf80f4bSopenharmony_ci        nameDataRef.displayName = pathCreateInfo.displayName;
6098bf80f4bSopenharmony_ci        auto& clientDataRef = shaderMappings_.clientData[index];
6108bf80f4bSopenharmony_ci        clientDataRef.graphicsStateIndex = createInfo.graphicsStateIndex;
6118bf80f4bSopenharmony_ci        clientDataRef.vertexInputDeclarationIndex = createInfo.vertexInputDeclarationIndex;
6128bf80f4bSopenharmony_ci        // add base shader if given
6138bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
6148bf80f4bSopenharmony_ci        if ((!pathCreateInfo.variantName.empty()) && pathCreateInfo.baseShaderPath.empty()) {
6158bf80f4bSopenharmony_ci            PLUGIN_LOG_W("RENDER_VALIDATION: base shader path not give to variant (%s %s)", createInfo.path.data(),
6168bf80f4bSopenharmony_ci                pathCreateInfo.variantName.data());
6178bf80f4bSopenharmony_ci        }
6188bf80f4bSopenharmony_ci#endif
6198bf80f4bSopenharmony_ci        if (!pathCreateInfo.baseShaderPath.empty()) {
6208bf80f4bSopenharmony_ci            if (const auto baseHandleIter = nameToClientHandle_.find(pathCreateInfo.baseShaderPath);
6218bf80f4bSopenharmony_ci                baseHandleIter != nameToClientHandle_.cend()) {
6228bf80f4bSopenharmony_ci                if (RenderHandleUtil::IsValid(baseHandleIter->second)) {
6238bf80f4bSopenharmony_ci                    clientDataRef.baseShaderHandle = baseHandleIter->second;
6248bf80f4bSopenharmony_ci                    const uint64_t hash = HashHandleAndSlot(clientDataRef.baseShaderHandle, createInfo.renderSlotId);
6258bf80f4bSopenharmony_ci                    hashToShaderVariant_[hash] = clientHandle;
6268bf80f4bSopenharmony_ci                }
6278bf80f4bSopenharmony_ci            } else {
6288bf80f4bSopenharmony_ci                PLUGIN_LOG_W("base shader (%s) not found for (%s)", pathCreateInfo.baseShaderPath.data(),
6298bf80f4bSopenharmony_ci                    createInfo.path.data());
6308bf80f4bSopenharmony_ci            }
6318bf80f4bSopenharmony_ci        }
6328bf80f4bSopenharmony_ci        return clientDataRef.rhr;
6338bf80f4bSopenharmony_ci    } else {
6348bf80f4bSopenharmony_ci        return {};
6358bf80f4bSopenharmony_ci    }
6368bf80f4bSopenharmony_ci}
6378bf80f4bSopenharmony_ci
6388bf80f4bSopenharmony_civoid ShaderManager::AddAdditionalNameForHandle(const RenderHandleReference& handle, const string_view name)
6398bf80f4bSopenharmony_ci{
6408bf80f4bSopenharmony_ci    if (handle) {
6418bf80f4bSopenharmony_ci        const RenderHandle rawHandle = handle.GetHandle();
6428bf80f4bSopenharmony_ci        const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
6438bf80f4bSopenharmony_ci        // add name only if name not used yet
6448bf80f4bSopenharmony_ci        if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
6458bf80f4bSopenharmony_ci            (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
6468bf80f4bSopenharmony_ci            if (!nameToClientHandle_.contains(name)) {
6478bf80f4bSopenharmony_ci                nameToClientHandle_[name] = rawHandle;
6488bf80f4bSopenharmony_ci            } else {
6498bf80f4bSopenharmony_ci                PLUGIN_LOG_W("trying to add additional name (%s) for shader handle, but the name is already in use",
6508bf80f4bSopenharmony_ci                    name.data());
6518bf80f4bSopenharmony_ci            }
6528bf80f4bSopenharmony_ci        }
6538bf80f4bSopenharmony_ci    }
6548bf80f4bSopenharmony_ci}
6558bf80f4bSopenharmony_ci
6568bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreateComputeShader(
6578bf80f4bSopenharmony_ci    const ComputeShaderCreateInfo& createInfo, const string_view baseShaderPath, const string_view variantName)
6588bf80f4bSopenharmony_ci{
6598bf80f4bSopenharmony_ci    if (createInfo.shaderPaths.size() >= 1u) {
6608bf80f4bSopenharmony_ci        if (const uint32_t moduleIdx = GetShaderModuleIndex(createInfo.shaderPaths[0].path);
6618bf80f4bSopenharmony_ci            moduleIdx != INVALID_SM_INDEX) {
6628bf80f4bSopenharmony_ci            return Create(ComputeShaderCreateData { createInfo.path, createInfo.renderSlotId, createInfo.categoryId,
6638bf80f4bSopenharmony_ci                              RenderHandleUtil::GetIndexPart(createInfo.pipelineLayout), moduleIdx, {}, {} },
6648bf80f4bSopenharmony_ci                { baseShaderPath, variantName, {} });
6658bf80f4bSopenharmony_ci        } else {
6668bf80f4bSopenharmony_ci            PLUGIN_LOG_E("ShaderManager: compute shader (%s) creation failed, compute shader path (%s) not found",
6678bf80f4bSopenharmony_ci                string(createInfo.path).c_str(), string(createInfo.shaderPaths[0].path).c_str());
6688bf80f4bSopenharmony_ci        }
6698bf80f4bSopenharmony_ci    } else {
6708bf80f4bSopenharmony_ci        PLUGIN_LOG_E("ShaderManager: compute shader (%s) creation failed, no shader module paths given",
6718bf80f4bSopenharmony_ci            string(createInfo.path).c_str());
6728bf80f4bSopenharmony_ci    }
6738bf80f4bSopenharmony_ci    return {};
6748bf80f4bSopenharmony_ci}
6758bf80f4bSopenharmony_ci
6768bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreateComputeShader(const ComputeShaderCreateInfo& createInfo)
6778bf80f4bSopenharmony_ci{
6788bf80f4bSopenharmony_ci    return CreateComputeShader(createInfo, "", "");
6798bf80f4bSopenharmony_ci}
6808bf80f4bSopenharmony_ci
6818bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreateShader(
6828bf80f4bSopenharmony_ci    const ShaderCreateInfo& createInfo, const string_view baseShaderPath, const string_view variantName)
6838bf80f4bSopenharmony_ci{
6848bf80f4bSopenharmony_ci    if (createInfo.shaderPaths.size() >= 2u) {
6858bf80f4bSopenharmony_ci        const uint32_t vertShaderModule = GetShaderModuleIndex(createInfo.shaderPaths[0u].path);
6868bf80f4bSopenharmony_ci        const uint32_t fragShaderModule = GetShaderModuleIndex(createInfo.shaderPaths[1u].path);
6878bf80f4bSopenharmony_ci        if ((vertShaderModule != INVALID_SM_INDEX) && (fragShaderModule != INVALID_SM_INDEX)) {
6888bf80f4bSopenharmony_ci            return Create(ShaderCreateData { createInfo.path, createInfo.renderSlotId, createInfo.categoryId,
6898bf80f4bSopenharmony_ci                              RenderHandleUtil::GetIndexPart(createInfo.vertexInputDeclaration),
6908bf80f4bSopenharmony_ci                              RenderHandleUtil::GetIndexPart(createInfo.pipelineLayout),
6918bf80f4bSopenharmony_ci                              RenderHandleUtil::GetIndexPart(createInfo.graphicsState), vertShaderModule,
6928bf80f4bSopenharmony_ci                              fragShaderModule, {}, {} },
6938bf80f4bSopenharmony_ci                { baseShaderPath, variantName, {} });
6948bf80f4bSopenharmony_ci        } else {
6958bf80f4bSopenharmony_ci            PLUGIN_LOG_E("ShaderManager: shader (%s) creation failed, shader path (vert:%s) (frag:%s) not found",
6968bf80f4bSopenharmony_ci                string(createInfo.path).c_str(), string(createInfo.shaderPaths[0u].path).c_str(),
6978bf80f4bSopenharmony_ci                string(createInfo.shaderPaths[1u].path).c_str());
6988bf80f4bSopenharmony_ci        }
6998bf80f4bSopenharmony_ci    } else {
7008bf80f4bSopenharmony_ci        PLUGIN_LOG_E("ShaderManager: shader (%s) creation failed, no shader module paths given",
7018bf80f4bSopenharmony_ci            string(createInfo.path).c_str());
7028bf80f4bSopenharmony_ci    }
7038bf80f4bSopenharmony_ci    return {};
7048bf80f4bSopenharmony_ci}
7058bf80f4bSopenharmony_ci
7068bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreateShader(const ShaderCreateInfo& createInfo)
7078bf80f4bSopenharmony_ci{
7088bf80f4bSopenharmony_ci    return CreateShader(createInfo, "", "");
7098bf80f4bSopenharmony_ci}
7108bf80f4bSopenharmony_ci
7118bf80f4bSopenharmony_civoid ShaderManager::HandlePendingAllocations()
7128bf80f4bSopenharmony_ci{
7138bf80f4bSopenharmony_ci    pendingMutex_.lock();
7148bf80f4bSopenharmony_ci    decltype(pendingAllocations_) pendingAllocations = move(pendingAllocations_);
7158bf80f4bSopenharmony_ci    pendingMutex_.unlock();
7168bf80f4bSopenharmony_ci
7178bf80f4bSopenharmony_ci    for (const auto& handleRef : pendingAllocations.destroyHandles) {
7188bf80f4bSopenharmony_ci        const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handleRef);
7198bf80f4bSopenharmony_ci        const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handleRef);
7208bf80f4bSopenharmony_ci        if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
7218bf80f4bSopenharmony_ci            if (arrayIndex < static_cast<uint32_t>(computeShaders_.size())) {
7228bf80f4bSopenharmony_ci                computeShaders_[arrayIndex] = {};
7238bf80f4bSopenharmony_ci            }
7248bf80f4bSopenharmony_ci        } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
7258bf80f4bSopenharmony_ci            if (arrayIndex < static_cast<uint32_t>(shaders_.size())) {
7268bf80f4bSopenharmony_ci                shaders_[arrayIndex] = {};
7278bf80f4bSopenharmony_ci            }
7288bf80f4bSopenharmony_ci        }
7298bf80f4bSopenharmony_ci    }
7308bf80f4bSopenharmony_ci    HandlePendingShaders(pendingAllocations);
7318bf80f4bSopenharmony_ci    HandlePendingModules(pendingAllocations);
7328bf80f4bSopenharmony_ci
7338bf80f4bSopenharmony_ci    const uint64_t frameCount = device_.GetFrameCount();
7348bf80f4bSopenharmony_ci    constexpr uint64_t additionalFrameCount { 2u };
7358bf80f4bSopenharmony_ci    const auto minAge = device_.GetCommandBufferingCount() + additionalFrameCount;
7368bf80f4bSopenharmony_ci    const auto ageLimit = (frameCount < minAge) ? 0 : (frameCount - minAge);
7378bf80f4bSopenharmony_ci    auto CompareForErase = [](const auto ageLimit, auto& vec) {
7388bf80f4bSopenharmony_ci        for (auto iter = vec.begin(); iter != vec.end();) {
7398bf80f4bSopenharmony_ci            if (iter->frameIndex < ageLimit) {
7408bf80f4bSopenharmony_ci                iter = vec.erase(iter);
7418bf80f4bSopenharmony_ci            } else {
7428bf80f4bSopenharmony_ci                ++iter;
7438bf80f4bSopenharmony_ci            }
7448bf80f4bSopenharmony_ci        }
7458bf80f4bSopenharmony_ci    };
7468bf80f4bSopenharmony_ci    CompareForErase(ageLimit, deferredDestructions_.shaderModules);
7478bf80f4bSopenharmony_ci    CompareForErase(ageLimit, deferredDestructions_.computePrograms);
7488bf80f4bSopenharmony_ci    CompareForErase(ageLimit, deferredDestructions_.shaderPrograms);
7498bf80f4bSopenharmony_ci
7508bf80f4bSopenharmony_ci    std::swap(reloadedShadersForBackend_, reloadedShaders_);
7518bf80f4bSopenharmony_ci    reloadedShaders_.clear();
7528bf80f4bSopenharmony_ci}
7538bf80f4bSopenharmony_ci
7548bf80f4bSopenharmony_civoid ShaderManager::HandlePendingShaders(Allocs& allocs)
7558bf80f4bSopenharmony_ci{
7568bf80f4bSopenharmony_ci    const uint64_t frameCount = device_.GetFrameCount();
7578bf80f4bSopenharmony_ci    for (const auto& ref : allocs.computeShaders) {
7588bf80f4bSopenharmony_ci        const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(ref.handle);
7598bf80f4bSopenharmony_ci        ShaderModule* shaderModule = GetShaderModule(ref.computeModuleIndex);
7608bf80f4bSopenharmony_ci        if (shaderModule) {
7618bf80f4bSopenharmony_ci            if (arrayIndex < static_cast<uint32_t>(computeShaders_.size())) {
7628bf80f4bSopenharmony_ci                // replace with new (push old for deferred destruction)
7638bf80f4bSopenharmony_ci                deferredDestructions_.computePrograms.push_back({ frameCount, move(computeShaders_[arrayIndex].gsp) });
7648bf80f4bSopenharmony_ci                computeShaders_[arrayIndex] = { device_.CreateGpuComputeProgram({ shaderModule }),
7658bf80f4bSopenharmony_ci                    ref.pipelineLayoutIndex, ref.computeModuleIndex };
7668bf80f4bSopenharmony_ci            } else {
7678bf80f4bSopenharmony_ci                // new gpu resource
7688bf80f4bSopenharmony_ci                computeShaders_.push_back({ device_.CreateGpuComputeProgram({ shaderModule }), ref.pipelineLayoutIndex,
7698bf80f4bSopenharmony_ci                    ref.computeModuleIndex });
7708bf80f4bSopenharmony_ci            }
7718bf80f4bSopenharmony_ci        }
7728bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
7738bf80f4bSopenharmony_ci        if (!shaderModule) {
7748bf80f4bSopenharmony_ci            PLUGIN_LOG_E("RENDER_VALIDATION: Compute shader module with index:%u, not found", ref.computeModuleIndex);
7758bf80f4bSopenharmony_ci        }
7768bf80f4bSopenharmony_ci#endif
7778bf80f4bSopenharmony_ci    }
7788bf80f4bSopenharmony_ci    for (const auto& ref : allocs.shaders) {
7798bf80f4bSopenharmony_ci        uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(ref.handle);
7808bf80f4bSopenharmony_ci        ShaderModule* vertShaderModule = GetShaderModule(ref.vertModuleIndex);
7818bf80f4bSopenharmony_ci        ShaderModule* fragShaderModule = GetShaderModule(ref.fragModuleIndex);
7828bf80f4bSopenharmony_ci        if (vertShaderModule && fragShaderModule) {
7838bf80f4bSopenharmony_ci            if ((arrayIndex < static_cast<uint32_t>(shaders_.size()))) {
7848bf80f4bSopenharmony_ci                // replace with new (push old for deferred destruction)
7858bf80f4bSopenharmony_ci                deferredDestructions_.shaderPrograms.push_back({ frameCount, move(shaders_[arrayIndex].gsp) });
7868bf80f4bSopenharmony_ci                shaders_[arrayIndex] = { device_.CreateGpuShaderProgram({ vertShaderModule, fragShaderModule }),
7878bf80f4bSopenharmony_ci                    ref.pipelineLayoutIndex, ref.vertexInputDeclIndex, ref.vertModuleIndex, ref.fragModuleIndex };
7888bf80f4bSopenharmony_ci            } else { // new gpu resource
7898bf80f4bSopenharmony_ci                shaders_.push_back({ device_.CreateGpuShaderProgram({ vertShaderModule, fragShaderModule }),
7908bf80f4bSopenharmony_ci                    ref.pipelineLayoutIndex, ref.vertexInputDeclIndex, ref.vertModuleIndex, ref.fragModuleIndex });
7918bf80f4bSopenharmony_ci            }
7928bf80f4bSopenharmony_ci        }
7938bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
7948bf80f4bSopenharmony_ci        if ((!vertShaderModule) || (!fragShaderModule)) {
7958bf80f4bSopenharmony_ci            PLUGIN_LOG_E("RENDER_VALIDATION: Shader module with index: %u or %u, not found", ref.vertModuleIndex,
7968bf80f4bSopenharmony_ci                ref.fragModuleIndex);
7978bf80f4bSopenharmony_ci        }
7988bf80f4bSopenharmony_ci#endif
7998bf80f4bSopenharmony_ci    }
8008bf80f4bSopenharmony_ci}
8018bf80f4bSopenharmony_ci
8028bf80f4bSopenharmony_civoid ShaderManager::HandlePendingModules(Allocs& allocs)
8038bf80f4bSopenharmony_ci{
8048bf80f4bSopenharmony_ci    const uint64_t frameCount = device_.GetFrameCount();
8058bf80f4bSopenharmony_ci    for (const auto modIdx : allocs.recreatedComputeModuleIndices) {
8068bf80f4bSopenharmony_ci        for (auto& shaderRef : computeShaders_) {
8078bf80f4bSopenharmony_ci            if (modIdx == shaderRef.compModuleIndex) {
8088bf80f4bSopenharmony_ci                if (ShaderModule* compModule = GetShaderModule(shaderRef.compModuleIndex); compModule) {
8098bf80f4bSopenharmony_ci                    deferredDestructions_.computePrograms.push_back({ frameCount, move(shaderRef.gsp) });
8108bf80f4bSopenharmony_ci                    shaderRef.gsp = device_.CreateGpuComputeProgram({ compModule });
8118bf80f4bSopenharmony_ci                }
8128bf80f4bSopenharmony_ci            }
8138bf80f4bSopenharmony_ci        }
8148bf80f4bSopenharmony_ci    }
8158bf80f4bSopenharmony_ci    for (const auto modIdx : allocs.recreatedShaderModuleIndices) {
8168bf80f4bSopenharmony_ci        for (auto& shaderRef : shaders_) {
8178bf80f4bSopenharmony_ci            if ((modIdx == shaderRef.vertModuleIndex) || (modIdx == shaderRef.fragModuleIndex)) {
8188bf80f4bSopenharmony_ci                ShaderModule* vertModule = GetShaderModule(shaderRef.vertModuleIndex);
8198bf80f4bSopenharmony_ci                ShaderModule* fragModule = GetShaderModule(shaderRef.fragModuleIndex);
8208bf80f4bSopenharmony_ci                if (vertModule && fragModule) {
8218bf80f4bSopenharmony_ci                    deferredDestructions_.shaderPrograms.push_back({ frameCount, move(shaderRef.gsp) });
8228bf80f4bSopenharmony_ci                    shaderRef.gsp = device_.CreateGpuShaderProgram({ vertModule, fragModule });
8238bf80f4bSopenharmony_ci                }
8248bf80f4bSopenharmony_ci            }
8258bf80f4bSopenharmony_ci        }
8268bf80f4bSopenharmony_ci    }
8278bf80f4bSopenharmony_ci}
8288bf80f4bSopenharmony_ci
8298bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetShaderHandle(const string_view path) const
8308bf80f4bSopenharmony_ci{
8318bf80f4bSopenharmony_ci    const RenderHandle handle = GetHandle(path, nameToClientHandle_);
8328bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
8338bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
8348bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
8358bf80f4bSopenharmony_ci        (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
8368bf80f4bSopenharmony_ci        return computeShaderMappings_.clientData[index].rhr;
8378bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
8388bf80f4bSopenharmony_ci               (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
8398bf80f4bSopenharmony_ci        return shaderMappings_.clientData[index].rhr;
8408bf80f4bSopenharmony_ci    } else {
8418bf80f4bSopenharmony_ci        PLUGIN_LOG_W("ShaderManager: invalid shader %s", path.data());
8428bf80f4bSopenharmony_ci        return {};
8438bf80f4bSopenharmony_ci    }
8448bf80f4bSopenharmony_ci}
8458bf80f4bSopenharmony_ci
8468bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetShaderHandle(const string_view path, const string_view variantName) const
8478bf80f4bSopenharmony_ci{
8488bf80f4bSopenharmony_ci    const string fullName = path + variantName;
8498bf80f4bSopenharmony_ci    const RenderHandle handle = GetHandle(fullName, nameToClientHandle_);
8508bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
8518bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
8528bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
8538bf80f4bSopenharmony_ci        (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
8548bf80f4bSopenharmony_ci        return computeShaderMappings_.clientData[index].rhr;
8558bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
8568bf80f4bSopenharmony_ci               (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
8578bf80f4bSopenharmony_ci        return shaderMappings_.clientData[index].rhr;
8588bf80f4bSopenharmony_ci    } else {
8598bf80f4bSopenharmony_ci        PLUGIN_LOG_W("ShaderManager: invalid shader (%s) variant (%s)", path.data(), variantName.data());
8608bf80f4bSopenharmony_ci        return {};
8618bf80f4bSopenharmony_ci    }
8628bf80f4bSopenharmony_ci}
8638bf80f4bSopenharmony_ci
8648bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetShaderHandle(const RenderHandle& handle, const uint32_t renderSlotId) const
8658bf80f4bSopenharmony_ci{
8668bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
8678bf80f4bSopenharmony_ci    if ((handleType != RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
8688bf80f4bSopenharmony_ci        (handleType != RenderHandleType::SHADER_STATE_OBJECT)) {
8698bf80f4bSopenharmony_ci        return {}; // early out
8708bf80f4bSopenharmony_ci    }
8718bf80f4bSopenharmony_ci
8728bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
8738bf80f4bSopenharmony_ci    RenderHandle baseShaderHandle;
8748bf80f4bSopenharmony_ci    // check first for own validity and possible base shader handle
8758bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
8768bf80f4bSopenharmony_ci        (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
8778bf80f4bSopenharmony_ci        const auto& ref = computeShaderMappings_.clientData[index];
8788bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
8798bf80f4bSopenharmony_ci            return ref.rhr;
8808bf80f4bSopenharmony_ci        }
8818bf80f4bSopenharmony_ci        baseShaderHandle = ref.baseShaderHandle;
8828bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
8838bf80f4bSopenharmony_ci               (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
8848bf80f4bSopenharmony_ci        const auto& ref = shaderMappings_.clientData[index];
8858bf80f4bSopenharmony_ci        if (ref.renderSlotId == renderSlotId) {
8868bf80f4bSopenharmony_ci            return ref.rhr;
8878bf80f4bSopenharmony_ci        }
8888bf80f4bSopenharmony_ci        baseShaderHandle = ref.baseShaderHandle;
8898bf80f4bSopenharmony_ci    }
8908bf80f4bSopenharmony_ci    // try to find a match through base shader variant
8918bf80f4bSopenharmony_ci    if (RenderHandleUtil::IsValid(baseShaderHandle)) {
8928bf80f4bSopenharmony_ci        const uint64_t hash = HashHandleAndSlot(baseShaderHandle, renderSlotId);
8938bf80f4bSopenharmony_ci        if (const auto iter = hashToShaderVariant_.find(hash); iter != hashToShaderVariant_.cend()) {
8948bf80f4bSopenharmony_ci            const RenderHandleType baseHandleType = RenderHandleUtil::GetHandleType(iter->second);
8958bf80f4bSopenharmony_ci            const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(iter->second);
8968bf80f4bSopenharmony_ci            if ((baseHandleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
8978bf80f4bSopenharmony_ci                (arrayIndex < computeShaderMappings_.clientData.size())) {
8988bf80f4bSopenharmony_ci                PLUGIN_ASSERT(computeShaderMappings_.clientData[arrayIndex].renderSlotId == renderSlotId);
8998bf80f4bSopenharmony_ci                return computeShaderMappings_.clientData[arrayIndex].rhr;
9008bf80f4bSopenharmony_ci            } else if ((baseHandleType == RenderHandleType::SHADER_STATE_OBJECT) &&
9018bf80f4bSopenharmony_ci                       (arrayIndex < shaderMappings_.clientData.size())) {
9028bf80f4bSopenharmony_ci                PLUGIN_ASSERT(shaderMappings_.clientData[arrayIndex].renderSlotId == renderSlotId);
9038bf80f4bSopenharmony_ci                return shaderMappings_.clientData[arrayIndex].rhr;
9048bf80f4bSopenharmony_ci            }
9058bf80f4bSopenharmony_ci        }
9068bf80f4bSopenharmony_ci    }
9078bf80f4bSopenharmony_ci    return {};
9088bf80f4bSopenharmony_ci}
9098bf80f4bSopenharmony_ci
9108bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetShaderHandle(
9118bf80f4bSopenharmony_ci    const RenderHandleReference& handle, const uint32_t renderSlotId) const
9128bf80f4bSopenharmony_ci{
9138bf80f4bSopenharmony_ci    return GetShaderHandle(handle.GetHandle(), renderSlotId);
9148bf80f4bSopenharmony_ci}
9158bf80f4bSopenharmony_ci
9168bf80f4bSopenharmony_civector<RenderHandleReference> ShaderManager::GetShaders(const uint32_t renderSlotId) const
9178bf80f4bSopenharmony_ci{
9188bf80f4bSopenharmony_ci    vector<RenderHandleReference> shaders;
9198bf80f4bSopenharmony_ci    GetShadersBySlot(renderSlotId, shaderMappings_, shaders);
9208bf80f4bSopenharmony_ci    GetShadersBySlot(renderSlotId, computeShaderMappings_, shaders);
9218bf80f4bSopenharmony_ci    return shaders;
9228bf80f4bSopenharmony_ci}
9238bf80f4bSopenharmony_ci
9248bf80f4bSopenharmony_civector<RenderHandle> ShaderManager::GetShaderRawHandles(const uint32_t renderSlotId) const
9258bf80f4bSopenharmony_ci{
9268bf80f4bSopenharmony_ci    vector<RenderHandle> shaders;
9278bf80f4bSopenharmony_ci    GetShadersBySlot(renderSlotId, shaderMappings_, shaders);
9288bf80f4bSopenharmony_ci    GetShadersBySlot(renderSlotId, computeShaderMappings_, shaders);
9298bf80f4bSopenharmony_ci    return shaders;
9308bf80f4bSopenharmony_ci}
9318bf80f4bSopenharmony_ci
9328bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreateGraphicsState(
9338bf80f4bSopenharmony_ci    const GraphicsStateCreateInfo& createInfo, const GraphicsStateVariantCreateInfo& variantCreateInfo)
9348bf80f4bSopenharmony_ci{
9358bf80f4bSopenharmony_ci    PLUGIN_ASSERT(graphicsStates_.rhr.size() == graphicsStates_.graphicsStates.size());
9368bf80f4bSopenharmony_ci    const uint32_t renderSlotId = CreateRenderSlotId(variantCreateInfo.renderSlot);
9378bf80f4bSopenharmony_ci    // NOTE: No collisions expected if path is used
9388bf80f4bSopenharmony_ci    const string fullName = createInfo.path + variantCreateInfo.variant;
9398bf80f4bSopenharmony_ci    uint32_t arrayIndex = INVALID_SM_INDEX;
9408bf80f4bSopenharmony_ci    if (auto nameIter = graphicsStates_.nameToIndex.find(fullName); nameIter != graphicsStates_.nameToIndex.end()) {
9418bf80f4bSopenharmony_ci        arrayIndex = static_cast<uint32_t>(nameIter->second);
9428bf80f4bSopenharmony_ci    }
9438bf80f4bSopenharmony_ci
9448bf80f4bSopenharmony_ci    uint32_t baseVariantIndex = INVALID_SM_INDEX;
9458bf80f4bSopenharmony_ci    RenderHandleReference rhr;
9468bf80f4bSopenharmony_ci    if (arrayIndex < graphicsStates_.rhr.size()) {
9478bf80f4bSopenharmony_ci        rhr = graphicsStates_.rhr[arrayIndex];
9488bf80f4bSopenharmony_ci        graphicsStates_.graphicsStates[arrayIndex] = createInfo.graphicsState;
9498bf80f4bSopenharmony_ci        const uint64_t hash = HashGraphicsState(createInfo.graphicsState);
9508bf80f4bSopenharmony_ci        baseVariantIndex = GetBaseGraphicsStateVariantIndex(graphicsStates_, variantCreateInfo);
9518bf80f4bSopenharmony_ci        graphicsStates_.data[arrayIndex] = { hash, renderSlotId, baseVariantIndex, variantCreateInfo.stateFlags };
9528bf80f4bSopenharmony_ci        graphicsStates_.hashToIndex[hash] = arrayIndex;
9538bf80f4bSopenharmony_ci    } else { // new
9548bf80f4bSopenharmony_ci        arrayIndex = static_cast<uint32_t>(graphicsStates_.rhr.size());
9558bf80f4bSopenharmony_ci        // NOTE: these are only updated for new states
9568bf80f4bSopenharmony_ci        if (!fullName.empty()) {
9578bf80f4bSopenharmony_ci            graphicsStates_.nameToIndex[fullName] = arrayIndex;
9588bf80f4bSopenharmony_ci        }
9598bf80f4bSopenharmony_ci        const RenderHandle handle = RenderHandleUtil::CreateHandle(RenderHandleType::GRAPHICS_STATE, arrayIndex);
9608bf80f4bSopenharmony_ci        graphicsStates_.rhr.push_back(
9618bf80f4bSopenharmony_ci            RenderHandleReference(handle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter())));
9628bf80f4bSopenharmony_ci        rhr = graphicsStates_.rhr[arrayIndex];
9638bf80f4bSopenharmony_ci        graphicsStates_.graphicsStates.push_back(createInfo.graphicsState);
9648bf80f4bSopenharmony_ci        const uint64_t hash = HashGraphicsState(createInfo.graphicsState);
9658bf80f4bSopenharmony_ci        // ordering matters, this fetches from nameToIndex
9668bf80f4bSopenharmony_ci        baseVariantIndex = GetBaseGraphicsStateVariantIndex(graphicsStates_, variantCreateInfo);
9678bf80f4bSopenharmony_ci        graphicsStates_.data.push_back({ hash, renderSlotId, baseVariantIndex, variantCreateInfo.stateFlags });
9688bf80f4bSopenharmony_ci        graphicsStates_.hashToIndex[hash] = arrayIndex;
9698bf80f4bSopenharmony_ci    }
9708bf80f4bSopenharmony_ci    if (baseVariantIndex < graphicsStates_.rhr.size()) {
9718bf80f4bSopenharmony_ci        const uint64_t variantHash = HashHandleAndSlot(graphicsStates_.rhr[baseVariantIndex].GetHandle(), renderSlotId);
9728bf80f4bSopenharmony_ci        if (variantHash != INVALID_SM_INDEX) {
9738bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
9748bf80f4bSopenharmony_ci            if (graphicsStates_.variantHashToIndex.contains(variantHash)) {
9758bf80f4bSopenharmony_ci                PLUGIN_LOG_W("RENDER_VALIDATION: overwriting variant hash with %s %s", createInfo.path.data(),
9768bf80f4bSopenharmony_ci                    variantCreateInfo.variant.data());
9778bf80f4bSopenharmony_ci            }
9788bf80f4bSopenharmony_ci#endif
9798bf80f4bSopenharmony_ci            graphicsStates_.variantHashToIndex[variantHash] = RenderHandleUtil::GetIndexPart(rhr.GetHandle());
9808bf80f4bSopenharmony_ci        }
9818bf80f4bSopenharmony_ci    }
9828bf80f4bSopenharmony_ci
9838bf80f4bSopenharmony_ci    return rhr;
9848bf80f4bSopenharmony_ci}
9858bf80f4bSopenharmony_ci
9868bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreateGraphicsState(const GraphicsStateCreateInfo& createInfo)
9878bf80f4bSopenharmony_ci{
9888bf80f4bSopenharmony_ci    return CreateGraphicsState(createInfo, {});
9898bf80f4bSopenharmony_ci}
9908bf80f4bSopenharmony_ci
9918bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetGraphicsStateHandle(const string_view path) const
9928bf80f4bSopenharmony_ci{
9938bf80f4bSopenharmony_ci    if (const auto iter = graphicsStates_.nameToIndex.find(path); iter != graphicsStates_.nameToIndex.cend()) {
9948bf80f4bSopenharmony_ci        PLUGIN_ASSERT(iter->second < graphicsStates_.rhr.size());
9958bf80f4bSopenharmony_ci        return graphicsStates_.rhr[iter->second];
9968bf80f4bSopenharmony_ci    } else {
9978bf80f4bSopenharmony_ci        PLUGIN_LOG_W("ShaderManager: named graphics state not found: %s", string(path).c_str());
9988bf80f4bSopenharmony_ci        return {};
9998bf80f4bSopenharmony_ci    }
10008bf80f4bSopenharmony_ci}
10018bf80f4bSopenharmony_ci
10028bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetGraphicsStateHandle(const string_view path, const string_view variantName) const
10038bf80f4bSopenharmony_ci{
10048bf80f4bSopenharmony_ci    // NOTE: does not call the base GetGraphicsStateHandle due to better error logging
10058bf80f4bSopenharmony_ci    const string fullName = string(path + variantName);
10068bf80f4bSopenharmony_ci    if (const auto iter = graphicsStates_.nameToIndex.find(fullName); iter != graphicsStates_.nameToIndex.cend()) {
10078bf80f4bSopenharmony_ci        PLUGIN_ASSERT(iter->second < graphicsStates_.rhr.size());
10088bf80f4bSopenharmony_ci        return graphicsStates_.rhr[iter->second];
10098bf80f4bSopenharmony_ci    } else {
10108bf80f4bSopenharmony_ci        PLUGIN_LOG_W(
10118bf80f4bSopenharmony_ci            "ShaderManager: named graphics state not found (name: %s variant: %s)", path.data(), variantName.data());
10128bf80f4bSopenharmony_ci        return {};
10138bf80f4bSopenharmony_ci    }
10148bf80f4bSopenharmony_ci}
10158bf80f4bSopenharmony_ci
10168bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetGraphicsStateHandle(
10178bf80f4bSopenharmony_ci    const RenderHandle& handle, const uint32_t renderSlotId) const
10188bf80f4bSopenharmony_ci{
10198bf80f4bSopenharmony_ci    if (RenderHandleUtil::GetHandleType(handle) == RenderHandleType::GRAPHICS_STATE) {
10208bf80f4bSopenharmony_ci        const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
10218bf80f4bSopenharmony_ci        if (arrayIndex < static_cast<uint32_t>(graphicsStates_.data.size())) {
10228bf80f4bSopenharmony_ci            // check for own validity
10238bf80f4bSopenharmony_ci            const auto& data = graphicsStates_.data[arrayIndex];
10248bf80f4bSopenharmony_ci            if (renderSlotId == data.renderSlotId) {
10258bf80f4bSopenharmony_ci                return graphicsStates_.rhr[arrayIndex];
10268bf80f4bSopenharmony_ci            }
10278bf80f4bSopenharmony_ci            // check for base variant for hashing
10288bf80f4bSopenharmony_ci            if (data.baseVariantIndex < static_cast<uint32_t>(graphicsStates_.data.size())) {
10298bf80f4bSopenharmony_ci                const RenderHandle baseHandle = graphicsStates_.rhr[data.baseVariantIndex].GetHandle();
10308bf80f4bSopenharmony_ci                const uint64_t hash = HashHandleAndSlot(baseHandle, renderSlotId);
10318bf80f4bSopenharmony_ci                if (const auto iter = graphicsStates_.variantHashToIndex.find(hash);
10328bf80f4bSopenharmony_ci                    iter != graphicsStates_.variantHashToIndex.cend()) {
10338bf80f4bSopenharmony_ci                    PLUGIN_ASSERT(iter->second < static_cast<uint32_t>(graphicsStates_.rhr.size()));
10348bf80f4bSopenharmony_ci                    return graphicsStates_.rhr[iter->second];
10358bf80f4bSopenharmony_ci                }
10368bf80f4bSopenharmony_ci            }
10378bf80f4bSopenharmony_ci        }
10388bf80f4bSopenharmony_ci    }
10398bf80f4bSopenharmony_ci    return {};
10408bf80f4bSopenharmony_ci}
10418bf80f4bSopenharmony_ci
10428bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetGraphicsStateHandle(
10438bf80f4bSopenharmony_ci    const RenderHandleReference& handle, const uint32_t renderSlotId) const
10448bf80f4bSopenharmony_ci{
10458bf80f4bSopenharmony_ci    return GetGraphicsStateHandle(handle.GetHandle(), renderSlotId);
10468bf80f4bSopenharmony_ci}
10478bf80f4bSopenharmony_ci
10488bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetGraphicsStateHandleByHash(const uint64_t hash) const
10498bf80f4bSopenharmony_ci{
10508bf80f4bSopenharmony_ci    if (const auto iter = graphicsStates_.hashToIndex.find(hash); iter != graphicsStates_.hashToIndex.cend()) {
10518bf80f4bSopenharmony_ci        PLUGIN_ASSERT(iter->second < graphicsStates_.rhr.size());
10528bf80f4bSopenharmony_ci        return graphicsStates_.rhr[iter->second];
10538bf80f4bSopenharmony_ci    } else {
10548bf80f4bSopenharmony_ci        return {};
10558bf80f4bSopenharmony_ci    }
10568bf80f4bSopenharmony_ci}
10578bf80f4bSopenharmony_ci
10588bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetGraphicsStateHandleByShaderHandle(const RenderHandle& handle) const
10598bf80f4bSopenharmony_ci{
10608bf80f4bSopenharmony_ci    if (RenderHandleUtil::GetHandleType(handle) == RenderHandleType::SHADER_STATE_OBJECT) {
10618bf80f4bSopenharmony_ci        const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
10628bf80f4bSopenharmony_ci        if (arrayIndex < static_cast<uint32_t>(shaderMappings_.clientData.size())) {
10638bf80f4bSopenharmony_ci            const uint32_t gsIndex = shaderMappings_.clientData[arrayIndex].graphicsStateIndex;
10648bf80f4bSopenharmony_ci            if (gsIndex < static_cast<uint32_t>(graphicsStates_.graphicsStates.size())) {
10658bf80f4bSopenharmony_ci                return graphicsStates_.rhr[gsIndex];
10668bf80f4bSopenharmony_ci            }
10678bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
10688bf80f4bSopenharmony_ci            PLUGIN_ASSERT(gsIndex != INVALID_SM_INDEX); // not and optional index ATM
10698bf80f4bSopenharmony_ci            PLUGIN_ASSERT(gsIndex < graphicsStates_.rhr.size());
10708bf80f4bSopenharmony_ci#endif
10718bf80f4bSopenharmony_ci        }
10728bf80f4bSopenharmony_ci    }
10738bf80f4bSopenharmony_ci    return {};
10748bf80f4bSopenharmony_ci}
10758bf80f4bSopenharmony_ci
10768bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetGraphicsStateHandleByShaderHandle(const RenderHandleReference& handle) const
10778bf80f4bSopenharmony_ci{
10788bf80f4bSopenharmony_ci    return GetGraphicsStateHandleByShaderHandle(handle.GetHandle());
10798bf80f4bSopenharmony_ci}
10808bf80f4bSopenharmony_ci
10818bf80f4bSopenharmony_ciGraphicsState ShaderManager::GetGraphicsState(const RenderHandleReference& handle) const
10828bf80f4bSopenharmony_ci{
10838bf80f4bSopenharmony_ci    return GetGraphicsStateRef(handle);
10848bf80f4bSopenharmony_ci}
10858bf80f4bSopenharmony_ci
10868bf80f4bSopenharmony_civector<RenderHandleReference> ShaderManager::GetGraphicsStates(const uint32_t renderSlotId) const
10878bf80f4bSopenharmony_ci{
10888bf80f4bSopenharmony_ci    vector<RenderHandleReference> gfxStates;
10898bf80f4bSopenharmony_ci    GetGraphicsStatesBySlot(renderSlotId, graphicsStates_, gfxStates);
10908bf80f4bSopenharmony_ci    return gfxStates;
10918bf80f4bSopenharmony_ci}
10928bf80f4bSopenharmony_ci
10938bf80f4bSopenharmony_ciconst GraphicsState& ShaderManager::GetGraphicsStateRef(const RenderHandle& handle) const
10948bf80f4bSopenharmony_ci{
10958bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
10968bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
10978bf80f4bSopenharmony_ci    if ((type == RenderHandleType::GRAPHICS_STATE) &&
10988bf80f4bSopenharmony_ci        (arrayIndex < static_cast<uint32_t>(graphicsStates_.graphicsStates.size()))) {
10998bf80f4bSopenharmony_ci        return graphicsStates_.graphicsStates[arrayIndex];
11008bf80f4bSopenharmony_ci    } else {
11018bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
11028bf80f4bSopenharmony_ci        if (RenderHandleUtil::IsValid(handle) && (type != RenderHandleType::GRAPHICS_STATE)) {
11038bf80f4bSopenharmony_ci            PLUGIN_LOG_W("RENDER_VALIDATION: invalid handle type given to GetGraphicsState()");
11048bf80f4bSopenharmony_ci        }
11058bf80f4bSopenharmony_ci#endif
11068bf80f4bSopenharmony_ci        return defaultGraphicsState_;
11078bf80f4bSopenharmony_ci    }
11088bf80f4bSopenharmony_ci}
11098bf80f4bSopenharmony_ci
11108bf80f4bSopenharmony_ciconst GraphicsState& ShaderManager::GetGraphicsStateRef(const RenderHandleReference& handle) const
11118bf80f4bSopenharmony_ci{
11128bf80f4bSopenharmony_ci    return GetGraphicsStateRef(handle.GetHandle());
11138bf80f4bSopenharmony_ci}
11148bf80f4bSopenharmony_ci
11158bf80f4bSopenharmony_ciuint32_t ShaderManager::GetRenderSlotId(const string_view renderSlot) const
11168bf80f4bSopenharmony_ci{
11178bf80f4bSopenharmony_ci    if (const auto iter = renderSlotIds_.nameToId.find(renderSlot); iter != renderSlotIds_.nameToId.cend()) {
11188bf80f4bSopenharmony_ci        return iter->second;
11198bf80f4bSopenharmony_ci    } else {
11208bf80f4bSopenharmony_ci        return INVALID_SM_INDEX;
11218bf80f4bSopenharmony_ci    }
11228bf80f4bSopenharmony_ci}
11238bf80f4bSopenharmony_ci
11248bf80f4bSopenharmony_ciuint32_t ShaderManager::GetRenderSlotId(const RenderHandle& handle) const
11258bf80f4bSopenharmony_ci{
11268bf80f4bSopenharmony_ci    uint32_t id = ~0u;
11278bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
11288bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
11298bf80f4bSopenharmony_ci    if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
11308bf80f4bSopenharmony_ci        if (arrayIndex < computeShaderMappings_.clientData.size()) {
11318bf80f4bSopenharmony_ci            id = computeShaderMappings_.clientData[arrayIndex].renderSlotId;
11328bf80f4bSopenharmony_ci        }
11338bf80f4bSopenharmony_ci    } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
11348bf80f4bSopenharmony_ci        if (arrayIndex < shaderMappings_.clientData.size()) {
11358bf80f4bSopenharmony_ci            id = shaderMappings_.clientData[arrayIndex].renderSlotId;
11368bf80f4bSopenharmony_ci        }
11378bf80f4bSopenharmony_ci    } else if (handleType == RenderHandleType::GRAPHICS_STATE) {
11388bf80f4bSopenharmony_ci        if (arrayIndex < graphicsStates_.data.size()) {
11398bf80f4bSopenharmony_ci            id = graphicsStates_.data[arrayIndex].renderSlotId;
11408bf80f4bSopenharmony_ci        }
11418bf80f4bSopenharmony_ci    }
11428bf80f4bSopenharmony_ci    return id;
11438bf80f4bSopenharmony_ci}
11448bf80f4bSopenharmony_ci
11458bf80f4bSopenharmony_ciuint32_t ShaderManager::GetRenderSlotId(const RenderHandleReference& handle) const
11468bf80f4bSopenharmony_ci{
11478bf80f4bSopenharmony_ci    return GetRenderSlotId(handle.GetHandle());
11488bf80f4bSopenharmony_ci}
11498bf80f4bSopenharmony_ci
11508bf80f4bSopenharmony_ciIShaderManager::RenderSlotData ShaderManager::GetRenderSlotData(const uint32_t renderSlotId) const
11518bf80f4bSopenharmony_ci{
11528bf80f4bSopenharmony_ci    if (renderSlotId < static_cast<uint32_t>(renderSlotIds_.data.size())) {
11538bf80f4bSopenharmony_ci        return renderSlotIds_.data[renderSlotId];
11548bf80f4bSopenharmony_ci    } else {
11558bf80f4bSopenharmony_ci        return {};
11568bf80f4bSopenharmony_ci    }
11578bf80f4bSopenharmony_ci}
11588bf80f4bSopenharmony_ci
11598bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle& handle) const
11608bf80f4bSopenharmony_ci{
11618bf80f4bSopenharmony_ci    if (RenderHandleUtil::GetHandleType(handle) == RenderHandleType::SHADER_STATE_OBJECT) {
11628bf80f4bSopenharmony_ci        const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
11638bf80f4bSopenharmony_ci        auto& mappings = shaderMappings_;
11648bf80f4bSopenharmony_ci        if (arrayIndex < mappings.clientData.size()) {
11658bf80f4bSopenharmony_ci            const uint32_t vidIndex = mappings.clientData[arrayIndex].vertexInputDeclarationIndex;
11668bf80f4bSopenharmony_ci            if (vidIndex < shaderVid_.rhr.size()) {
11678bf80f4bSopenharmony_ci                PLUGIN_ASSERT(vidIndex < shaderVid_.rhr.size());
11688bf80f4bSopenharmony_ci                return shaderVid_.rhr[vidIndex];
11698bf80f4bSopenharmony_ci            }
11708bf80f4bSopenharmony_ci        }
11718bf80f4bSopenharmony_ci    }
11728bf80f4bSopenharmony_ci    return {};
11738bf80f4bSopenharmony_ci}
11748bf80f4bSopenharmony_ci
11758bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetVertexInputDeclarationHandleByShaderHandle(
11768bf80f4bSopenharmony_ci    const RenderHandleReference& handle) const
11778bf80f4bSopenharmony_ci{
11788bf80f4bSopenharmony_ci    return GetVertexInputDeclarationHandleByShaderHandle(handle.GetHandle());
11798bf80f4bSopenharmony_ci}
11808bf80f4bSopenharmony_ci
11818bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetVertexInputDeclarationHandle(const string_view path) const
11828bf80f4bSopenharmony_ci{
11838bf80f4bSopenharmony_ci    if (const auto iter = shaderVid_.nameToIndex.find(path); iter != shaderVid_.nameToIndex.cend()) {
11848bf80f4bSopenharmony_ci        PLUGIN_ASSERT(iter->second < shaderVid_.rhr.size());
11858bf80f4bSopenharmony_ci        return shaderVid_.rhr[iter->second];
11868bf80f4bSopenharmony_ci    } else {
11878bf80f4bSopenharmony_ci        PLUGIN_LOG_W("ShaderManager: vertex input declaration not found: %s", path.data());
11888bf80f4bSopenharmony_ci        return {};
11898bf80f4bSopenharmony_ci    }
11908bf80f4bSopenharmony_ci}
11918bf80f4bSopenharmony_ci
11928bf80f4bSopenharmony_ciVertexInputDeclarationView ShaderManager::GetVertexInputDeclarationView(const RenderHandle& handle) const
11938bf80f4bSopenharmony_ci{
11948bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
11958bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
11968bf80f4bSopenharmony_ci    if ((type == RenderHandleType::VERTEX_INPUT_DECLARATION) &&
11978bf80f4bSopenharmony_ci        (index < static_cast<uint32_t>(shaderVid_.data.size()))) {
11988bf80f4bSopenharmony_ci        const auto& ref = shaderVid_.data[index];
11998bf80f4bSopenharmony_ci        return {
12008bf80f4bSopenharmony_ci            array_view<const VertexInputDeclaration::VertexInputBindingDescription>(
12018bf80f4bSopenharmony_ci                ref.bindingDescriptions, ref.bindingDescriptionCount),
12028bf80f4bSopenharmony_ci            array_view<const VertexInputDeclaration::VertexInputAttributeDescription>(
12038bf80f4bSopenharmony_ci                ref.attributeDescriptions, ref.attributeDescriptionCount),
12048bf80f4bSopenharmony_ci        };
12058bf80f4bSopenharmony_ci    } else {
12068bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
12078bf80f4bSopenharmony_ci        if (RenderHandleUtil::IsValid(handle) && (type != RenderHandleType::VERTEX_INPUT_DECLARATION)) {
12088bf80f4bSopenharmony_ci            PLUGIN_LOG_W("RENDER_VALIDATION: invalid handle type given to GetVertexInputDeclarationView()");
12098bf80f4bSopenharmony_ci        }
12108bf80f4bSopenharmony_ci#endif
12118bf80f4bSopenharmony_ci        return {};
12128bf80f4bSopenharmony_ci    }
12138bf80f4bSopenharmony_ci}
12148bf80f4bSopenharmony_ci
12158bf80f4bSopenharmony_ciVertexInputDeclarationView ShaderManager::GetVertexInputDeclarationView(const RenderHandleReference& handle) const
12168bf80f4bSopenharmony_ci{
12178bf80f4bSopenharmony_ci    return GetVertexInputDeclarationView(handle.GetHandle());
12188bf80f4bSopenharmony_ci}
12198bf80f4bSopenharmony_ci
12208bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreateVertexInputDeclaration(const VertexInputDeclarationCreateInfo& createInfo)
12218bf80f4bSopenharmony_ci{
12228bf80f4bSopenharmony_ci    uint32_t arrayIndex = INVALID_SM_INDEX;
12238bf80f4bSopenharmony_ci    if (auto nameIter = shaderVid_.nameToIndex.find(createInfo.path); nameIter != shaderVid_.nameToIndex.end()) {
12248bf80f4bSopenharmony_ci        PLUGIN_ASSERT(nameIter->second < shaderVid_.rhr.size());
12258bf80f4bSopenharmony_ci        arrayIndex = static_cast<uint32_t>(nameIter->second);
12268bf80f4bSopenharmony_ci    }
12278bf80f4bSopenharmony_ci    if (arrayIndex < static_cast<uint32_t>(shaderVid_.data.size())) {
12288bf80f4bSopenharmony_ci        // inside core validation due to being very low info for common users
12298bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
12308bf80f4bSopenharmony_ci        PLUGIN_LOG_I("ShaderManager: re-creating vertex input declaration (name %s)", createInfo.path.data());
12318bf80f4bSopenharmony_ci#endif
12328bf80f4bSopenharmony_ci    } else { // new
12338bf80f4bSopenharmony_ci        arrayIndex = static_cast<uint32_t>(shaderVid_.data.size());
12348bf80f4bSopenharmony_ci        const RenderHandle handle =
12358bf80f4bSopenharmony_ci            RenderHandleUtil::CreateHandle(RenderHandleType::VERTEX_INPUT_DECLARATION, arrayIndex);
12368bf80f4bSopenharmony_ci        shaderVid_.rhr.push_back(
12378bf80f4bSopenharmony_ci            RenderHandleReference(handle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter())));
12388bf80f4bSopenharmony_ci        shaderVid_.data.push_back(VertexInputDeclarationData {});
12398bf80f4bSopenharmony_ci        // NOTE: only updated for new
12408bf80f4bSopenharmony_ci        if (!createInfo.path.empty()) {
12418bf80f4bSopenharmony_ci            shaderVid_.nameToIndex[createInfo.path] = arrayIndex;
12428bf80f4bSopenharmony_ci        }
12438bf80f4bSopenharmony_ci    }
12448bf80f4bSopenharmony_ci
12458bf80f4bSopenharmony_ci    if (arrayIndex < static_cast<uint32_t>(shaderVid_.data.size())) {
12468bf80f4bSopenharmony_ci        const VertexInputDeclarationView& vertexInputDeclarationView = createInfo.vertexInputDeclarationView;
12478bf80f4bSopenharmony_ci        VertexInputDeclarationData& ref = shaderVid_.data[arrayIndex];
12488bf80f4bSopenharmony_ci        ref.bindingDescriptionCount = (uint32_t)vertexInputDeclarationView.bindingDescriptions.size();
12498bf80f4bSopenharmony_ci        ref.attributeDescriptionCount = (uint32_t)vertexInputDeclarationView.attributeDescriptions.size();
12508bf80f4bSopenharmony_ci
12518bf80f4bSopenharmony_ci        PLUGIN_ASSERT(ref.bindingDescriptionCount <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
12528bf80f4bSopenharmony_ci        PLUGIN_ASSERT(ref.attributeDescriptionCount <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
12538bf80f4bSopenharmony_ci
12548bf80f4bSopenharmony_ci        for (uint32_t idx = 0; idx < ref.bindingDescriptionCount; ++idx) {
12558bf80f4bSopenharmony_ci            ref.bindingDescriptions[idx] = vertexInputDeclarationView.bindingDescriptions[idx];
12568bf80f4bSopenharmony_ci        }
12578bf80f4bSopenharmony_ci        for (uint32_t idx = 0; idx < ref.attributeDescriptionCount; ++idx) {
12588bf80f4bSopenharmony_ci            ref.attributeDescriptions[idx] = vertexInputDeclarationView.attributeDescriptions[idx];
12598bf80f4bSopenharmony_ci        }
12608bf80f4bSopenharmony_ci        return shaderVid_.rhr[arrayIndex];
12618bf80f4bSopenharmony_ci    } else {
12628bf80f4bSopenharmony_ci        return {};
12638bf80f4bSopenharmony_ci    }
12648bf80f4bSopenharmony_ci}
12658bf80f4bSopenharmony_ci
12668bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const
12678bf80f4bSopenharmony_ci{
12688bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
12698bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
12708bf80f4bSopenharmony_ci    if (type == RenderHandleType::SHADER_STATE_OBJECT) {
12718bf80f4bSopenharmony_ci        auto& mappings = shaderMappings_;
12728bf80f4bSopenharmony_ci        if (arrayIndex < mappings.clientData.size()) {
12738bf80f4bSopenharmony_ci            const uint32_t plIndex = mappings.clientData[arrayIndex].pipelineLayoutIndex;
12748bf80f4bSopenharmony_ci            if (plIndex < static_cast<uint32_t>(pl_.rhr.size())) {
12758bf80f4bSopenharmony_ci                PLUGIN_ASSERT(plIndex < static_cast<uint32_t>(pl_.rhr.size()));
12768bf80f4bSopenharmony_ci                return pl_.rhr[plIndex];
12778bf80f4bSopenharmony_ci            }
12788bf80f4bSopenharmony_ci        }
12798bf80f4bSopenharmony_ci    } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
12808bf80f4bSopenharmony_ci        auto& mappings = computeShaderMappings_;
12818bf80f4bSopenharmony_ci        if (arrayIndex < mappings.clientData.size()) {
12828bf80f4bSopenharmony_ci            const uint32_t plIndex = mappings.clientData[arrayIndex].pipelineLayoutIndex;
12838bf80f4bSopenharmony_ci            if (plIndex < static_cast<uint32_t>(pl_.rhr.size())) {
12848bf80f4bSopenharmony_ci                PLUGIN_ASSERT(plIndex < static_cast<uint32_t>(pl_.rhr.size()));
12858bf80f4bSopenharmony_ci                return pl_.rhr[plIndex];
12868bf80f4bSopenharmony_ci            }
12878bf80f4bSopenharmony_ci        }
12888bf80f4bSopenharmony_ci    }
12898bf80f4bSopenharmony_ci    return {};
12908bf80f4bSopenharmony_ci}
12918bf80f4bSopenharmony_ci
12928bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandleReference& handle) const
12938bf80f4bSopenharmony_ci{
12948bf80f4bSopenharmony_ci    return GetPipelineLayoutHandleByShaderHandle(handle.GetHandle());
12958bf80f4bSopenharmony_ci}
12968bf80f4bSopenharmony_ci
12978bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetPipelineLayoutHandle(const string_view path) const
12988bf80f4bSopenharmony_ci{
12998bf80f4bSopenharmony_ci    if (const auto iter = pl_.nameToIndex.find(path); iter != pl_.nameToIndex.cend()) {
13008bf80f4bSopenharmony_ci        const uint32_t index = iter->second;
13018bf80f4bSopenharmony_ci        PLUGIN_ASSERT(index < static_cast<uint32_t>(pl_.rhr.size()));
13028bf80f4bSopenharmony_ci        return pl_.rhr[index];
13038bf80f4bSopenharmony_ci    } else {
13048bf80f4bSopenharmony_ci        PLUGIN_LOG_W("ShaderManager: pipeline layout not found: %s", path.data());
13058bf80f4bSopenharmony_ci        return {};
13068bf80f4bSopenharmony_ci    }
13078bf80f4bSopenharmony_ci}
13088bf80f4bSopenharmony_ci
13098bf80f4bSopenharmony_ciPipelineLayout ShaderManager::GetPipelineLayout(const RenderHandle& handle) const
13108bf80f4bSopenharmony_ci{
13118bf80f4bSopenharmony_ci    return GetPipelineLayoutRef(handle);
13128bf80f4bSopenharmony_ci}
13138bf80f4bSopenharmony_ci
13148bf80f4bSopenharmony_ciPipelineLayout ShaderManager::GetPipelineLayout(const RenderHandleReference& handle) const
13158bf80f4bSopenharmony_ci{
13168bf80f4bSopenharmony_ci    return GetPipelineLayoutRef(handle.GetHandle());
13178bf80f4bSopenharmony_ci}
13188bf80f4bSopenharmony_ci
13198bf80f4bSopenharmony_ciconst PipelineLayout& ShaderManager::GetPipelineLayoutRef(const RenderHandle& handle) const
13208bf80f4bSopenharmony_ci{
13218bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
13228bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
13238bf80f4bSopenharmony_ci    if ((type == RenderHandleType::PIPELINE_LAYOUT) && (index < static_cast<uint32_t>(pl_.data.size()))) {
13248bf80f4bSopenharmony_ci        return pl_.data[index];
13258bf80f4bSopenharmony_ci    } else {
13268bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
13278bf80f4bSopenharmony_ci        if (RenderHandleUtil::IsValid(handle) && (type != RenderHandleType::PIPELINE_LAYOUT)) {
13288bf80f4bSopenharmony_ci            PLUGIN_LOG_W("RENDER_VALIDATION: invalid handle type given to GetPipelineLayout()");
13298bf80f4bSopenharmony_ci        }
13308bf80f4bSopenharmony_ci#endif
13318bf80f4bSopenharmony_ci        return defaultPipelineLayout_;
13328bf80f4bSopenharmony_ci    }
13338bf80f4bSopenharmony_ci}
13348bf80f4bSopenharmony_ci
13358bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const
13368bf80f4bSopenharmony_ci{
13378bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
13388bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
13398bf80f4bSopenharmony_ci    uint32_t plIndex = INVALID_SM_INDEX;
13408bf80f4bSopenharmony_ci    if (type == RenderHandleType::SHADER_STATE_OBJECT) {
13418bf80f4bSopenharmony_ci        if (arrayIndex < shaderMappings_.clientData.size()) {
13428bf80f4bSopenharmony_ci            plIndex = shaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
13438bf80f4bSopenharmony_ci        }
13448bf80f4bSopenharmony_ci    } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
13458bf80f4bSopenharmony_ci        if (arrayIndex < computeShaderMappings_.clientData.size()) {
13468bf80f4bSopenharmony_ci            plIndex = computeShaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
13478bf80f4bSopenharmony_ci        }
13488bf80f4bSopenharmony_ci    }
13498bf80f4bSopenharmony_ci
13508bf80f4bSopenharmony_ci    if (plIndex < pl_.data.size()) {
13518bf80f4bSopenharmony_ci        return pl_.rhr[plIndex];
13528bf80f4bSopenharmony_ci    } else {
13538bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
13548bf80f4bSopenharmony_ci        PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionPipelineLayoutHandle");
13558bf80f4bSopenharmony_ci#endif
13568bf80f4bSopenharmony_ci        return {};
13578bf80f4bSopenharmony_ci    }
13588bf80f4bSopenharmony_ci}
13598bf80f4bSopenharmony_ci
13608bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandleReference& handle) const
13618bf80f4bSopenharmony_ci{
13628bf80f4bSopenharmony_ci    return GetReflectionPipelineLayoutHandle(handle.GetHandle());
13638bf80f4bSopenharmony_ci}
13648bf80f4bSopenharmony_ci
13658bf80f4bSopenharmony_ciPipelineLayout ShaderManager::GetReflectionPipelineLayout(const RenderHandleReference& handle) const
13668bf80f4bSopenharmony_ci{
13678bf80f4bSopenharmony_ci    return GetReflectionPipelineLayoutRef(handle.GetHandle());
13688bf80f4bSopenharmony_ci}
13698bf80f4bSopenharmony_ci
13708bf80f4bSopenharmony_ciconst PipelineLayout& ShaderManager::GetReflectionPipelineLayoutRef(const RenderHandle& handle) const
13718bf80f4bSopenharmony_ci{
13728bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
13738bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
13748bf80f4bSopenharmony_ci    uint32_t plIndex = INVALID_SM_INDEX;
13758bf80f4bSopenharmony_ci    if (type == RenderHandleType::SHADER_STATE_OBJECT) {
13768bf80f4bSopenharmony_ci        if (arrayIndex < shaderMappings_.clientData.size()) {
13778bf80f4bSopenharmony_ci            plIndex = shaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
13788bf80f4bSopenharmony_ci        }
13798bf80f4bSopenharmony_ci    } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
13808bf80f4bSopenharmony_ci        if (arrayIndex < computeShaderMappings_.clientData.size()) {
13818bf80f4bSopenharmony_ci            plIndex = computeShaderMappings_.clientData[arrayIndex].reflectionPipelineLayoutIndex;
13828bf80f4bSopenharmony_ci        }
13838bf80f4bSopenharmony_ci    }
13848bf80f4bSopenharmony_ci
13858bf80f4bSopenharmony_ci    if (plIndex < pl_.data.size()) {
13868bf80f4bSopenharmony_ci        return pl_.data[plIndex];
13878bf80f4bSopenharmony_ci    } else {
13888bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
13898bf80f4bSopenharmony_ci        PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionPipelineLayout");
13908bf80f4bSopenharmony_ci#endif
13918bf80f4bSopenharmony_ci        return defaultPipelineLayout_;
13928bf80f4bSopenharmony_ci    }
13938bf80f4bSopenharmony_ci}
13948bf80f4bSopenharmony_ci
13958bf80f4bSopenharmony_ciShaderSpecializationConstantView ShaderManager::GetReflectionSpecialization(const RenderHandle& handle) const
13968bf80f4bSopenharmony_ci{
13978bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
13988bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
13998bf80f4bSopenharmony_ci    if (type == RenderHandleType::SHADER_STATE_OBJECT) {
14008bf80f4bSopenharmony_ci        // NOTE: at the moment there might not be availability yet, will be FIXED
14018bf80f4bSopenharmony_ci        if (arrayIndex < shaders_.size()) {
14028bf80f4bSopenharmony_ci            if (shaders_[arrayIndex].gsp) {
14038bf80f4bSopenharmony_ci                return shaders_[arrayIndex].gsp->GetReflection().shaderSpecializationConstantView;
14048bf80f4bSopenharmony_ci            }
14058bf80f4bSopenharmony_ci        }
14068bf80f4bSopenharmony_ci    } else if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
14078bf80f4bSopenharmony_ci        // NOTE: at the moment there might not be availability yet, will be FIXED
14088bf80f4bSopenharmony_ci        if (arrayIndex < computeShaders_.size()) {
14098bf80f4bSopenharmony_ci            if (computeShaders_[arrayIndex].gsp) {
14108bf80f4bSopenharmony_ci                return computeShaders_[arrayIndex].gsp->GetReflection().shaderSpecializationConstantView;
14118bf80f4bSopenharmony_ci            }
14128bf80f4bSopenharmony_ci        }
14138bf80f4bSopenharmony_ci    }
14148bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
14158bf80f4bSopenharmony_ci    PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionSpecialization");
14168bf80f4bSopenharmony_ci#endif
14178bf80f4bSopenharmony_ci    return defaultSSCV_;
14188bf80f4bSopenharmony_ci}
14198bf80f4bSopenharmony_ci
14208bf80f4bSopenharmony_ciShaderSpecializationConstantView ShaderManager::GetReflectionSpecialization(const RenderHandleReference& handle) const
14218bf80f4bSopenharmony_ci{
14228bf80f4bSopenharmony_ci    return GetReflectionSpecialization(handle.GetHandle());
14238bf80f4bSopenharmony_ci}
14248bf80f4bSopenharmony_ci
14258bf80f4bSopenharmony_ciVertexInputDeclarationView ShaderManager::GetReflectionVertexInputDeclaration(const RenderHandle& handle) const
14268bf80f4bSopenharmony_ci{
14278bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
14288bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
14298bf80f4bSopenharmony_ci    if (type == RenderHandleType::SHADER_STATE_OBJECT) {
14308bf80f4bSopenharmony_ci        // NOTE: at the moment there might not be availability yet, will be FIXED
14318bf80f4bSopenharmony_ci        if (arrayIndex < shaders_.size()) {
14328bf80f4bSopenharmony_ci            if (shaders_[arrayIndex].gsp) {
14338bf80f4bSopenharmony_ci                return shaders_[arrayIndex].gsp->GetReflection().vertexInputDeclarationView;
14348bf80f4bSopenharmony_ci            }
14358bf80f4bSopenharmony_ci        }
14368bf80f4bSopenharmony_ci    }
14378bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
14388bf80f4bSopenharmony_ci    PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionVertexInputDeclaration");
14398bf80f4bSopenharmony_ci#endif
14408bf80f4bSopenharmony_ci    return defaultVIDV_;
14418bf80f4bSopenharmony_ci}
14428bf80f4bSopenharmony_ci
14438bf80f4bSopenharmony_ciVertexInputDeclarationView ShaderManager::GetReflectionVertexInputDeclaration(const RenderHandleReference& handle) const
14448bf80f4bSopenharmony_ci{
14458bf80f4bSopenharmony_ci    return GetReflectionVertexInputDeclaration(handle.GetHandle());
14468bf80f4bSopenharmony_ci}
14478bf80f4bSopenharmony_ci
14488bf80f4bSopenharmony_ciShaderThreadGroup ShaderManager::GetReflectionThreadGroupSize(const RenderHandle& handle) const
14498bf80f4bSopenharmony_ci{
14508bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
14518bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
14528bf80f4bSopenharmony_ci    if (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
14538bf80f4bSopenharmony_ci        // NOTE: at the moment there might not be availability yet, will be FIXED
14548bf80f4bSopenharmony_ci        if (arrayIndex < computeShaders_.size()) {
14558bf80f4bSopenharmony_ci            if (computeShaders_[arrayIndex].gsp) {
14568bf80f4bSopenharmony_ci                const auto& refl = computeShaders_[arrayIndex].gsp->GetReflection();
14578bf80f4bSopenharmony_ci                return { refl.threadGroupSizeX, refl.threadGroupSizeY, refl.threadGroupSizeZ };
14588bf80f4bSopenharmony_ci            }
14598bf80f4bSopenharmony_ci        }
14608bf80f4bSopenharmony_ci    }
14618bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
14628bf80f4bSopenharmony_ci    PLUGIN_LOG_W("RENDER_VALIDATION: ShaderManager, invalid shader handle for GetReflectionThreadGroupSize");
14638bf80f4bSopenharmony_ci#endif
14648bf80f4bSopenharmony_ci    return defaultSTG_;
14658bf80f4bSopenharmony_ci}
14668bf80f4bSopenharmony_ci
14678bf80f4bSopenharmony_ciShaderThreadGroup ShaderManager::GetReflectionThreadGroupSize(const RenderHandleReference& handle) const
14688bf80f4bSopenharmony_ci{
14698bf80f4bSopenharmony_ci    return GetReflectionThreadGroupSize(handle.GetHandle());
14708bf80f4bSopenharmony_ci}
14718bf80f4bSopenharmony_ci
14728bf80f4bSopenharmony_ciRenderHandleReference ShaderManager::CreatePipelineLayout(const PipelineLayoutCreateInfo& createInfo)
14738bf80f4bSopenharmony_ci{
14748bf80f4bSopenharmony_ci    uint32_t arrayIndex = INVALID_SM_INDEX;
14758bf80f4bSopenharmony_ci    if (auto nameIter = pl_.nameToIndex.find(createInfo.path); nameIter != pl_.nameToIndex.end()) {
14768bf80f4bSopenharmony_ci        PLUGIN_ASSERT(nameIter->second < pl_.rhr.size());
14778bf80f4bSopenharmony_ci        arrayIndex = static_cast<uint32_t>(nameIter->second);
14788bf80f4bSopenharmony_ci    }
14798bf80f4bSopenharmony_ci
14808bf80f4bSopenharmony_ci    if (arrayIndex < static_cast<uint32_t>(pl_.data.size())) { // replace
14818bf80f4bSopenharmony_ci        // inside core validation due to being very low info for common users
14828bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
14838bf80f4bSopenharmony_ci        PLUGIN_LOG_I("ShaderManager: re-creating pipeline layout (name %s)", createInfo.path.data());
14848bf80f4bSopenharmony_ci#endif
14858bf80f4bSopenharmony_ci    } else { // new
14868bf80f4bSopenharmony_ci        arrayIndex = static_cast<uint32_t>(pl_.data.size());
14878bf80f4bSopenharmony_ci        pl_.data.push_back(PipelineLayout {});
14888bf80f4bSopenharmony_ci        // NOTE: only updated for new (should check with re-creation)
14898bf80f4bSopenharmony_ci        if (!createInfo.path.empty()) {
14908bf80f4bSopenharmony_ci            pl_.nameToIndex[createInfo.path] = arrayIndex;
14918bf80f4bSopenharmony_ci        }
14928bf80f4bSopenharmony_ci        pl_.rhr.push_back(RenderHandleReference {});
14938bf80f4bSopenharmony_ci    }
14948bf80f4bSopenharmony_ci
14958bf80f4bSopenharmony_ci    if (arrayIndex < static_cast<uint32_t>(pl_.data.size())) {
14968bf80f4bSopenharmony_ci        const PipelineLayout& pipelineLayout = createInfo.pipelineLayout;
14978bf80f4bSopenharmony_ci        PipelineLayout& ref = pl_.data[arrayIndex];
14988bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
14998bf80f4bSopenharmony_ci        if (pipelineLayout.descriptorSetCount > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT ||
15008bf80f4bSopenharmony_ci            pipelineLayout.pushConstant.byteSize > PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE) {
15018bf80f4bSopenharmony_ci            PLUGIN_LOG_W(
15028bf80f4bSopenharmony_ci                "Invalid pipeline layout sizes clamped (name:%s). Set count %u <= %u, push constant size %u <= %u",
15038bf80f4bSopenharmony_ci                createInfo.path.data(), ref.descriptorSetCount, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT,
15048bf80f4bSopenharmony_ci                pipelineLayout.pushConstant.byteSize, PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE);
15058bf80f4bSopenharmony_ci        }
15068bf80f4bSopenharmony_ci#endif
15078bf80f4bSopenharmony_ci        ref.pushConstant = pipelineLayout.pushConstant;
15088bf80f4bSopenharmony_ci        ref.descriptorSetCount =
15098bf80f4bSopenharmony_ci            Math::min(PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT, pipelineLayout.descriptorSetCount);
15108bf80f4bSopenharmony_ci        ref.pushConstant.byteSize =
15118bf80f4bSopenharmony_ci            Math::min(PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE, pipelineLayout.pushConstant.byteSize);
15128bf80f4bSopenharmony_ci        uint32_t descriptorSetBitmask = 0;
15138bf80f4bSopenharmony_ci        // can be user generated pipeline layout (i.e. set index might be different than index)
15148bf80f4bSopenharmony_ci        for (uint32_t idx = 0; idx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT; ++idx) {
15158bf80f4bSopenharmony_ci            const uint32_t setIdx = pipelineLayout.descriptorSetLayouts[idx].set;
15168bf80f4bSopenharmony_ci            if (setIdx < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
15178bf80f4bSopenharmony_ci                ref.descriptorSetLayouts[setIdx] = pipelineLayout.descriptorSetLayouts[setIdx];
15188bf80f4bSopenharmony_ci                descriptorSetBitmask |= (1 << setIdx);
15198bf80f4bSopenharmony_ci            }
15208bf80f4bSopenharmony_ci        }
15218bf80f4bSopenharmony_ci
15228bf80f4bSopenharmony_ci        const RenderHandle handle =
15238bf80f4bSopenharmony_ci            RenderHandleUtil::CreateHandle(RenderHandleType::PIPELINE_LAYOUT, arrayIndex, 0, descriptorSetBitmask);
15248bf80f4bSopenharmony_ci        pl_.rhr[arrayIndex] = RenderHandleReference(handle, IRenderReferenceCounter::Ptr(new ShaderReferenceCounter()));
15258bf80f4bSopenharmony_ci        return pl_.rhr[arrayIndex];
15268bf80f4bSopenharmony_ci    } else {
15278bf80f4bSopenharmony_ci        return {};
15288bf80f4bSopenharmony_ci    }
15298bf80f4bSopenharmony_ci}
15308bf80f4bSopenharmony_ci
15318bf80f4bSopenharmony_ciconst GpuComputeProgram* ShaderManager::GetGpuComputeProgram(const RenderHandle& handle) const
15328bf80f4bSopenharmony_ci{
15338bf80f4bSopenharmony_ci    if (!IsComputeShaderFunc(handle)) {
15348bf80f4bSopenharmony_ci        PLUGIN_LOG_E("ShaderManager: invalid compute shader handle");
15358bf80f4bSopenharmony_ci        return nullptr;
15368bf80f4bSopenharmony_ci    }
15378bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
15388bf80f4bSopenharmony_ci    if (index < static_cast<uint32_t>(computeShaders_.size())) {
15398bf80f4bSopenharmony_ci        return computeShaders_[index].gsp.get();
15408bf80f4bSopenharmony_ci    } else {
15418bf80f4bSopenharmony_ci        PLUGIN_LOG_E("ShaderManager: invalid compute shader handle");
15428bf80f4bSopenharmony_ci        return nullptr;
15438bf80f4bSopenharmony_ci    }
15448bf80f4bSopenharmony_ci}
15458bf80f4bSopenharmony_ci
15468bf80f4bSopenharmony_ciconst GpuShaderProgram* ShaderManager::GetGpuShaderProgram(const RenderHandle& handle) const
15478bf80f4bSopenharmony_ci{
15488bf80f4bSopenharmony_ci    if (!IsShaderFunc(handle)) {
15498bf80f4bSopenharmony_ci        PLUGIN_LOG_E("ShaderManager: invalid shader handle");
15508bf80f4bSopenharmony_ci        return nullptr;
15518bf80f4bSopenharmony_ci    }
15528bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
15538bf80f4bSopenharmony_ci    if (index < static_cast<uint32_t>(shaders_.size())) {
15548bf80f4bSopenharmony_ci        return shaders_[index].gsp.get();
15558bf80f4bSopenharmony_ci    } else {
15568bf80f4bSopenharmony_ci        PLUGIN_LOG_E("ShaderManager: invalid shader handle");
15578bf80f4bSopenharmony_ci        return nullptr;
15588bf80f4bSopenharmony_ci    }
15598bf80f4bSopenharmony_ci}
15608bf80f4bSopenharmony_ci
15618bf80f4bSopenharmony_ciuint32_t ShaderManager::CreateShaderModule(const string_view path, const ShaderModuleCreateInfo& createInfo)
15628bf80f4bSopenharmony_ci{
15638bf80f4bSopenharmony_ci    auto& nameToIdx = shaderModules_.nameToIndex;
15648bf80f4bSopenharmony_ci    auto& modules = shaderModules_.shaderModules;
15658bf80f4bSopenharmony_ci    if (auto iter = nameToIdx.find(path); iter != nameToIdx.end()) {
15668bf80f4bSopenharmony_ci        PLUGIN_ASSERT(iter->second < modules.size());
15678bf80f4bSopenharmony_ci        // inside core validation due to being very low info for common users
15688bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
15698bf80f4bSopenharmony_ci        PLUGIN_LOG_I("ShaderManager: re-creating shader module %s", path.data());
15708bf80f4bSopenharmony_ci#endif
15718bf80f4bSopenharmony_ci        // check that we don't push the same indices multiple times
15728bf80f4bSopenharmony_ci        bool found = false;
15738bf80f4bSopenharmony_ci        for (const auto& ref : pendingAllocations_.recreatedShaderModuleIndices) {
15748bf80f4bSopenharmony_ci            if (ref == iter->second) {
15758bf80f4bSopenharmony_ci                found = true;
15768bf80f4bSopenharmony_ci                break;
15778bf80f4bSopenharmony_ci            }
15788bf80f4bSopenharmony_ci        }
15798bf80f4bSopenharmony_ci        if (!found) {
15808bf80f4bSopenharmony_ci            pendingAllocations_.recreatedShaderModuleIndices.push_back(iter->second);
15818bf80f4bSopenharmony_ci        }
15828bf80f4bSopenharmony_ci        deferredDestructions_.shaderModules.push_back({ device_.GetFrameCount(), move(modules[iter->second]) });
15838bf80f4bSopenharmony_ci        modules[iter->second] = device_.CreateShaderModule(createInfo);
15848bf80f4bSopenharmony_ci        return iter->second;
15858bf80f4bSopenharmony_ci    } else {
15868bf80f4bSopenharmony_ci        const uint32_t idx = static_cast<uint32_t>(modules.size());
15878bf80f4bSopenharmony_ci        if (!path.empty()) {
15888bf80f4bSopenharmony_ci            nameToIdx[path] = idx;
15898bf80f4bSopenharmony_ci        }
15908bf80f4bSopenharmony_ci        modules.push_back(device_.CreateShaderModule(createInfo));
15918bf80f4bSopenharmony_ci        return idx;
15928bf80f4bSopenharmony_ci    }
15938bf80f4bSopenharmony_ci}
15948bf80f4bSopenharmony_ci
15958bf80f4bSopenharmony_ciShaderModule* ShaderManager::GetShaderModule(const uint32_t index) const
15968bf80f4bSopenharmony_ci{
15978bf80f4bSopenharmony_ci    const auto& modules = shaderModules_.shaderModules;
15988bf80f4bSopenharmony_ci    if (index < modules.size()) {
15998bf80f4bSopenharmony_ci        return modules[index].get();
16008bf80f4bSopenharmony_ci    } else {
16018bf80f4bSopenharmony_ci        return nullptr;
16028bf80f4bSopenharmony_ci    }
16038bf80f4bSopenharmony_ci}
16048bf80f4bSopenharmony_ci
16058bf80f4bSopenharmony_ciuint32_t ShaderManager::GetShaderModuleIndex(const string_view path) const
16068bf80f4bSopenharmony_ci{
16078bf80f4bSopenharmony_ci    const auto& nameToIdx = shaderModules_.nameToIndex;
16088bf80f4bSopenharmony_ci    if (const auto iter = nameToIdx.find(path); iter != nameToIdx.cend()) {
16098bf80f4bSopenharmony_ci        PLUGIN_ASSERT(iter->second < shaderModules_.shaderModules.size());
16108bf80f4bSopenharmony_ci        return iter->second;
16118bf80f4bSopenharmony_ci    } else {
16128bf80f4bSopenharmony_ci        return INVALID_SM_INDEX;
16138bf80f4bSopenharmony_ci    }
16148bf80f4bSopenharmony_ci}
16158bf80f4bSopenharmony_ci
16168bf80f4bSopenharmony_cibool ShaderManager::IsComputeShader(const RenderHandleReference& handle) const
16178bf80f4bSopenharmony_ci{
16188bf80f4bSopenharmony_ci    return IsComputeShaderFunc(handle.GetHandle());
16198bf80f4bSopenharmony_ci}
16208bf80f4bSopenharmony_ci
16218bf80f4bSopenharmony_cibool ShaderManager::IsShader(const RenderHandleReference& handle) const
16228bf80f4bSopenharmony_ci{
16238bf80f4bSopenharmony_ci    return IsShaderFunc(handle.GetHandle());
16248bf80f4bSopenharmony_ci}
16258bf80f4bSopenharmony_ci
16268bf80f4bSopenharmony_civoid ShaderManager::LoadShaderFiles(const ShaderFilePathDesc& desc)
16278bf80f4bSopenharmony_ci{
16288bf80f4bSopenharmony_ci    if (shaderLoader_) {
16298bf80f4bSopenharmony_ci        shaderLoader_->Load(desc);
16308bf80f4bSopenharmony_ci    }
16318bf80f4bSopenharmony_ci}
16328bf80f4bSopenharmony_ci
16338bf80f4bSopenharmony_civoid ShaderManager::LoadShaderFile(const string_view uri)
16348bf80f4bSopenharmony_ci{
16358bf80f4bSopenharmony_ci    if (shaderLoader_ && (!uri.empty())) {
16368bf80f4bSopenharmony_ci        shaderLoader_->LoadFile(uri, false);
16378bf80f4bSopenharmony_ci    }
16388bf80f4bSopenharmony_ci}
16398bf80f4bSopenharmony_ci
16408bf80f4bSopenharmony_civoid ShaderManager::UnloadShaderFiles(const ShaderFilePathDesc& desc) {}
16418bf80f4bSopenharmony_ci
16428bf80f4bSopenharmony_civoid ShaderManager::ReloadShaderFile(const string_view uri)
16438bf80f4bSopenharmony_ci{
16448bf80f4bSopenharmony_ci    if (shaderLoader_ && (!uri.empty())) {
16458bf80f4bSopenharmony_ci        shaderLoader_->LoadFile(uri, true);
16468bf80f4bSopenharmony_ci        if (const auto iter = nameToClientHandle_.find(uri); iter != nameToClientHandle_.cend()) {
16478bf80f4bSopenharmony_ci            reloadedShaders_.push_back(iter->second);
16488bf80f4bSopenharmony_ci        }
16498bf80f4bSopenharmony_ci    }
16508bf80f4bSopenharmony_ci}
16518bf80f4bSopenharmony_ci
16528bf80f4bSopenharmony_cibool ShaderManager::HasReloadedShaderForBackend() const
16538bf80f4bSopenharmony_ci{
16548bf80f4bSopenharmony_ci    return !reloadedShadersForBackend_.empty();
16558bf80f4bSopenharmony_ci}
16568bf80f4bSopenharmony_ci
16578bf80f4bSopenharmony_ciBASE_NS::array_view<const RenderHandle> ShaderManager::GetReloadedShadersForBackend() const
16588bf80f4bSopenharmony_ci{
16598bf80f4bSopenharmony_ci    return reloadedShadersForBackend_;
16608bf80f4bSopenharmony_ci}
16618bf80f4bSopenharmony_ci
16628bf80f4bSopenharmony_ciconst BASE_NS::string_view ShaderManager::GetShaderFile(const RenderHandleReference& handle) const
16638bf80f4bSopenharmony_ci{
16648bf80f4bSopenharmony_ci    if (const auto iter = handleToShaderDataFile_.find(handle.GetHandle()); iter != handleToShaderDataFile_.cend()) {
16658bf80f4bSopenharmony_ci        return iter->second;
16668bf80f4bSopenharmony_ci    }
16678bf80f4bSopenharmony_ci    return {};
16688bf80f4bSopenharmony_ci}
16698bf80f4bSopenharmony_ci
16708bf80f4bSopenharmony_ciconst json::value* ShaderManager::GetMaterialMetadata(const RenderHandleReference& handle) const
16718bf80f4bSopenharmony_ci{
16728bf80f4bSopenharmony_ci    if (const auto iter = shaderToMetadata_.find(handle.GetHandle()); iter != shaderToMetadata_.end()) {
16738bf80f4bSopenharmony_ci        return &iter->second.json;
16748bf80f4bSopenharmony_ci    }
16758bf80f4bSopenharmony_ci    return nullptr;
16768bf80f4bSopenharmony_ci}
16778bf80f4bSopenharmony_ci
16788bf80f4bSopenharmony_civoid ShaderManager::DestroyShader(const RenderHandle handle)
16798bf80f4bSopenharmony_ci{
16808bf80f4bSopenharmony_ci    PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
16818bf80f4bSopenharmony_ci    PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
16828bf80f4bSopenharmony_ci
16838bf80f4bSopenharmony_ci    auto eraseIndexData = [](auto& mapStore, const RenderHandle handle) {
16848bf80f4bSopenharmony_ci        if (auto const pos = std::find_if(
16858bf80f4bSopenharmony_ci            mapStore.begin(), mapStore.end(), [handle](auto const& element) { return element.second == handle; });
16868bf80f4bSopenharmony_ci            pos != mapStore.end()) {
16878bf80f4bSopenharmony_ci            mapStore.erase(pos);
16888bf80f4bSopenharmony_ci        }
16898bf80f4bSopenharmony_ci    };
16908bf80f4bSopenharmony_ci
16918bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
16928bf80f4bSopenharmony_ci    if (IsComputeShaderFunc(handle)) {
16938bf80f4bSopenharmony_ci        auto& mappings = computeShaderMappings_;
16948bf80f4bSopenharmony_ci        if (index < static_cast<uint32_t>(mappings.clientData.size())) {
16958bf80f4bSopenharmony_ci            mappings.clientData[index] = {};
16968bf80f4bSopenharmony_ci            mappings.nameData[index] = {};
16978bf80f4bSopenharmony_ci            eraseIndexData(nameToClientHandle_, handle);
16988bf80f4bSopenharmony_ci            {
16998bf80f4bSopenharmony_ci                const auto lock = std::lock_guard(pendingMutex_);
17008bf80f4bSopenharmony_ci                pendingAllocations_.destroyHandles.push_back(handle);
17018bf80f4bSopenharmony_ci            }
17028bf80f4bSopenharmony_ci        }
17038bf80f4bSopenharmony_ci    } else if (IsShaderFunc(handle)) {
17048bf80f4bSopenharmony_ci        auto& mappings = shaderMappings_;
17058bf80f4bSopenharmony_ci        if (index < static_cast<uint32_t>(mappings.clientData.size())) {
17068bf80f4bSopenharmony_ci            mappings.clientData[index] = {};
17078bf80f4bSopenharmony_ci            mappings.nameData[index] = {};
17088bf80f4bSopenharmony_ci            eraseIndexData(nameToClientHandle_, handle);
17098bf80f4bSopenharmony_ci            {
17108bf80f4bSopenharmony_ci                const auto lock = std::lock_guard(pendingMutex_);
17118bf80f4bSopenharmony_ci                pendingAllocations_.destroyHandles.push_back(handle);
17128bf80f4bSopenharmony_ci            }
17138bf80f4bSopenharmony_ci        }
17148bf80f4bSopenharmony_ci    }
17158bf80f4bSopenharmony_ci}
17168bf80f4bSopenharmony_ci
17178bf80f4bSopenharmony_civoid ShaderManager::Destroy(const RenderHandleReference& handle)
17188bf80f4bSopenharmony_ci{
17198bf80f4bSopenharmony_ci    const RenderHandle rawHandle = handle.GetHandle();
17208bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
17218bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
17228bf80f4bSopenharmony_ci        (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
17238bf80f4bSopenharmony_ci        DestroyShader(rawHandle);
17248bf80f4bSopenharmony_ci    } else if (handleType == RenderHandleType::GRAPHICS_STATE) {
17258bf80f4bSopenharmony_ci        DestroyGraphicsState(rawHandle);
17268bf80f4bSopenharmony_ci    } else if (handleType == RenderHandleType::PIPELINE_LAYOUT) {
17278bf80f4bSopenharmony_ci        DestroyPipelineLayout(rawHandle);
17288bf80f4bSopenharmony_ci    } else if (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) {
17298bf80f4bSopenharmony_ci        DestroyVertexInputDeclaration(rawHandle);
17308bf80f4bSopenharmony_ci    }
17318bf80f4bSopenharmony_ci}
17328bf80f4bSopenharmony_ci
17338bf80f4bSopenharmony_civoid ShaderManager::DestroyGraphicsState(const RenderHandle handle)
17348bf80f4bSopenharmony_ci{
17358bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
17368bf80f4bSopenharmony_ci    if (index < static_cast<uint32_t>(graphicsStates_.rhr.size())) {
17378bf80f4bSopenharmony_ci        graphicsStates_.rhr[index] = {};
17388bf80f4bSopenharmony_ci        graphicsStates_.data[index] = {};
17398bf80f4bSopenharmony_ci        graphicsStates_.graphicsStates[index] = {};
17408bf80f4bSopenharmony_ci
17418bf80f4bSopenharmony_ci        auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
17428bf80f4bSopenharmony_ci            if (auto const pos = std::find_if(
17438bf80f4bSopenharmony_ci                mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
17448bf80f4bSopenharmony_ci                pos != mapStore.end()) {
17458bf80f4bSopenharmony_ci                mapStore.erase(pos);
17468bf80f4bSopenharmony_ci            }
17478bf80f4bSopenharmony_ci        };
17488bf80f4bSopenharmony_ci        eraseIndexData(graphicsStates_.nameToIndex, index);
17498bf80f4bSopenharmony_ci        eraseIndexData(graphicsStates_.hashToIndex, index);
17508bf80f4bSopenharmony_ci        // NOTE: shaderToStates needs to be added
17518bf80f4bSopenharmony_ci    }
17528bf80f4bSopenharmony_ci}
17538bf80f4bSopenharmony_ci
17548bf80f4bSopenharmony_civoid ShaderManager::DestroyPipelineLayout(const RenderHandle handle)
17558bf80f4bSopenharmony_ci{
17568bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
17578bf80f4bSopenharmony_ci    if (index < static_cast<uint32_t>(pl_.rhr.size())) {
17588bf80f4bSopenharmony_ci        pl_.rhr[index] = {};
17598bf80f4bSopenharmony_ci        pl_.data[index] = {};
17608bf80f4bSopenharmony_ci
17618bf80f4bSopenharmony_ci        auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
17628bf80f4bSopenharmony_ci            if (auto const pos = std::find_if(
17638bf80f4bSopenharmony_ci                mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
17648bf80f4bSopenharmony_ci                pos != mapStore.end()) {
17658bf80f4bSopenharmony_ci                mapStore.erase(pos);
17668bf80f4bSopenharmony_ci            }
17678bf80f4bSopenharmony_ci        };
17688bf80f4bSopenharmony_ci        eraseIndexData(pl_.nameToIndex, index);
17698bf80f4bSopenharmony_ci        eraseIndexData(pl_.computeShaderToIndex, index);
17708bf80f4bSopenharmony_ci        eraseIndexData(pl_.shaderToIndex, index);
17718bf80f4bSopenharmony_ci    }
17728bf80f4bSopenharmony_ci}
17738bf80f4bSopenharmony_ci
17748bf80f4bSopenharmony_civoid ShaderManager::DestroyVertexInputDeclaration(const RenderHandle handle)
17758bf80f4bSopenharmony_ci{
17768bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
17778bf80f4bSopenharmony_ci    if (index < static_cast<uint32_t>(shaderVid_.rhr.size())) {
17788bf80f4bSopenharmony_ci        shaderVid_.rhr[index] = {};
17798bf80f4bSopenharmony_ci        shaderVid_.data[index] = {};
17808bf80f4bSopenharmony_ci
17818bf80f4bSopenharmony_ci        auto eraseIndexData = [](auto& mapStore, const uint32_t index) {
17828bf80f4bSopenharmony_ci            if (auto const pos = std::find_if(
17838bf80f4bSopenharmony_ci                mapStore.begin(), mapStore.end(), [index](auto const& element) { return element.second == index; });
17848bf80f4bSopenharmony_ci                pos != mapStore.end()) {
17858bf80f4bSopenharmony_ci                mapStore.erase(pos);
17868bf80f4bSopenharmony_ci            }
17878bf80f4bSopenharmony_ci        };
17888bf80f4bSopenharmony_ci        eraseIndexData(shaderVid_.nameToIndex, index);
17898bf80f4bSopenharmony_ci        eraseIndexData(shaderVid_.shaderToIndex, index);
17908bf80f4bSopenharmony_ci    }
17918bf80f4bSopenharmony_ci}
17928bf80f4bSopenharmony_ci
17938bf80f4bSopenharmony_civector<RenderHandleReference> ShaderManager::GetShaders(
17948bf80f4bSopenharmony_ci    const RenderHandleReference& handle, const ShaderStageFlags shaderStageFlags) const
17958bf80f4bSopenharmony_ci{
17968bf80f4bSopenharmony_ci    vector<RenderHandleReference> shaders;
17978bf80f4bSopenharmony_ci    if ((shaderStageFlags &
17988bf80f4bSopenharmony_ci            (CORE_SHADER_STAGE_VERTEX_BIT | CORE_SHADER_STAGE_FRAGMENT_BIT | CORE_SHADER_STAGE_COMPUTE_BIT)) == 0) {
17998bf80f4bSopenharmony_ci        return shaders;
18008bf80f4bSopenharmony_ci    }
18018bf80f4bSopenharmony_ci    const RenderHandleType handleType = handle.GetHandleType();
18028bf80f4bSopenharmony_ci    const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(handle.GetHandle());
18038bf80f4bSopenharmony_ci    if (handleType == RenderHandleType::GRAPHICS_STATE) {
18048bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
18058bf80f4bSopenharmony_ci        PLUGIN_LOG_W("RENDER_VALIDATION: GetShaders with graphics state handle not supported");
18068bf80f4bSopenharmony_ci#endif
18078bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) ||
18088bf80f4bSopenharmony_ci               (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION)) {
18098bf80f4bSopenharmony_ci        if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT) {
18108bf80f4bSopenharmony_ci            for (const auto& ref : computeShaderMappings_.clientData) {
18118bf80f4bSopenharmony_ci                if (ref.pipelineLayoutIndex == handleIndex) {
18128bf80f4bSopenharmony_ci                    shaders.push_back(ref.rhr);
18138bf80f4bSopenharmony_ci                }
18148bf80f4bSopenharmony_ci            }
18158bf80f4bSopenharmony_ci        }
18168bf80f4bSopenharmony_ci        if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_ALL_GRAPHICS) {
18178bf80f4bSopenharmony_ci            for (const auto& ref : shaderMappings_.clientData) {
18188bf80f4bSopenharmony_ci                if (ref.vertexInputDeclarationIndex == handleIndex) {
18198bf80f4bSopenharmony_ci                    shaders.push_back(ref.rhr);
18208bf80f4bSopenharmony_ci                }
18218bf80f4bSopenharmony_ci            }
18228bf80f4bSopenharmony_ci        }
18238bf80f4bSopenharmony_ci    }
18248bf80f4bSopenharmony_ci    return shaders;
18258bf80f4bSopenharmony_ci}
18268bf80f4bSopenharmony_ci
18278bf80f4bSopenharmony_civector<RenderHandle> ShaderManager::GetShaders(
18288bf80f4bSopenharmony_ci    const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const
18298bf80f4bSopenharmony_ci{
18308bf80f4bSopenharmony_ci    vector<RenderHandle> shaders;
18318bf80f4bSopenharmony_ci    if ((shaderStageFlags &
18328bf80f4bSopenharmony_ci            (CORE_SHADER_STAGE_VERTEX_BIT | CORE_SHADER_STAGE_FRAGMENT_BIT | CORE_SHADER_STAGE_COMPUTE_BIT)) == 0) {
18338bf80f4bSopenharmony_ci        return shaders;
18348bf80f4bSopenharmony_ci    }
18358bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
18368bf80f4bSopenharmony_ci    const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(handle);
18378bf80f4bSopenharmony_ci    if (handleType == RenderHandleType::GRAPHICS_STATE) {
18388bf80f4bSopenharmony_ci#if (RENDER_VALIDATION_ENABLED == 1)
18398bf80f4bSopenharmony_ci        PLUGIN_LOG_W("RENDER_VALIDATION: GetShaders with graphics state handle not supported");
18408bf80f4bSopenharmony_ci#endif
18418bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) ||
18428bf80f4bSopenharmony_ci               (handleType == RenderHandleType::VERTEX_INPUT_DECLARATION)) {
18438bf80f4bSopenharmony_ci        if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT) {
18448bf80f4bSopenharmony_ci            for (const auto& ref : computeShaderMappings_.clientData) {
18458bf80f4bSopenharmony_ci                if (ref.pipelineLayoutIndex == handleIndex) {
18468bf80f4bSopenharmony_ci                    shaders.push_back(ref.rhr.GetHandle());
18478bf80f4bSopenharmony_ci                }
18488bf80f4bSopenharmony_ci            }
18498bf80f4bSopenharmony_ci        }
18508bf80f4bSopenharmony_ci        if (shaderStageFlags & ShaderStageFlagBits::CORE_SHADER_STAGE_ALL_GRAPHICS) {
18518bf80f4bSopenharmony_ci            for (const auto& ref : shaderMappings_.clientData) {
18528bf80f4bSopenharmony_ci                if (ref.vertexInputDeclarationIndex == handleIndex) {
18538bf80f4bSopenharmony_ci                    shaders.push_back(ref.rhr.GetHandle());
18548bf80f4bSopenharmony_ci                }
18558bf80f4bSopenharmony_ci            }
18568bf80f4bSopenharmony_ci        }
18578bf80f4bSopenharmony_ci    }
18588bf80f4bSopenharmony_ci    return shaders;
18598bf80f4bSopenharmony_ci}
18608bf80f4bSopenharmony_ci
18618bf80f4bSopenharmony_civector<RenderHandleReference> ShaderManager::GetShaders() const
18628bf80f4bSopenharmony_ci{
18638bf80f4bSopenharmony_ci    vector<RenderHandleReference> shaders;
18648bf80f4bSopenharmony_ci    shaders.reserve(computeShaderMappings_.clientData.size() + shaderMappings_.clientData.size());
18658bf80f4bSopenharmony_ci    for (const auto& ref : computeShaderMappings_.clientData) {
18668bf80f4bSopenharmony_ci        if (ref.rhr) {
18678bf80f4bSopenharmony_ci            shaders.push_back(ref.rhr);
18688bf80f4bSopenharmony_ci        }
18698bf80f4bSopenharmony_ci    }
18708bf80f4bSopenharmony_ci    for (const auto& ref : shaderMappings_.clientData) {
18718bf80f4bSopenharmony_ci        if (ref.rhr) {
18728bf80f4bSopenharmony_ci            shaders.push_back(ref.rhr);
18738bf80f4bSopenharmony_ci        }
18748bf80f4bSopenharmony_ci    }
18758bf80f4bSopenharmony_ci    return shaders;
18768bf80f4bSopenharmony_ci}
18778bf80f4bSopenharmony_ci
18788bf80f4bSopenharmony_civector<RenderHandleReference> ShaderManager::GetGraphicsStates() const
18798bf80f4bSopenharmony_ci{
18808bf80f4bSopenharmony_ci    vector<RenderHandleReference> states;
18818bf80f4bSopenharmony_ci    states.reserve(graphicsStates_.rhr.size());
18828bf80f4bSopenharmony_ci    for (const auto& ref : graphicsStates_.rhr) {
18838bf80f4bSopenharmony_ci        if (ref) {
18848bf80f4bSopenharmony_ci            states.push_back(ref);
18858bf80f4bSopenharmony_ci        }
18868bf80f4bSopenharmony_ci    }
18878bf80f4bSopenharmony_ci    return states;
18888bf80f4bSopenharmony_ci}
18898bf80f4bSopenharmony_ci
18908bf80f4bSopenharmony_civector<RenderHandleReference> ShaderManager::GetPipelineLayouts() const
18918bf80f4bSopenharmony_ci{
18928bf80f4bSopenharmony_ci    vector<RenderHandleReference> pls;
18938bf80f4bSopenharmony_ci    pls.reserve(pl_.rhr.size());
18948bf80f4bSopenharmony_ci    for (const auto& ref : pl_.rhr) {
18958bf80f4bSopenharmony_ci        if (ref) {
18968bf80f4bSopenharmony_ci            pls.push_back(ref);
18978bf80f4bSopenharmony_ci        }
18988bf80f4bSopenharmony_ci    }
18998bf80f4bSopenharmony_ci    return pls;
19008bf80f4bSopenharmony_ci}
19018bf80f4bSopenharmony_ci
19028bf80f4bSopenharmony_civector<RenderHandleReference> ShaderManager::GetVertexInputDeclarations() const
19038bf80f4bSopenharmony_ci{
19048bf80f4bSopenharmony_ci    vector<RenderHandleReference> vids;
19058bf80f4bSopenharmony_ci    vids.reserve(shaderVid_.rhr.size());
19068bf80f4bSopenharmony_ci    for (const auto& ref : shaderVid_.rhr) {
19078bf80f4bSopenharmony_ci        if (ref) {
19088bf80f4bSopenharmony_ci            vids.push_back(ref);
19098bf80f4bSopenharmony_ci        }
19108bf80f4bSopenharmony_ci    }
19118bf80f4bSopenharmony_ci    return vids;
19128bf80f4bSopenharmony_ci}
19138bf80f4bSopenharmony_ci
19148bf80f4bSopenharmony_ciIShaderManager::IdDesc ShaderManager::GetShaderIdDesc(const RenderHandle handle) const
19158bf80f4bSopenharmony_ci{
19168bf80f4bSopenharmony_ci    PLUGIN_ASSERT(computeShaderMappings_.clientData.size() == computeShaderMappings_.nameData.size());
19178bf80f4bSopenharmony_ci    PLUGIN_ASSERT(shaderMappings_.clientData.size() == shaderMappings_.nameData.size());
19188bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
19198bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
19208bf80f4bSopenharmony_ci    IdDesc desc;
19218bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
19228bf80f4bSopenharmony_ci        (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
19238bf80f4bSopenharmony_ci        const auto& cdRef = computeShaderMappings_.clientData[index];
19248bf80f4bSopenharmony_ci        const auto& nameRef = computeShaderMappings_.nameData[index];
19258bf80f4bSopenharmony_ci        desc.frameIndex = cdRef.frameIndex;
19268bf80f4bSopenharmony_ci        desc.renderSlot = GetRenderSlotName(cdRef.renderSlotId);
19278bf80f4bSopenharmony_ci        desc.category = GetCategoryName(cdRef.categoryId);
19288bf80f4bSopenharmony_ci        desc.displayName = nameRef.displayName;
19298bf80f4bSopenharmony_ci        desc.path = nameRef.path;
19308bf80f4bSopenharmony_ci        desc.variant = nameRef.variantName;
19318bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
19328bf80f4bSopenharmony_ci               (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
19338bf80f4bSopenharmony_ci        const auto& cdRef = shaderMappings_.clientData[index];
19348bf80f4bSopenharmony_ci        const auto& nameRef = shaderMappings_.nameData[index];
19358bf80f4bSopenharmony_ci        desc.frameIndex = cdRef.frameIndex;
19368bf80f4bSopenharmony_ci        desc.renderSlot = GetRenderSlotName(cdRef.renderSlotId);
19378bf80f4bSopenharmony_ci        desc.category = GetCategoryName(cdRef.categoryId);
19388bf80f4bSopenharmony_ci        desc.displayName = nameRef.displayName;
19398bf80f4bSopenharmony_ci        desc.path = nameRef.path;
19408bf80f4bSopenharmony_ci        desc.variant = nameRef.variantName;
19418bf80f4bSopenharmony_ci    }
19428bf80f4bSopenharmony_ci    return desc;
19438bf80f4bSopenharmony_ci}
19448bf80f4bSopenharmony_ci
19458bf80f4bSopenharmony_ciuint64_t ShaderManager::GetShaderFrameIndex(const RenderHandle handle) const
19468bf80f4bSopenharmony_ci{
19478bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(handle);
19488bf80f4bSopenharmony_ci    const uint32_t index = RenderHandleUtil::GetIndexPart(handle);
19498bf80f4bSopenharmony_ci    uint64_t frameIndex = 0;
19508bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) &&
19518bf80f4bSopenharmony_ci        (index < static_cast<uint32_t>(computeShaderMappings_.clientData.size()))) {
19528bf80f4bSopenharmony_ci        frameIndex = computeShaderMappings_.clientData[index].frameIndex;
19538bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::SHADER_STATE_OBJECT) &&
19548bf80f4bSopenharmony_ci               (index < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
19558bf80f4bSopenharmony_ci        frameIndex = shaderMappings_.clientData[index].frameIndex;
19568bf80f4bSopenharmony_ci    }
19578bf80f4bSopenharmony_ci    return frameIndex;
19588bf80f4bSopenharmony_ci}
19598bf80f4bSopenharmony_ci
19608bf80f4bSopenharmony_ciIShaderManager::IdDesc ShaderManager::GetIdDesc(const RenderHandleReference& handle) const
19618bf80f4bSopenharmony_ci{
19628bf80f4bSopenharmony_ci    auto GetIdDesc = [](const auto& nameToIndex, const auto handleIndex) {
19638bf80f4bSopenharmony_ci        IdDesc desc;
19648bf80f4bSopenharmony_ci        for (const auto& ref : nameToIndex) {
19658bf80f4bSopenharmony_ci            if (ref.second == handleIndex) {
19668bf80f4bSopenharmony_ci                desc.path = ref.first;
19678bf80f4bSopenharmony_ci            }
19688bf80f4bSopenharmony_ci        }
19698bf80f4bSopenharmony_ci        return desc;
19708bf80f4bSopenharmony_ci    };
19718bf80f4bSopenharmony_ci    const RenderHandle rawHandle = handle.GetHandle();
19728bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
19738bf80f4bSopenharmony_ci    const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(rawHandle);
19748bf80f4bSopenharmony_ci    IdDesc desc;
19758bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
19768bf80f4bSopenharmony_ci        (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
19778bf80f4bSopenharmony_ci        desc = GetShaderIdDesc(rawHandle);
19788bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::GRAPHICS_STATE) && (handleIndex < graphicsStates_.rhr.size())) {
19798bf80f4bSopenharmony_ci        desc = GetIdDesc(graphicsStates_.nameToIndex, handleIndex);
19808bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) && (handleIndex < pl_.rhr.size())) {
19818bf80f4bSopenharmony_ci        desc = GetIdDesc(pl_.nameToIndex, handleIndex);
19828bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) && (handleIndex < shaderVid_.rhr.size())) {
19838bf80f4bSopenharmony_ci        desc = GetIdDesc(shaderVid_.nameToIndex, handleIndex);
19848bf80f4bSopenharmony_ci    }
19858bf80f4bSopenharmony_ci    return desc;
19868bf80f4bSopenharmony_ci}
19878bf80f4bSopenharmony_ci
19888bf80f4bSopenharmony_ciuint64_t ShaderManager::GetFrameIndex(const RenderHandleReference& handle) const
19898bf80f4bSopenharmony_ci{
19908bf80f4bSopenharmony_ci    const RenderHandle rawHandle = handle.GetHandle();
19918bf80f4bSopenharmony_ci    const RenderHandleType handleType = RenderHandleUtil::GetHandleType(rawHandle);
19928bf80f4bSopenharmony_ci    const uint32_t handleIndex = RenderHandleUtil::GetIndexPart(rawHandle);
19938bf80f4bSopenharmony_ci    uint64_t frameIndex = 0;
19948bf80f4bSopenharmony_ci    if ((handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) ||
19958bf80f4bSopenharmony_ci        (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
19968bf80f4bSopenharmony_ci        frameIndex = GetShaderFrameIndex(rawHandle);
19978bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::GRAPHICS_STATE) && (handleIndex < graphicsStates_.rhr.size())) {
19988bf80f4bSopenharmony_ci        frameIndex = 0;
19998bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::PIPELINE_LAYOUT) && (handleIndex < pl_.rhr.size())) {
20008bf80f4bSopenharmony_ci        frameIndex = 0;
20018bf80f4bSopenharmony_ci    } else if ((handleType == RenderHandleType::VERTEX_INPUT_DECLARATION) && (handleIndex < shaderVid_.rhr.size())) {
20028bf80f4bSopenharmony_ci        frameIndex = 0;
20038bf80f4bSopenharmony_ci    }
20048bf80f4bSopenharmony_ci    return frameIndex;
20058bf80f4bSopenharmony_ci}
20068bf80f4bSopenharmony_ci
20078bf80f4bSopenharmony_ciIShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(
20088bf80f4bSopenharmony_ci    const RenderHandleReference& handle, const PipelineLayout& pipelineLayout) const
20098bf80f4bSopenharmony_ci{
20108bf80f4bSopenharmony_ci    const RenderHandleType type = handle.GetHandleType();
20118bf80f4bSopenharmony_ci    if (handle &&
20128bf80f4bSopenharmony_ci        ((type == RenderHandleType::SHADER_STATE_OBJECT) || (type == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT))) {
20138bf80f4bSopenharmony_ci        return IShaderPipelineBinder::Ptr { new ShaderPipelineBinder((IShaderManager&)*this, handle, pipelineLayout) };
20148bf80f4bSopenharmony_ci    }
20158bf80f4bSopenharmony_ci    return nullptr;
20168bf80f4bSopenharmony_ci}
20178bf80f4bSopenharmony_ci
20188bf80f4bSopenharmony_ciIShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(
20198bf80f4bSopenharmony_ci    const RenderHandleReference& handle, const RenderHandleReference& plHandle) const
20208bf80f4bSopenharmony_ci{
20218bf80f4bSopenharmony_ci    RenderHandleReference finalPlHandle = plHandle;
20228bf80f4bSopenharmony_ci    if (!finalPlHandle) {
20238bf80f4bSopenharmony_ci        finalPlHandle = GetPipelineLayoutHandleByShaderHandle(handle.GetHandle());
20248bf80f4bSopenharmony_ci        if (!finalPlHandle) {
20258bf80f4bSopenharmony_ci            finalPlHandle = GetReflectionPipelineLayoutHandle(handle.GetHandle());
20268bf80f4bSopenharmony_ci        }
20278bf80f4bSopenharmony_ci    }
20288bf80f4bSopenharmony_ci    return CreateShaderPipelineBinder(handle, GetPipelineLayout(finalPlHandle));
20298bf80f4bSopenharmony_ci}
20308bf80f4bSopenharmony_ci
20318bf80f4bSopenharmony_ciIShaderPipelineBinder::Ptr ShaderManager::CreateShaderPipelineBinder(const RenderHandleReference& handle) const
20328bf80f4bSopenharmony_ci{
20338bf80f4bSopenharmony_ci    return CreateShaderPipelineBinder(handle, RenderHandleReference {});
20348bf80f4bSopenharmony_ci}
20358bf80f4bSopenharmony_ci
20368bf80f4bSopenharmony_ciShaderManager::CompatibilityFlags ShaderManager::GetCompatibilityFlags(
20378bf80f4bSopenharmony_ci    const RenderHandle& lhs, const RenderHandle& rhs) const
20388bf80f4bSopenharmony_ci{
20398bf80f4bSopenharmony_ci    const RenderHandleType lType = RenderHandleUtil::GetHandleType(lhs);
20408bf80f4bSopenharmony_ci    const RenderHandleType rType = RenderHandleUtil::GetHandleType(rhs);
20418bf80f4bSopenharmony_ci    CompatibilityFlags flags = 0;
20428bf80f4bSopenharmony_ci    // NOTE: only same types supported at the moment
20438bf80f4bSopenharmony_ci    if (lType == rType) {
20448bf80f4bSopenharmony_ci        if (lType == RenderHandleType::PIPELINE_LAYOUT) {
20458bf80f4bSopenharmony_ci            const PipelineLayout lpl = GetPipelineLayout(lhs);
20468bf80f4bSopenharmony_ci            const PipelineLayout rpl = GetPipelineLayout(rhs);
20478bf80f4bSopenharmony_ci            flags = GetPipelineLayoutCompatibilityFlags(lpl, rpl);
20488bf80f4bSopenharmony_ci        } else if ((lType == RenderHandleType::SHADER_STATE_OBJECT) ||
20498bf80f4bSopenharmony_ci                   (lType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT)) {
20508bf80f4bSopenharmony_ci            // first check that given pipeline layout is valid to own reflection
20518bf80f4bSopenharmony_ci            const RenderHandle shaderPlHandle = GetPipelineLayoutHandleByShaderHandle(rhs).GetHandle();
20528bf80f4bSopenharmony_ci            if (RenderHandleUtil::IsValid(shaderPlHandle)) {
20538bf80f4bSopenharmony_ci                const PipelineLayout shaderPl = GetPipelineLayout(shaderPlHandle);
20548bf80f4bSopenharmony_ci                const PipelineLayout rpl = GetReflectionPipelineLayoutRef(rhs);
20558bf80f4bSopenharmony_ci                if (rpl.descriptorSetCount > 0) {
20568bf80f4bSopenharmony_ci                    flags = GetPipelineLayoutCompatibilityFlags(rpl, shaderPl);
20578bf80f4bSopenharmony_ci                }
20588bf80f4bSopenharmony_ci            } else {
20598bf80f4bSopenharmony_ci                // some shaders do not specify actual pipeline layout, only shader reflection pipeline layout
20608bf80f4bSopenharmony_ci                flags = 1u;
20618bf80f4bSopenharmony_ci            }
20628bf80f4bSopenharmony_ci            // then, compare to lhs with rhs reflection
20638bf80f4bSopenharmony_ci            if (flags != 0) {
20648bf80f4bSopenharmony_ci                const RenderHandle lShaderPlHandle = GetPipelineLayoutHandleByShaderHandle(lhs).GetHandle();
20658bf80f4bSopenharmony_ci                const PipelineLayout lpl = RenderHandleUtil::IsValid(lShaderPlHandle)
20668bf80f4bSopenharmony_ci                                               ? GetPipelineLayout(lShaderPlHandle)
20678bf80f4bSopenharmony_ci                                               : GetReflectionPipelineLayoutRef(lhs);
20688bf80f4bSopenharmony_ci                flags = GetPipelineLayoutCompatibilityFlags(lpl, GetReflectionPipelineLayoutRef(rhs));
20698bf80f4bSopenharmony_ci            }
20708bf80f4bSopenharmony_ci        }
20718bf80f4bSopenharmony_ci    }
20728bf80f4bSopenharmony_ci    return flags;
20738bf80f4bSopenharmony_ci}
20748bf80f4bSopenharmony_ci
20758bf80f4bSopenharmony_ciShaderManager::CompatibilityFlags ShaderManager::GetCompatibilityFlags(
20768bf80f4bSopenharmony_ci    const RenderHandleReference& lhs, const RenderHandleReference& rhs) const
20778bf80f4bSopenharmony_ci{
20788bf80f4bSopenharmony_ci    if (lhs && rhs) {
20798bf80f4bSopenharmony_ci        return GetCompatibilityFlags(lhs.GetHandle(), rhs.GetHandle());
20808bf80f4bSopenharmony_ci    } else {
20818bf80f4bSopenharmony_ci        return CompatibilityFlags { 0 };
20828bf80f4bSopenharmony_ci    }
20838bf80f4bSopenharmony_ci}
20848bf80f4bSopenharmony_ci
20858bf80f4bSopenharmony_ciGraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const RenderHandle& handle) const
20868bf80f4bSopenharmony_ci{
20878bf80f4bSopenharmony_ci    if (!RenderHandleUtil::IsValid(handle)) {
20888bf80f4bSopenharmony_ci        return 0U; // early out
20898bf80f4bSopenharmony_ci    }
20908bf80f4bSopenharmony_ci
20918bf80f4bSopenharmony_ci    const RenderHandleType type = RenderHandleUtil::GetHandleType(handle);
20928bf80f4bSopenharmony_ci    const uint32_t arrayIndex = RenderHandleUtil::GetIndexPart(handle);
20938bf80f4bSopenharmony_ci    GraphicsStateFlags flags { 0u };
20948bf80f4bSopenharmony_ci
20958bf80f4bSopenharmony_ci    uint32_t graphicsStateIndex = ~0u;
20968bf80f4bSopenharmony_ci    if (type == RenderHandleType::GRAPHICS_STATE) {
20978bf80f4bSopenharmony_ci        graphicsStateIndex = arrayIndex;
20988bf80f4bSopenharmony_ci    } else if ((type == RenderHandleType::SHADER_STATE_OBJECT) &&
20998bf80f4bSopenharmony_ci               (arrayIndex < static_cast<uint32_t>(shaderMappings_.clientData.size()))) {
21008bf80f4bSopenharmony_ci        graphicsStateIndex = shaderMappings_.clientData[arrayIndex].graphicsStateIndex;
21018bf80f4bSopenharmony_ci    }
21028bf80f4bSopenharmony_ci
21038bf80f4bSopenharmony_ci    if (graphicsStateIndex < static_cast<uint32_t>(graphicsStates_.graphicsStates.size())) {
21048bf80f4bSopenharmony_ci        flags = graphicsStates_.data[arrayIndex].stateFlags;
21058bf80f4bSopenharmony_ci    }
21068bf80f4bSopenharmony_ci    return flags;
21078bf80f4bSopenharmony_ci}
21088bf80f4bSopenharmony_ci
21098bf80f4bSopenharmony_ciGraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const RenderHandleReference& handle) const
21108bf80f4bSopenharmony_ci{
21118bf80f4bSopenharmony_ci    return GetForcedGraphicsStateFlags(handle.GetHandle());
21128bf80f4bSopenharmony_ci}
21138bf80f4bSopenharmony_ci
21148bf80f4bSopenharmony_ciGraphicsStateFlags ShaderManager::GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const
21158bf80f4bSopenharmony_ci{
21168bf80f4bSopenharmony_ci    if (renderSlotId < static_cast<uint32_t>(renderSlotIds_.data.size())) {
21178bf80f4bSopenharmony_ci        return GetForcedGraphicsStateFlags(renderSlotIds_.data[renderSlotId].graphicsState.GetHandle());
21188bf80f4bSopenharmony_ci    }
21198bf80f4bSopenharmony_ci    return 0u;
21208bf80f4bSopenharmony_ci}
21218bf80f4bSopenharmony_ci
21228bf80f4bSopenharmony_civoid ShaderManager::SetFileManager(IFileManager& fileMgr)
21238bf80f4bSopenharmony_ci{
21248bf80f4bSopenharmony_ci    fileMgr_ = &fileMgr;
21258bf80f4bSopenharmony_ci    shaderLoader_ = make_unique<ShaderLoader>(*fileMgr_, *this, device_.GetBackendType());
21268bf80f4bSopenharmony_ci}
21278bf80f4bSopenharmony_ci
21288bf80f4bSopenharmony_ciconstexpr uint8_t REFLECTION_TAG[] = { 'r', 'f', 'l', 0 };
21298bf80f4bSopenharmony_cistruct ReflectionHeader {
21308bf80f4bSopenharmony_ci    uint8_t tag[sizeof(REFLECTION_TAG)];
21318bf80f4bSopenharmony_ci    uint16_t type;
21328bf80f4bSopenharmony_ci    uint16_t offsetPushConstants;
21338bf80f4bSopenharmony_ci    uint16_t offsetSpecializationConstants;
21348bf80f4bSopenharmony_ci    uint16_t offsetDescriptorSets;
21358bf80f4bSopenharmony_ci    uint16_t offsetInputs;
21368bf80f4bSopenharmony_ci    uint16_t offsetLocalSize;
21378bf80f4bSopenharmony_ci};
21388bf80f4bSopenharmony_ci
21398bf80f4bSopenharmony_cibool ShaderReflectionData::IsValid() const
21408bf80f4bSopenharmony_ci{
21418bf80f4bSopenharmony_ci    if (reflectionData.size() < sizeof(ReflectionHeader)) {
21428bf80f4bSopenharmony_ci        return false;
21438bf80f4bSopenharmony_ci    }
21448bf80f4bSopenharmony_ci    const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
21458bf80f4bSopenharmony_ci    return memcmp(header.tag, REFLECTION_TAG, sizeof(REFLECTION_TAG)) == 0;
21468bf80f4bSopenharmony_ci}
21478bf80f4bSopenharmony_ci
21488bf80f4bSopenharmony_ciShaderStageFlags ShaderReflectionData::GetStageFlags() const
21498bf80f4bSopenharmony_ci{
21508bf80f4bSopenharmony_ci    ShaderStageFlags flags;
21518bf80f4bSopenharmony_ci    const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
21528bf80f4bSopenharmony_ci    flags = header.type;
21538bf80f4bSopenharmony_ci    return flags;
21548bf80f4bSopenharmony_ci}
21558bf80f4bSopenharmony_ci
21568bf80f4bSopenharmony_ciPipelineLayout ShaderReflectionData::GetPipelineLayout() const
21578bf80f4bSopenharmony_ci{
21588bf80f4bSopenharmony_ci    PipelineLayout pipelineLayout;
21598bf80f4bSopenharmony_ci    const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
21608bf80f4bSopenharmony_ci    if (header.offsetPushConstants && header.offsetPushConstants < reflectionData.size()) {
21618bf80f4bSopenharmony_ci        auto ptr = reflectionData.data() + header.offsetPushConstants;
21628bf80f4bSopenharmony_ci        const auto constants = *ptr;
21638bf80f4bSopenharmony_ci        if (constants) {
21648bf80f4bSopenharmony_ci            pipelineLayout.pushConstant.shaderStageFlags = header.type;
21658bf80f4bSopenharmony_ci            pipelineLayout.pushConstant.byteSize = static_cast<uint32_t>(*(ptr + 1) | (*(ptr + 2) << 8));
21668bf80f4bSopenharmony_ci        }
21678bf80f4bSopenharmony_ci    }
21688bf80f4bSopenharmony_ci    if (header.offsetDescriptorSets && header.offsetDescriptorSets < reflectionData.size()) {
21698bf80f4bSopenharmony_ci        auto ptr = reflectionData.data() + header.offsetDescriptorSets;
21708bf80f4bSopenharmony_ci        pipelineLayout.descriptorSetCount = static_cast<uint32_t>(*(ptr) | (*(ptr + 1) << 8));
21718bf80f4bSopenharmony_ci        ptr += 2;
21728bf80f4bSopenharmony_ci        for (auto i = 0u; i < pipelineLayout.descriptorSetCount; ++i) {
21738bf80f4bSopenharmony_ci            // write to correct set location
21748bf80f4bSopenharmony_ci            const uint32_t set = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
21758bf80f4bSopenharmony_ci            PLUGIN_ASSERT(set < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT);
21768bf80f4bSopenharmony_ci            auto& layout = pipelineLayout.descriptorSetLayouts[set];
21778bf80f4bSopenharmony_ci            layout.set = set;
21788bf80f4bSopenharmony_ci            ptr += 2;
21798bf80f4bSopenharmony_ci            const auto bindings = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
21808bf80f4bSopenharmony_ci            ptr += 2;
21818bf80f4bSopenharmony_ci            for (auto j = 0u; j < bindings; ++j) {
21828bf80f4bSopenharmony_ci                DescriptorSetLayoutBinding binding;
21838bf80f4bSopenharmony_ci                binding.binding = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
21848bf80f4bSopenharmony_ci                ptr += 2;
21858bf80f4bSopenharmony_ci                binding.descriptorType = static_cast<DescriptorType>(*ptr | (*(ptr + 1) << 8));
21868bf80f4bSopenharmony_ci                if ((binding.descriptorType > DescriptorType::CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) &&
21878bf80f4bSopenharmony_ci                    (binding.descriptorType ==
21888bf80f4bSopenharmony_ci                        (DescriptorType::CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE & 0xffff))) {
21898bf80f4bSopenharmony_ci                    binding.descriptorType = DescriptorType::CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE;
21908bf80f4bSopenharmony_ci                }
21918bf80f4bSopenharmony_ci                ptr += 2;
21928bf80f4bSopenharmony_ci                binding.descriptorCount = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8));
21938bf80f4bSopenharmony_ci                ptr += 2;
21948bf80f4bSopenharmony_ci                binding.shaderStageFlags = header.type;
21958bf80f4bSopenharmony_ci                layout.bindings.push_back(binding);
21968bf80f4bSopenharmony_ci            }
21978bf80f4bSopenharmony_ci        }
21988bf80f4bSopenharmony_ci    }
21998bf80f4bSopenharmony_ci    return pipelineLayout;
22008bf80f4bSopenharmony_ci}
22018bf80f4bSopenharmony_ci
22028bf80f4bSopenharmony_civector<ShaderSpecialization::Constant> ShaderReflectionData::GetSpecializationConstants() const
22038bf80f4bSopenharmony_ci{
22048bf80f4bSopenharmony_ci    vector<ShaderSpecialization::Constant> constants;
22058bf80f4bSopenharmony_ci    const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
22068bf80f4bSopenharmony_ci    if (header.offsetSpecializationConstants && header.offsetSpecializationConstants < reflectionData.size()) {
22078bf80f4bSopenharmony_ci        auto ptr = reflectionData.data() + header.offsetSpecializationConstants;
22088bf80f4bSopenharmony_ci        const auto size = *ptr | *(ptr + 1) << 8 | *(ptr + 2) << 16 | *(ptr + 3) << 24;
22098bf80f4bSopenharmony_ci        ptr += 4;
22108bf80f4bSopenharmony_ci        for (auto i = 0; i < size; ++i) {
22118bf80f4bSopenharmony_ci            ShaderSpecialization::Constant constant;
22128bf80f4bSopenharmony_ci            constant.shaderStage = header.type;
22138bf80f4bSopenharmony_ci            constant.id = static_cast<uint32_t>(*ptr | *(ptr + 1) << 8 | *(ptr + 2) << 16 | *(ptr + 3) << 24);
22148bf80f4bSopenharmony_ci            ptr += 4;
22158bf80f4bSopenharmony_ci            constant.type = static_cast<ShaderSpecialization::Constant::Type>(
22168bf80f4bSopenharmony_ci                *ptr | *(ptr + 1) << 8 | *(ptr + 2) << 16 | *(ptr + 3) << 24);
22178bf80f4bSopenharmony_ci            ptr += 4;
22188bf80f4bSopenharmony_ci            constant.offset = 0;
22198bf80f4bSopenharmony_ci            constants.push_back(constant);
22208bf80f4bSopenharmony_ci        }
22218bf80f4bSopenharmony_ci    }
22228bf80f4bSopenharmony_ci    return constants;
22238bf80f4bSopenharmony_ci}
22248bf80f4bSopenharmony_ci
22258bf80f4bSopenharmony_civector<VertexInputDeclaration::VertexInputAttributeDescription> ShaderReflectionData::GetInputDescriptions() const
22268bf80f4bSopenharmony_ci{
22278bf80f4bSopenharmony_ci    vector<VertexInputDeclaration::VertexInputAttributeDescription> inputs;
22288bf80f4bSopenharmony_ci    const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
22298bf80f4bSopenharmony_ci    if (header.offsetInputs && header.offsetInputs < reflectionData.size()) {
22308bf80f4bSopenharmony_ci        auto ptr = reflectionData.data() + header.offsetInputs;
22318bf80f4bSopenharmony_ci        const auto size = *(ptr) | (*(ptr + 1) << 8);
22328bf80f4bSopenharmony_ci        ptr += 2;
22338bf80f4bSopenharmony_ci        for (auto i = 0; i < size; ++i) {
22348bf80f4bSopenharmony_ci            VertexInputDeclaration::VertexInputAttributeDescription desc;
22358bf80f4bSopenharmony_ci            desc.location = static_cast<uint32_t>(*(ptr) | (*(ptr + 1) << 8));
22368bf80f4bSopenharmony_ci            ptr += 2;
22378bf80f4bSopenharmony_ci            desc.binding = desc.location;
22388bf80f4bSopenharmony_ci            desc.format = static_cast<Format>(*(ptr) | (*(ptr + 1) << 8));
22398bf80f4bSopenharmony_ci            ptr += 2;
22408bf80f4bSopenharmony_ci            desc.offset = 0;
22418bf80f4bSopenharmony_ci            inputs.push_back(desc);
22428bf80f4bSopenharmony_ci        }
22438bf80f4bSopenharmony_ci    }
22448bf80f4bSopenharmony_ci    return inputs;
22458bf80f4bSopenharmony_ci}
22468bf80f4bSopenharmony_ci
22478bf80f4bSopenharmony_ciMath::UVec3 ShaderReflectionData::GetLocalSize() const
22488bf80f4bSopenharmony_ci{
22498bf80f4bSopenharmony_ci    Math::UVec3 sizes;
22508bf80f4bSopenharmony_ci    const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
22518bf80f4bSopenharmony_ci    if (header.offsetLocalSize && header.offsetLocalSize < reflectionData.size()) {
22528bf80f4bSopenharmony_ci        auto ptr = reflectionData.data() + header.offsetLocalSize;
22538bf80f4bSopenharmony_ci        sizes.x = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8) | (*(ptr + 2)) << 16 | (*(ptr + 3)) << 24);
22548bf80f4bSopenharmony_ci        ptr += 4;
22558bf80f4bSopenharmony_ci        sizes.y = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8) | (*(ptr + 2)) << 16 | (*(ptr + 3)) << 24);
22568bf80f4bSopenharmony_ci        ptr += 4;
22578bf80f4bSopenharmony_ci        sizes.z = static_cast<uint32_t>(*ptr | (*(ptr + 1) << 8) | (*(ptr + 2)) << 16 | (*(ptr + 3)) << 24);
22588bf80f4bSopenharmony_ci    }
22598bf80f4bSopenharmony_ci    return sizes;
22608bf80f4bSopenharmony_ci}
22618bf80f4bSopenharmony_ci
22628bf80f4bSopenharmony_ciconst uint8_t* ShaderReflectionData::GetPushConstants() const
22638bf80f4bSopenharmony_ci{
22648bf80f4bSopenharmony_ci    const uint8_t* ptr = nullptr;
22658bf80f4bSopenharmony_ci    const ReflectionHeader& header = *reinterpret_cast<const ReflectionHeader*>(reflectionData.data());
22668bf80f4bSopenharmony_ci    if (header.offsetPushConstants && header.offsetPushConstants < reflectionData.size()) {
22678bf80f4bSopenharmony_ci        const auto constants = *(reflectionData.data() + header.offsetPushConstants);
22688bf80f4bSopenharmony_ci        if (constants) {
22698bf80f4bSopenharmony_ci            // number of constants is uint8 and the size of the constant is uint16
22708bf80f4bSopenharmony_ci            ptr = reflectionData.data() + header.offsetPushConstants + sizeof(uint8_t) + sizeof(uint16_t);
22718bf80f4bSopenharmony_ci        }
22728bf80f4bSopenharmony_ci    }
22738bf80f4bSopenharmony_ci    return ptr;
22748bf80f4bSopenharmony_ci}
22758bf80f4bSopenharmony_ci
22768bf80f4bSopenharmony_ciRenderNodeShaderManager::RenderNodeShaderManager(const ShaderManager& shaderMgr) : shaderMgr_(shaderMgr) {}
22778bf80f4bSopenharmony_ci
22788bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetShaderHandle(const string_view path) const
22798bf80f4bSopenharmony_ci{
22808bf80f4bSopenharmony_ci    return shaderMgr_.GetShaderHandle(path).GetHandle();
22818bf80f4bSopenharmony_ci}
22828bf80f4bSopenharmony_ci
22838bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetShaderHandle(const string_view path, const string_view variantName) const
22848bf80f4bSopenharmony_ci{
22858bf80f4bSopenharmony_ci    return shaderMgr_.GetShaderHandle(path, variantName).GetHandle();
22868bf80f4bSopenharmony_ci}
22878bf80f4bSopenharmony_ci
22888bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetShaderHandle(const RenderHandle& handle, const uint32_t renderSlotId) const
22898bf80f4bSopenharmony_ci{
22908bf80f4bSopenharmony_ci    return shaderMgr_.GetShaderHandle(handle, renderSlotId).GetHandle();
22918bf80f4bSopenharmony_ci}
22928bf80f4bSopenharmony_ci
22938bf80f4bSopenharmony_civector<RenderHandle> RenderNodeShaderManager::GetShaders(const uint32_t renderSlotId) const
22948bf80f4bSopenharmony_ci{
22958bf80f4bSopenharmony_ci    return shaderMgr_.GetShaderRawHandles(renderSlotId);
22968bf80f4bSopenharmony_ci}
22978bf80f4bSopenharmony_ci
22988bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(const string_view path) const
22998bf80f4bSopenharmony_ci{
23008bf80f4bSopenharmony_ci    return shaderMgr_.GetGraphicsStateHandle(path).GetHandle();
23018bf80f4bSopenharmony_ci}
23028bf80f4bSopenharmony_ci
23038bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(
23048bf80f4bSopenharmony_ci    const string_view path, const string_view variantName) const
23058bf80f4bSopenharmony_ci{
23068bf80f4bSopenharmony_ci    return shaderMgr_.GetGraphicsStateHandle(path, variantName).GetHandle();
23078bf80f4bSopenharmony_ci}
23088bf80f4bSopenharmony_ci
23098bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetGraphicsStateHandle(
23108bf80f4bSopenharmony_ci    const RenderHandle& handle, const uint32_t renderSlotId) const
23118bf80f4bSopenharmony_ci{
23128bf80f4bSopenharmony_ci    return shaderMgr_.GetGraphicsStateHandle(handle, renderSlotId).GetHandle();
23138bf80f4bSopenharmony_ci}
23148bf80f4bSopenharmony_ci
23158bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetGraphicsStateHandleByHash(const uint64_t hash) const
23168bf80f4bSopenharmony_ci{
23178bf80f4bSopenharmony_ci    return shaderMgr_.GetGraphicsStateHandleByHash(hash).GetHandle();
23188bf80f4bSopenharmony_ci}
23198bf80f4bSopenharmony_ci
23208bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetGraphicsStateHandleByShaderHandle(const RenderHandle& handle) const
23218bf80f4bSopenharmony_ci{
23228bf80f4bSopenharmony_ci    return shaderMgr_.GetGraphicsStateHandleByShaderHandle(handle).GetHandle();
23238bf80f4bSopenharmony_ci}
23248bf80f4bSopenharmony_ci
23258bf80f4bSopenharmony_ciconst GraphicsState& RenderNodeShaderManager::GetGraphicsState(const RenderHandle& handle) const
23268bf80f4bSopenharmony_ci{
23278bf80f4bSopenharmony_ci    return shaderMgr_.GetGraphicsStateRef(handle);
23288bf80f4bSopenharmony_ci}
23298bf80f4bSopenharmony_ci
23308bf80f4bSopenharmony_ciuint32_t RenderNodeShaderManager::GetRenderSlotId(const string_view renderSlot) const
23318bf80f4bSopenharmony_ci{
23328bf80f4bSopenharmony_ci    return shaderMgr_.GetRenderSlotId(renderSlot);
23338bf80f4bSopenharmony_ci}
23348bf80f4bSopenharmony_ci
23358bf80f4bSopenharmony_ciuint32_t RenderNodeShaderManager::GetRenderSlotId(const RenderHandle& handle) const
23368bf80f4bSopenharmony_ci{
23378bf80f4bSopenharmony_ci    return shaderMgr_.GetRenderSlotId(handle);
23388bf80f4bSopenharmony_ci}
23398bf80f4bSopenharmony_ci
23408bf80f4bSopenharmony_ciIShaderManager::RenderSlotData RenderNodeShaderManager::GetRenderSlotData(const uint32_t renderSlotId) const
23418bf80f4bSopenharmony_ci{
23428bf80f4bSopenharmony_ci    return shaderMgr_.GetRenderSlotData(renderSlotId);
23438bf80f4bSopenharmony_ci}
23448bf80f4bSopenharmony_ci
23458bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetVertexInputDeclarationHandleByShaderHandle(const RenderHandle& handle) const
23468bf80f4bSopenharmony_ci{
23478bf80f4bSopenharmony_ci    return shaderMgr_.GetVertexInputDeclarationHandleByShaderHandle(handle).GetHandle();
23488bf80f4bSopenharmony_ci}
23498bf80f4bSopenharmony_ci
23508bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetVertexInputDeclarationHandle(const string_view path) const
23518bf80f4bSopenharmony_ci{
23528bf80f4bSopenharmony_ci    return shaderMgr_.GetVertexInputDeclarationHandle(path).GetHandle();
23538bf80f4bSopenharmony_ci}
23548bf80f4bSopenharmony_ci
23558bf80f4bSopenharmony_ciVertexInputDeclarationView RenderNodeShaderManager::GetVertexInputDeclarationView(const RenderHandle& handle) const
23568bf80f4bSopenharmony_ci{
23578bf80f4bSopenharmony_ci    return shaderMgr_.GetVertexInputDeclarationView(handle);
23588bf80f4bSopenharmony_ci}
23598bf80f4bSopenharmony_ci
23608bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetPipelineLayoutHandleByShaderHandle(const RenderHandle& handle) const
23618bf80f4bSopenharmony_ci{
23628bf80f4bSopenharmony_ci    return shaderMgr_.GetPipelineLayoutHandleByShaderHandle(handle).GetHandle();
23638bf80f4bSopenharmony_ci}
23648bf80f4bSopenharmony_ci
23658bf80f4bSopenharmony_ciconst PipelineLayout& RenderNodeShaderManager::GetPipelineLayout(const RenderHandle& handle) const
23668bf80f4bSopenharmony_ci{
23678bf80f4bSopenharmony_ci    return shaderMgr_.GetPipelineLayoutRef(handle);
23688bf80f4bSopenharmony_ci}
23698bf80f4bSopenharmony_ci
23708bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetPipelineLayoutHandle(const string_view path) const
23718bf80f4bSopenharmony_ci{
23728bf80f4bSopenharmony_ci    return shaderMgr_.GetPipelineLayoutHandle(path).GetHandle();
23738bf80f4bSopenharmony_ci}
23748bf80f4bSopenharmony_ci
23758bf80f4bSopenharmony_ciRenderHandle RenderNodeShaderManager::GetReflectionPipelineLayoutHandle(const RenderHandle& handle) const
23768bf80f4bSopenharmony_ci{
23778bf80f4bSopenharmony_ci    return shaderMgr_.GetReflectionPipelineLayoutHandle(handle).GetHandle();
23788bf80f4bSopenharmony_ci}
23798bf80f4bSopenharmony_ci
23808bf80f4bSopenharmony_ciconst PipelineLayout& RenderNodeShaderManager::GetReflectionPipelineLayout(const RenderHandle& handle) const
23818bf80f4bSopenharmony_ci{
23828bf80f4bSopenharmony_ci    return shaderMgr_.GetReflectionPipelineLayoutRef(handle);
23838bf80f4bSopenharmony_ci}
23848bf80f4bSopenharmony_ci
23858bf80f4bSopenharmony_ciShaderSpecializationConstantView RenderNodeShaderManager::GetReflectionSpecialization(const RenderHandle& handle) const
23868bf80f4bSopenharmony_ci{
23878bf80f4bSopenharmony_ci    return shaderMgr_.GetReflectionSpecialization(handle);
23888bf80f4bSopenharmony_ci}
23898bf80f4bSopenharmony_ci
23908bf80f4bSopenharmony_ciVertexInputDeclarationView RenderNodeShaderManager::GetReflectionVertexInputDeclaration(
23918bf80f4bSopenharmony_ci    const RenderHandle& handle) const
23928bf80f4bSopenharmony_ci{
23938bf80f4bSopenharmony_ci    return shaderMgr_.GetReflectionVertexInputDeclaration(handle);
23948bf80f4bSopenharmony_ci}
23958bf80f4bSopenharmony_ci
23968bf80f4bSopenharmony_ciShaderThreadGroup RenderNodeShaderManager::GetReflectionThreadGroupSize(const RenderHandle& handle) const
23978bf80f4bSopenharmony_ci{
23988bf80f4bSopenharmony_ci    return shaderMgr_.GetReflectionThreadGroupSize(handle);
23998bf80f4bSopenharmony_ci}
24008bf80f4bSopenharmony_ci
24018bf80f4bSopenharmony_ciuint64_t RenderNodeShaderManager::HashGraphicsState(const GraphicsState& graphicsState) const
24028bf80f4bSopenharmony_ci{
24038bf80f4bSopenharmony_ci    return shaderMgr_.HashGraphicsState(graphicsState);
24048bf80f4bSopenharmony_ci}
24058bf80f4bSopenharmony_ci
24068bf80f4bSopenharmony_cibool RenderNodeShaderManager::IsValid(const RenderHandle& handle) const
24078bf80f4bSopenharmony_ci{
24088bf80f4bSopenharmony_ci    return RenderHandleUtil::IsValid(handle);
24098bf80f4bSopenharmony_ci}
24108bf80f4bSopenharmony_ci
24118bf80f4bSopenharmony_cibool RenderNodeShaderManager::IsComputeShader(const RenderHandle& handle) const
24128bf80f4bSopenharmony_ci{
24138bf80f4bSopenharmony_ci    return IsComputeShaderFunc(handle);
24148bf80f4bSopenharmony_ci}
24158bf80f4bSopenharmony_ci
24168bf80f4bSopenharmony_cibool RenderNodeShaderManager::IsShader(const RenderHandle& handle) const
24178bf80f4bSopenharmony_ci{
24188bf80f4bSopenharmony_ci    return IsShaderFunc(handle);
24198bf80f4bSopenharmony_ci}
24208bf80f4bSopenharmony_ci
24218bf80f4bSopenharmony_civector<RenderHandle> RenderNodeShaderManager::GetShaders(
24228bf80f4bSopenharmony_ci    const RenderHandle& handle, const ShaderStageFlags shaderStageFlags) const
24238bf80f4bSopenharmony_ci{
24248bf80f4bSopenharmony_ci    return shaderMgr_.GetShaders(handle, shaderStageFlags);
24258bf80f4bSopenharmony_ci}
24268bf80f4bSopenharmony_ci
24278bf80f4bSopenharmony_ciIShaderManager::CompatibilityFlags RenderNodeShaderManager::GetCompatibilityFlags(
24288bf80f4bSopenharmony_ci    const RenderHandle& lhs, const RenderHandle& rhs) const
24298bf80f4bSopenharmony_ci{
24308bf80f4bSopenharmony_ci    return shaderMgr_.GetCompatibilityFlags(lhs, rhs);
24318bf80f4bSopenharmony_ci}
24328bf80f4bSopenharmony_ci
24338bf80f4bSopenharmony_ciGraphicsStateFlags RenderNodeShaderManager::GetForcedGraphicsStateFlags(const RenderHandle& handle) const
24348bf80f4bSopenharmony_ci{
24358bf80f4bSopenharmony_ci    return shaderMgr_.GetForcedGraphicsStateFlags(handle);
24368bf80f4bSopenharmony_ci}
24378bf80f4bSopenharmony_ci
24388bf80f4bSopenharmony_ciGraphicsStateFlags RenderNodeShaderManager::GetForcedGraphicsStateFlags(const uint32_t renderSlotId) const
24398bf80f4bSopenharmony_ci{
24408bf80f4bSopenharmony_ci    return shaderMgr_.GetForcedGraphicsStateFlags(renderSlotId);
24418bf80f4bSopenharmony_ci}
24428bf80f4bSopenharmony_ciRENDER_END_NAMESPACE()
2443