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 "loader/shader_loader.h" 178bf80f4bSopenharmony_ci 188bf80f4bSopenharmony_ci#include <cstring> 198bf80f4bSopenharmony_ci#include <set> 208bf80f4bSopenharmony_ci 218bf80f4bSopenharmony_ci#include <base/containers/array_view.h> 228bf80f4bSopenharmony_ci#include <base/containers/vector.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/shader_manager.h" 298bf80f4bSopenharmony_ci#include "loader/json_util.h" 308bf80f4bSopenharmony_ci#include "loader/pipeline_layout_loader.h" 318bf80f4bSopenharmony_ci#include "loader/shader_data_loader.h" 328bf80f4bSopenharmony_ci#include "loader/shader_state_loader.h" 338bf80f4bSopenharmony_ci#include "loader/vertex_input_declaration_loader.h" 348bf80f4bSopenharmony_ci#include "util/log.h" 358bf80f4bSopenharmony_ci 368bf80f4bSopenharmony_ciusing namespace BASE_NS; 378bf80f4bSopenharmony_ciusing namespace CORE_NS; 388bf80f4bSopenharmony_ci 398bf80f4bSopenharmony_ciRENDER_BEGIN_NAMESPACE() 408bf80f4bSopenharmony_cinamespace { 418bf80f4bSopenharmony_cienum ShaderDataFileType : uint32_t { 428bf80f4bSopenharmony_ci UNDEFINED = 0, 438bf80f4bSopenharmony_ci SHADER = 1, 448bf80f4bSopenharmony_ci SHADER_STATE = 2, 458bf80f4bSopenharmony_ci VERTEX_INPUT_DECLARATION = 3, 468bf80f4bSopenharmony_ci PIPELINE_LAYOUT = 4, 478bf80f4bSopenharmony_ci}; 488bf80f4bSopenharmony_ci 498bf80f4bSopenharmony_ciconstexpr string_view ShaderDataFileExtensions[] { 508bf80f4bSopenharmony_ci "", 518bf80f4bSopenharmony_ci ".shader", 528bf80f4bSopenharmony_ci ".shadergs", 538bf80f4bSopenharmony_ci ".shadervid", 548bf80f4bSopenharmony_ci ".shaderpl", 558bf80f4bSopenharmony_ci}; 568bf80f4bSopenharmony_ci 578bf80f4bSopenharmony_cibool HasExtension(const char* ext, const string_view fileUri) 588bf80f4bSopenharmony_ci{ 598bf80f4bSopenharmony_ci if (auto const pos = fileUri.rfind(ext); pos != string_view::npos) { 608bf80f4bSopenharmony_ci return std::strlen(ext) == (fileUri.length() - pos); 618bf80f4bSopenharmony_ci } 628bf80f4bSopenharmony_ci return false; 638bf80f4bSopenharmony_ci} 648bf80f4bSopenharmony_ci 658bf80f4bSopenharmony_ciShaderDataFileType GetShaderDataFileType(IFileManager& fileMgr, const string_view fullFilename) 668bf80f4bSopenharmony_ci{ 678bf80f4bSopenharmony_ci if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER].data(), fullFilename)) { 688bf80f4bSopenharmony_ci return ShaderDataFileType::SHADER; 698bf80f4bSopenharmony_ci } else if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER_STATE].data(), fullFilename)) { 708bf80f4bSopenharmony_ci return ShaderDataFileType::SHADER_STATE; 718bf80f4bSopenharmony_ci } else if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::PIPELINE_LAYOUT].data(), fullFilename)) { 728bf80f4bSopenharmony_ci return ShaderDataFileType::PIPELINE_LAYOUT; 738bf80f4bSopenharmony_ci } else if (HasExtension( 748bf80f4bSopenharmony_ci ShaderDataFileExtensions[ShaderDataFileType::VERTEX_INPUT_DECLARATION].data(), fullFilename)) { 758bf80f4bSopenharmony_ci return ShaderDataFileType::VERTEX_INPUT_DECLARATION; 768bf80f4bSopenharmony_ci } 778bf80f4bSopenharmony_ci return ShaderDataFileType::UNDEFINED; 788bf80f4bSopenharmony_ci} 798bf80f4bSopenharmony_ci 808bf80f4bSopenharmony_civector<uint8_t> ReadFile(IFile& file) 818bf80f4bSopenharmony_ci{ 828bf80f4bSopenharmony_ci auto fileData = vector<uint8_t>(static_cast<std::size_t>(file.GetLength())); 838bf80f4bSopenharmony_ci file.Read(fileData.data(), fileData.size()); 848bf80f4bSopenharmony_ci return fileData; 858bf80f4bSopenharmony_ci} 868bf80f4bSopenharmony_ci} // namespace 878bf80f4bSopenharmony_ci 888bf80f4bSopenharmony_ciShaderLoader::ShaderLoader(IFileManager& fileManager, ShaderManager& shaderManager, const DeviceBackendType type) 898bf80f4bSopenharmony_ci : fileManager_(fileManager), shaderMgr_(shaderManager), type_(type) 908bf80f4bSopenharmony_ci{} 918bf80f4bSopenharmony_ci 928bf80f4bSopenharmony_civoid ShaderLoader::Load(const ShaderManager::ShaderFilePathDesc& desc) 938bf80f4bSopenharmony_ci{ 948bf80f4bSopenharmony_ci if (!desc.shaderStatePath.empty()) { 958bf80f4bSopenharmony_ci auto const shaderStatesPath = fileManager_.OpenDirectory(desc.shaderStatePath); 968bf80f4bSopenharmony_ci if (shaderStatesPath) { 978bf80f4bSopenharmony_ci LoadShaderStates(desc.shaderStatePath, *shaderStatesPath); 988bf80f4bSopenharmony_ci } else { 998bf80f4bSopenharmony_ci PLUGIN_LOG_W("graphics state path (%s) not found.", desc.shaderStatePath.data()); 1008bf80f4bSopenharmony_ci } 1018bf80f4bSopenharmony_ci } 1028bf80f4bSopenharmony_ci if (!desc.vertexInputDeclarationPath.empty()) { 1038bf80f4bSopenharmony_ci auto const vidsPath = fileManager_.OpenDirectory(desc.vertexInputDeclarationPath); 1048bf80f4bSopenharmony_ci if (vidsPath) { 1058bf80f4bSopenharmony_ci LoadVids(desc.vertexInputDeclarationPath, *vidsPath); 1068bf80f4bSopenharmony_ci } else { 1078bf80f4bSopenharmony_ci PLUGIN_LOG_W("vertex input declaration path (%s) not found.", desc.vertexInputDeclarationPath.data()); 1088bf80f4bSopenharmony_ci } 1098bf80f4bSopenharmony_ci } 1108bf80f4bSopenharmony_ci if (!desc.pipelineLayoutPath.empty()) { 1118bf80f4bSopenharmony_ci auto const pipelineLayoutsPath = fileManager_.OpenDirectory(desc.pipelineLayoutPath); 1128bf80f4bSopenharmony_ci if (pipelineLayoutsPath) { 1138bf80f4bSopenharmony_ci LoadPipelineLayouts(desc.pipelineLayoutPath, *pipelineLayoutsPath); 1148bf80f4bSopenharmony_ci } else { 1158bf80f4bSopenharmony_ci PLUGIN_LOG_W("pipeline layout path (%s) not found.", desc.pipelineLayoutPath.data()); 1168bf80f4bSopenharmony_ci } 1178bf80f4bSopenharmony_ci } 1188bf80f4bSopenharmony_ci if (!desc.shaderPath.empty()) { 1198bf80f4bSopenharmony_ci auto const shadersPath = fileManager_.OpenDirectory(desc.shaderPath); 1208bf80f4bSopenharmony_ci if (shadersPath) { 1218bf80f4bSopenharmony_ci RecurseDirectory(desc.shaderPath, *shadersPath); 1228bf80f4bSopenharmony_ci } else { 1238bf80f4bSopenharmony_ci PLUGIN_LOG_W("shader path (%s) not found.", desc.shaderPath.data()); 1248bf80f4bSopenharmony_ci } 1258bf80f4bSopenharmony_ci } 1268bf80f4bSopenharmony_ci} 1278bf80f4bSopenharmony_ci 1288bf80f4bSopenharmony_civoid ShaderLoader::LoadFile(const string_view uri, const bool forceReload) 1298bf80f4bSopenharmony_ci{ 1308bf80f4bSopenharmony_ci const IDirectory::Entry entry = fileManager_.GetEntry(uri); 1318bf80f4bSopenharmony_ci if (entry.type == IDirectory::Entry::FILE) { 1328bf80f4bSopenharmony_ci // NOTE: currently there's no info within the shader json files 1338bf80f4bSopenharmony_ci // we do type evaluation based on some key names in the json 1348bf80f4bSopenharmony_ci const ShaderDataFileType shaderDataFileType = GetShaderDataFileType(fileManager_, uri); 1358bf80f4bSopenharmony_ci switch (shaderDataFileType) { 1368bf80f4bSopenharmony_ci case ShaderDataFileType::SHADER: { 1378bf80f4bSopenharmony_ci // Force re-loads the shader module creation 1388bf80f4bSopenharmony_ci HandleShaderFile(uri, entry, forceReload); 1398bf80f4bSopenharmony_ci break; 1408bf80f4bSopenharmony_ci } 1418bf80f4bSopenharmony_ci case ShaderDataFileType::SHADER_STATE: { 1428bf80f4bSopenharmony_ci HandleShaderStateFile(uri, entry); 1438bf80f4bSopenharmony_ci break; 1448bf80f4bSopenharmony_ci } 1458bf80f4bSopenharmony_ci case ShaderDataFileType::PIPELINE_LAYOUT: { 1468bf80f4bSopenharmony_ci HandlePipelineLayoutFile(uri, entry); 1478bf80f4bSopenharmony_ci break; 1488bf80f4bSopenharmony_ci } 1498bf80f4bSopenharmony_ci case ShaderDataFileType::VERTEX_INPUT_DECLARATION: { 1508bf80f4bSopenharmony_ci HandleVertexInputDeclarationFile(uri, entry); 1518bf80f4bSopenharmony_ci break; 1528bf80f4bSopenharmony_ci } 1538bf80f4bSopenharmony_ci default: { 1548bf80f4bSopenharmony_ci break; 1558bf80f4bSopenharmony_ci } 1568bf80f4bSopenharmony_ci } 1578bf80f4bSopenharmony_ci } 1588bf80f4bSopenharmony_ci} 1598bf80f4bSopenharmony_ci 1608bf80f4bSopenharmony_civoid ShaderLoader::HandleShaderFile( 1618bf80f4bSopenharmony_ci const string_view fullFileName, const IDirectory::Entry& entry, const bool forceReload) 1628bf80f4bSopenharmony_ci{ 1638bf80f4bSopenharmony_ci if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER].data(), entry.name)) { 1648bf80f4bSopenharmony_ci ShaderDataLoader loader; 1658bf80f4bSopenharmony_ci const auto result = loader.Load(fileManager_, fullFileName); 1668bf80f4bSopenharmony_ci if (result.success) { 1678bf80f4bSopenharmony_ci auto const handle = CreateShader(loader, forceReload); 1688bf80f4bSopenharmony_ci#if (RENDER_DEV_ENABLED == 1) 1698bf80f4bSopenharmony_ci const auto shaderVariants = loader.GetShaderVariants(); 1708bf80f4bSopenharmony_ci for (const auto& shaderVariant : shaderVariants) { 1718bf80f4bSopenharmony_ci // Dev related book-keeping for reloading of spv files 1728bf80f4bSopenharmony_ci auto const handleType = handle.GetHandleType(); 1738bf80f4bSopenharmony_ci if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) { 1748bf80f4bSopenharmony_ci string compShader = shaderVariant.computeShader; 1758bf80f4bSopenharmony_ci PLUGIN_ASSERT(!compShader.empty()); 1768bf80f4bSopenharmony_ci 1778bf80f4bSopenharmony_ci auto& ref = fileToShaderNames_[move(compShader)]; 1788bf80f4bSopenharmony_ci ref.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT; 1798bf80f4bSopenharmony_ci ref.shaderNames.emplace_back(fullFileName); 1808bf80f4bSopenharmony_ci } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) { 1818bf80f4bSopenharmony_ci string vertShader = shaderVariant.vertexShader; 1828bf80f4bSopenharmony_ci string fragShader = shaderVariant.fragmentShader; 1838bf80f4bSopenharmony_ci PLUGIN_ASSERT_MSG( 1848bf80f4bSopenharmony_ci (!vertShader.empty()) && (!fragShader.empty()), "shader name: %s", fullFileName.data()); 1858bf80f4bSopenharmony_ci 1868bf80f4bSopenharmony_ci auto& refVert = fileToShaderNames_[move(vertShader)]; 1878bf80f4bSopenharmony_ci refVert.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT; 1888bf80f4bSopenharmony_ci refVert.shaderNames.emplace_back(fullFileName); 1898bf80f4bSopenharmony_ci auto& refFrag = fileToShaderNames_[move(fragShader)]; 1908bf80f4bSopenharmony_ci refFrag.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT; 1918bf80f4bSopenharmony_ci refFrag.shaderNames.emplace_back(fullFileName); 1928bf80f4bSopenharmony_ci } 1938bf80f4bSopenharmony_ci } 1948bf80f4bSopenharmony_ci#endif 1958bf80f4bSopenharmony_ci } else { 1968bf80f4bSopenharmony_ci PLUGIN_LOG_E("unable to load shader json %s : %s", fullFileName.data(), result.error.c_str()); 1978bf80f4bSopenharmony_ci } 1988bf80f4bSopenharmony_ci } 1998bf80f4bSopenharmony_ci} 2008bf80f4bSopenharmony_ci 2018bf80f4bSopenharmony_civoid ShaderLoader::HandleShaderStateFile(const string_view fullFileName, const IDirectory::Entry& entry) 2028bf80f4bSopenharmony_ci{ 2038bf80f4bSopenharmony_ci if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER_STATE].data(), entry.name)) { 2048bf80f4bSopenharmony_ci ShaderStateLoader loader; 2058bf80f4bSopenharmony_ci const auto result = loader.Load(fileManager_, fullFileName); 2068bf80f4bSopenharmony_ci if (result.success) { 2078bf80f4bSopenharmony_ci CreateShaderStates(loader.GetUri(), loader.GetGraphicsStateVariantData(), loader.GetGraphicsStates()); 2088bf80f4bSopenharmony_ci } else { 2098bf80f4bSopenharmony_ci PLUGIN_LOG_E("unable to load shader state json %s : %s", fullFileName.data(), result.error.c_str()); 2108bf80f4bSopenharmony_ci } 2118bf80f4bSopenharmony_ci } 2128bf80f4bSopenharmony_ci} 2138bf80f4bSopenharmony_ci 2148bf80f4bSopenharmony_civoid ShaderLoader::HandlePipelineLayoutFile(const string_view fullFileName, const IDirectory::Entry& entry) 2158bf80f4bSopenharmony_ci{ 2168bf80f4bSopenharmony_ci if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::PIPELINE_LAYOUT].data(), entry.name)) { 2178bf80f4bSopenharmony_ci PipelineLayoutLoader loader; 2188bf80f4bSopenharmony_ci const auto result = loader.Load(fileManager_, fullFileName); 2198bf80f4bSopenharmony_ci if (result.success) { 2208bf80f4bSopenharmony_ci auto const handle = CreatePipelineLayout(loader); 2218bf80f4bSopenharmony_ci if (!handle) { 2228bf80f4bSopenharmony_ci PLUGIN_LOG_E( 2238bf80f4bSopenharmony_ci "pipeline layout could not be created (%s) (%s)", fullFileName.data(), loader.GetUri().data()); 2248bf80f4bSopenharmony_ci } 2258bf80f4bSopenharmony_ci } else { 2268bf80f4bSopenharmony_ci PLUGIN_LOG_E("unable to load pipeline layout json %s : %s", fullFileName.data(), result.error.c_str()); 2278bf80f4bSopenharmony_ci } 2288bf80f4bSopenharmony_ci } 2298bf80f4bSopenharmony_ci} 2308bf80f4bSopenharmony_ci 2318bf80f4bSopenharmony_civoid ShaderLoader::HandleVertexInputDeclarationFile(const string_view fullFileName, const IDirectory::Entry& entry) 2328bf80f4bSopenharmony_ci{ 2338bf80f4bSopenharmony_ci if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::VERTEX_INPUT_DECLARATION].data(), entry.name)) { 2348bf80f4bSopenharmony_ci VertexInputDeclarationLoader loader; 2358bf80f4bSopenharmony_ci const auto result = loader.Load(fileManager_, fullFileName); 2368bf80f4bSopenharmony_ci if (result.success) { 2378bf80f4bSopenharmony_ci auto const vidName = loader.GetUri(); 2388bf80f4bSopenharmony_ci auto const handle = CreateVertexInputDeclaration(loader); 2398bf80f4bSopenharmony_ci if (!handle) { 2408bf80f4bSopenharmony_ci PLUGIN_LOG_E( 2418bf80f4bSopenharmony_ci "vertex input declaration could not be created (%s) (%s)", fullFileName.data(), vidName.data()); 2428bf80f4bSopenharmony_ci } 2438bf80f4bSopenharmony_ci } else { 2448bf80f4bSopenharmony_ci PLUGIN_LOG_E( 2458bf80f4bSopenharmony_ci "unable to load vertex input declaration json %s : %s", fullFileName.data(), result.error.c_str()); 2468bf80f4bSopenharmony_ci } 2478bf80f4bSopenharmony_ci } 2488bf80f4bSopenharmony_ci} 2498bf80f4bSopenharmony_ci 2508bf80f4bSopenharmony_civoid ShaderLoader::RecurseDirectory(const string_view currentPath, const IDirectory& directory) 2518bf80f4bSopenharmony_ci{ 2528bf80f4bSopenharmony_ci for (auto const& entry : directory.GetEntries()) { 2538bf80f4bSopenharmony_ci switch (entry.type) { 2548bf80f4bSopenharmony_ci default: 2558bf80f4bSopenharmony_ci case IDirectory::Entry::Type::UNKNOWN: 2568bf80f4bSopenharmony_ci break; 2578bf80f4bSopenharmony_ci case IDirectory::Entry::Type::FILE: { 2588bf80f4bSopenharmony_ci // does not force the shader module re-creations 2598bf80f4bSopenharmony_ci HandleShaderFile(currentPath + entry.name, entry, false); 2608bf80f4bSopenharmony_ci break; 2618bf80f4bSopenharmony_ci } 2628bf80f4bSopenharmony_ci case IDirectory::Entry::Type::DIRECTORY: { 2638bf80f4bSopenharmony_ci if (entry.name == "." || entry.name == "..") { 2648bf80f4bSopenharmony_ci continue; 2658bf80f4bSopenharmony_ci } 2668bf80f4bSopenharmony_ci auto nextDirectory = currentPath + entry.name + '/'; 2678bf80f4bSopenharmony_ci auto dir = fileManager_.OpenDirectory(nextDirectory); 2688bf80f4bSopenharmony_ci if (dir) { 2698bf80f4bSopenharmony_ci RecurseDirectory(nextDirectory, *dir); 2708bf80f4bSopenharmony_ci } 2718bf80f4bSopenharmony_ci break; 2728bf80f4bSopenharmony_ci } 2738bf80f4bSopenharmony_ci } 2748bf80f4bSopenharmony_ci } 2758bf80f4bSopenharmony_ci} 2768bf80f4bSopenharmony_ci 2778bf80f4bSopenharmony_ciShaderLoader::ShaderFile ShaderLoader::LoadShaderFile(const string_view shader, const ShaderStageFlags stageBits) 2788bf80f4bSopenharmony_ci{ 2798bf80f4bSopenharmony_ci ShaderLoader::ShaderFile info; 2808bf80f4bSopenharmony_ci IFile::Ptr shaderFile; 2818bf80f4bSopenharmony_ci switch (type_) { 2828bf80f4bSopenharmony_ci case DeviceBackendType::VULKAN: 2838bf80f4bSopenharmony_ci shaderFile = fileManager_.OpenFile(shader); 2848bf80f4bSopenharmony_ci break; 2858bf80f4bSopenharmony_ci case DeviceBackendType::OPENGLES: 2868bf80f4bSopenharmony_ci shaderFile = fileManager_.OpenFile(shader + ".gles"); 2878bf80f4bSopenharmony_ci break; 2888bf80f4bSopenharmony_ci case DeviceBackendType::OPENGL: 2898bf80f4bSopenharmony_ci shaderFile = fileManager_.OpenFile(shader + ".gl"); 2908bf80f4bSopenharmony_ci break; 2918bf80f4bSopenharmony_ci default: 2928bf80f4bSopenharmony_ci break; 2938bf80f4bSopenharmony_ci } 2948bf80f4bSopenharmony_ci if (shaderFile) { 2958bf80f4bSopenharmony_ci info.data = ReadFile(*shaderFile); 2968bf80f4bSopenharmony_ci 2978bf80f4bSopenharmony_ci if (IFile::Ptr reflectionFile = fileManager_.OpenFile(shader + ".lsb"); reflectionFile) { 2988bf80f4bSopenharmony_ci info.reflectionData = ReadFile(*reflectionFile); 2998bf80f4bSopenharmony_ci } 3008bf80f4bSopenharmony_ci info.info = { stageBits, info.data, { info.reflectionData } }; 3018bf80f4bSopenharmony_ci } else { 3028bf80f4bSopenharmony_ci PLUGIN_LOG_E("shader file not found (%s)", shader.data()); 3038bf80f4bSopenharmony_ci } 3048bf80f4bSopenharmony_ci return info; 3058bf80f4bSopenharmony_ci} 3068bf80f4bSopenharmony_ci 3078bf80f4bSopenharmony_ciRenderHandleReference ShaderLoader::CreateComputeShader(const ShaderDataLoader& dataLoader, const bool forceReload) 3088bf80f4bSopenharmony_ci{ 3098bf80f4bSopenharmony_ci RenderHandleReference firstShaderVariantRhr; 3108bf80f4bSopenharmony_ci const array_view<const ShaderDataLoader::ShaderVariant> shaderVariants = dataLoader.GetShaderVariants(); 3118bf80f4bSopenharmony_ci for (const auto& shaderVariant : shaderVariants) { 3128bf80f4bSopenharmony_ci const string_view computeShader = shaderVariant.computeShader; 3138bf80f4bSopenharmony_ci uint32_t index = INVALID_SM_INDEX; 3148bf80f4bSopenharmony_ci if (!forceReload) { 3158bf80f4bSopenharmony_ci index = shaderMgr_.GetShaderModuleIndex(computeShader); 3168bf80f4bSopenharmony_ci } 3178bf80f4bSopenharmony_ci if (index == INVALID_SM_INDEX) { 3188bf80f4bSopenharmony_ci const auto shaderFile = LoadShaderFile(computeShader, ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT); 3198bf80f4bSopenharmony_ci if (!shaderFile.data.empty()) { 3208bf80f4bSopenharmony_ci index = shaderMgr_.CreateShaderModule(computeShader, shaderFile.info); 3218bf80f4bSopenharmony_ci } else { 3228bf80f4bSopenharmony_ci PLUGIN_LOG_E("shader file not found (%s)", computeShader.data()); 3238bf80f4bSopenharmony_ci } 3248bf80f4bSopenharmony_ci } 3258bf80f4bSopenharmony_ci if (index != INVALID_SM_INDEX) { 3268bf80f4bSopenharmony_ci const string_view uri = dataLoader.GetUri(); 3278bf80f4bSopenharmony_ci const string_view baseShaderPath = dataLoader.GetBaseShader(); 3288bf80f4bSopenharmony_ci const string_view baseCategory = dataLoader.GetBaseCategory(); 3298bf80f4bSopenharmony_ci const string_view variantName = shaderVariant.variantName; 3308bf80f4bSopenharmony_ci const string_view displayName = shaderVariant.displayName; 3318bf80f4bSopenharmony_ci const string_view pipelineLayout = shaderVariant.pipelineLayout; 3328bf80f4bSopenharmony_ci const string_view renderSlot = shaderVariant.renderSlot; 3338bf80f4bSopenharmony_ci const string_view shaderFileStr = shaderVariant.shaderFileStr; 3348bf80f4bSopenharmony_ci const string_view matMetadataStr = shaderVariant.materialMetadata; 3358bf80f4bSopenharmony_ci const uint32_t rsId = shaderMgr_.CreateRenderSlotId(renderSlot); 3368bf80f4bSopenharmony_ci const uint32_t catId = shaderMgr_.CreateCategoryId(baseCategory); 3378bf80f4bSopenharmony_ci const uint32_t plIndex = 3388bf80f4bSopenharmony_ci (pipelineLayout.empty()) 3398bf80f4bSopenharmony_ci ? INVALID_SM_INDEX 3408bf80f4bSopenharmony_ci : RenderHandleUtil::GetIndexPart(shaderMgr_.GetPipelineLayoutHandle(pipelineLayout).GetHandle()); 3418bf80f4bSopenharmony_ci // if many variants, the first is shader created without variant name 3428bf80f4bSopenharmony_ci // it will have additional name for searching though 3438bf80f4bSopenharmony_ci RenderHandleReference rhr; 3448bf80f4bSopenharmony_ci if (!firstShaderVariantRhr) { 3458bf80f4bSopenharmony_ci // NOTE: empty variant name 3468bf80f4bSopenharmony_ci rhr = shaderMgr_.Create( 3478bf80f4bSopenharmony_ci ComputeShaderCreateData { uri, rsId, catId, plIndex, index, shaderFileStr, matMetadataStr }, 3488bf80f4bSopenharmony_ci { baseShaderPath, {}, displayName }); 3498bf80f4bSopenharmony_ci firstShaderVariantRhr = rhr; 3508bf80f4bSopenharmony_ci // add additional fullname with variant for the base shader 3518bf80f4bSopenharmony_ci if (!variantName.empty()) { 3528bf80f4bSopenharmony_ci shaderMgr_.AddAdditionalNameForHandle(rhr, uri); 3538bf80f4bSopenharmony_ci } 3548bf80f4bSopenharmony_ci } else { 3558bf80f4bSopenharmony_ci rhr = shaderMgr_.Create( 3568bf80f4bSopenharmony_ci ComputeShaderCreateData { uri, rsId, catId, plIndex, index, shaderFileStr, matMetadataStr }, 3578bf80f4bSopenharmony_ci { baseShaderPath, variantName, displayName }); 3588bf80f4bSopenharmony_ci } 3598bf80f4bSopenharmony_ci if (shaderVariant.renderSlotDefaultShader) { 3608bf80f4bSopenharmony_ci shaderMgr_.SetRenderSlotData(rsId, rhr, {}); 3618bf80f4bSopenharmony_ci } 3628bf80f4bSopenharmony_ci } else { 3638bf80f4bSopenharmony_ci PLUGIN_LOG_E("Failed to load shader : %s", computeShader.data()); 3648bf80f4bSopenharmony_ci } 3658bf80f4bSopenharmony_ci } 3668bf80f4bSopenharmony_ci return firstShaderVariantRhr; 3678bf80f4bSopenharmony_ci} 3688bf80f4bSopenharmony_ci 3698bf80f4bSopenharmony_ciRenderHandleReference ShaderLoader::CreateGraphicsShader(const ShaderDataLoader& dataLoader, const bool forceReload) 3708bf80f4bSopenharmony_ci{ 3718bf80f4bSopenharmony_ci RenderHandleReference firstShaderVariantRhr; 3728bf80f4bSopenharmony_ci const array_view<const ShaderDataLoader::ShaderVariant> shaderVariants = dataLoader.GetShaderVariants(); 3738bf80f4bSopenharmony_ci for (const auto& svRef : shaderVariants) { 3748bf80f4bSopenharmony_ci const string_view vertexShader = svRef.vertexShader; 3758bf80f4bSopenharmony_ci const string_view fragmentShader = svRef.fragmentShader; 3768bf80f4bSopenharmony_ci uint32_t vertIndex = (forceReload) ? INVALID_SM_INDEX : shaderMgr_.GetShaderModuleIndex(vertexShader); 3778bf80f4bSopenharmony_ci if (vertIndex == INVALID_SM_INDEX) { 3788bf80f4bSopenharmony_ci const auto shaderFile = LoadShaderFile(vertexShader, ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT); 3798bf80f4bSopenharmony_ci if (!shaderFile.data.empty()) { 3808bf80f4bSopenharmony_ci vertIndex = shaderMgr_.CreateShaderModule(vertexShader, shaderFile.info); 3818bf80f4bSopenharmony_ci } 3828bf80f4bSopenharmony_ci } 3838bf80f4bSopenharmony_ci uint32_t fragIndex = (forceReload) ? INVALID_SM_INDEX : shaderMgr_.GetShaderModuleIndex(fragmentShader); 3848bf80f4bSopenharmony_ci if (fragIndex == INVALID_SM_INDEX) { 3858bf80f4bSopenharmony_ci const auto shaderFile = LoadShaderFile(fragmentShader, ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT); 3868bf80f4bSopenharmony_ci if (!shaderFile.data.empty()) { 3878bf80f4bSopenharmony_ci fragIndex = shaderMgr_.CreateShaderModule(fragmentShader, shaderFile.info); 3888bf80f4bSopenharmony_ci } 3898bf80f4bSopenharmony_ci } 3908bf80f4bSopenharmony_ci if ((vertIndex != INVALID_SM_INDEX) && (fragIndex != INVALID_SM_INDEX)) { 3918bf80f4bSopenharmony_ci const string_view uri = dataLoader.GetUri(); 3928bf80f4bSopenharmony_ci // creating the default graphics state with full name 3938bf80f4bSopenharmony_ci const string fullName = uri + svRef.variantName; 3948bf80f4bSopenharmony_ci // default graphics state is created beforehand 3958bf80f4bSopenharmony_ci const RenderHandleReference defaultGfxState = shaderMgr_.CreateGraphicsState( 3968bf80f4bSopenharmony_ci { fullName, svRef.graphicsState }, { svRef.renderSlot, {}, {}, {}, svRef.stateFlags }); 3978bf80f4bSopenharmony_ci const uint32_t rsId = shaderMgr_.CreateRenderSlotId(svRef.renderSlot); 3988bf80f4bSopenharmony_ci const uint32_t catId = shaderMgr_.CreateCategoryId(dataLoader.GetBaseCategory()); 3998bf80f4bSopenharmony_ci const uint32_t plIndex = svRef.pipelineLayout.empty() 4008bf80f4bSopenharmony_ci ? INVALID_SM_INDEX 4018bf80f4bSopenharmony_ci : RenderHandleUtil::GetIndexPart( 4028bf80f4bSopenharmony_ci shaderMgr_.GetPipelineLayoutHandle(svRef.pipelineLayout).GetHandle()); 4038bf80f4bSopenharmony_ci const uint32_t vidIndex = 4048bf80f4bSopenharmony_ci svRef.vertexInputDeclaration.empty() 4058bf80f4bSopenharmony_ci ? INVALID_SM_INDEX 4068bf80f4bSopenharmony_ci : RenderHandleUtil::GetIndexPart( 4078bf80f4bSopenharmony_ci shaderMgr_.GetVertexInputDeclarationHandle(svRef.vertexInputDeclaration).GetHandle()); 4088bf80f4bSopenharmony_ci const uint32_t stateIndex = RenderHandleUtil::GetIndexPart(defaultGfxState.GetHandle()); 4098bf80f4bSopenharmony_ci const string_view shaderStr = svRef.shaderFileStr; 4108bf80f4bSopenharmony_ci const string_view matMeta = svRef.materialMetadata; 4118bf80f4bSopenharmony_ci // if many variants, the first is shader created without variant name 4128bf80f4bSopenharmony_ci // it will have additional name for searching though 4138bf80f4bSopenharmony_ci RenderHandleReference rhr; 4148bf80f4bSopenharmony_ci if (!firstShaderVariantRhr) { 4158bf80f4bSopenharmony_ci // NOTE: empty variant name 4168bf80f4bSopenharmony_ci rhr = shaderMgr_.Create( 4178bf80f4bSopenharmony_ci { uri, rsId, catId, vidIndex, plIndex, stateIndex, vertIndex, fragIndex, shaderStr, matMeta }, 4188bf80f4bSopenharmony_ci { dataLoader.GetBaseShader(), {}, svRef.displayName }); 4198bf80f4bSopenharmony_ci firstShaderVariantRhr = rhr; 4208bf80f4bSopenharmony_ci // add additional fullname with variant for the base shader 4218bf80f4bSopenharmony_ci if (!svRef.variantName.empty()) { 4228bf80f4bSopenharmony_ci shaderMgr_.AddAdditionalNameForHandle(firstShaderVariantRhr, fullName); 4238bf80f4bSopenharmony_ci } 4248bf80f4bSopenharmony_ci } else { 4258bf80f4bSopenharmony_ci rhr = shaderMgr_.Create( 4268bf80f4bSopenharmony_ci { uri, rsId, catId, vidIndex, plIndex, stateIndex, vertIndex, fragIndex, shaderStr, matMeta }, 4278bf80f4bSopenharmony_ci { dataLoader.GetBaseShader(), svRef.variantName, svRef.displayName }); 4288bf80f4bSopenharmony_ci } 4298bf80f4bSopenharmony_ci if (svRef.renderSlotDefaultShader) { 4308bf80f4bSopenharmony_ci shaderMgr_.SetRenderSlotData(rsId, rhr, {}); 4318bf80f4bSopenharmony_ci } 4328bf80f4bSopenharmony_ci } else { 4338bf80f4bSopenharmony_ci PLUGIN_LOG_E("Failed to load shader : %s %s", vertexShader.data(), fragmentShader.data()); 4348bf80f4bSopenharmony_ci } 4358bf80f4bSopenharmony_ci } 4368bf80f4bSopenharmony_ci return firstShaderVariantRhr; 4378bf80f4bSopenharmony_ci} 4388bf80f4bSopenharmony_ci 4398bf80f4bSopenharmony_ciRenderHandleReference ShaderLoader::CreateShader(const ShaderDataLoader& dataLoader, const bool forceReload) 4408bf80f4bSopenharmony_ci{ 4418bf80f4bSopenharmony_ci const array_view<const ShaderDataLoader::ShaderVariant> shaderVariants = dataLoader.GetShaderVariants(); 4428bf80f4bSopenharmony_ci if (shaderVariants.empty()) { 4438bf80f4bSopenharmony_ci return {}; 4448bf80f4bSopenharmony_ci } 4458bf80f4bSopenharmony_ci 4468bf80f4bSopenharmony_ci const string_view compShader = shaderVariants[0].computeShader; 4478bf80f4bSopenharmony_ci if (!compShader.empty()) { 4488bf80f4bSopenharmony_ci return CreateComputeShader(dataLoader, forceReload); 4498bf80f4bSopenharmony_ci } else { 4508bf80f4bSopenharmony_ci const string_view vertShader = shaderVariants[0].vertexShader; 4518bf80f4bSopenharmony_ci const string_view fragShader = shaderVariants[0].fragmentShader; 4528bf80f4bSopenharmony_ci if (!vertShader.empty() && !fragShader.empty()) { 4538bf80f4bSopenharmony_ci return CreateGraphicsShader(dataLoader, forceReload); 4548bf80f4bSopenharmony_ci } 4558bf80f4bSopenharmony_ci } 4568bf80f4bSopenharmony_ci return {}; 4578bf80f4bSopenharmony_ci} 4588bf80f4bSopenharmony_ci 4598bf80f4bSopenharmony_civoid ShaderLoader::LoadShaderStates(const string_view currentPath, const IDirectory& directory) 4608bf80f4bSopenharmony_ci{ 4618bf80f4bSopenharmony_ci for (auto const& entry : directory.GetEntries()) { 4628bf80f4bSopenharmony_ci switch (entry.type) { 4638bf80f4bSopenharmony_ci default: 4648bf80f4bSopenharmony_ci case IDirectory::Entry::Type::UNKNOWN: 4658bf80f4bSopenharmony_ci break; 4668bf80f4bSopenharmony_ci case IDirectory::Entry::Type::FILE: { 4678bf80f4bSopenharmony_ci HandleShaderStateFile(currentPath + entry.name, entry); 4688bf80f4bSopenharmony_ci break; 4698bf80f4bSopenharmony_ci } 4708bf80f4bSopenharmony_ci case IDirectory::Entry::Type::DIRECTORY: { 4718bf80f4bSopenharmony_ci PLUGIN_LOG_I("recursive vertex input declarations directories not supported"); 4728bf80f4bSopenharmony_ci break; 4738bf80f4bSopenharmony_ci } 4748bf80f4bSopenharmony_ci } 4758bf80f4bSopenharmony_ci } 4768bf80f4bSopenharmony_ci} 4778bf80f4bSopenharmony_ci 4788bf80f4bSopenharmony_civoid ShaderLoader::CreateShaderStates(const string_view uri, 4798bf80f4bSopenharmony_ci const array_view<const ShaderStateLoaderVariantData>& variantData, const array_view<const GraphicsState>& states) 4808bf80f4bSopenharmony_ci{ 4818bf80f4bSopenharmony_ci for (size_t stateIdx = 0; stateIdx < states.size(); ++stateIdx) { 4828bf80f4bSopenharmony_ci const ShaderManager::GraphicsStateCreateInfo createInfo { uri, states[stateIdx] }; 4838bf80f4bSopenharmony_ci const auto& variant = variantData[stateIdx]; 4848bf80f4bSopenharmony_ci const ShaderManager::GraphicsStateVariantCreateInfo variantCreateInfo { variant.renderSlot, variant.variantName, 4858bf80f4bSopenharmony_ci variant.baseShaderState, variant.baseVariantName, variant.stateFlags }; 4868bf80f4bSopenharmony_ci const RenderHandleReference handle = shaderMgr_.CreateGraphicsState(createInfo, variantCreateInfo); 4878bf80f4bSopenharmony_ci if (variant.renderSlotDefaultState && (!variant.renderSlot.empty())) { 4888bf80f4bSopenharmony_ci const uint32_t renderSlotId = shaderMgr_.GetRenderSlotId(variant.renderSlot); 4898bf80f4bSopenharmony_ci shaderMgr_.SetRenderSlotData(renderSlotId, {}, handle); 4908bf80f4bSopenharmony_ci } 4918bf80f4bSopenharmony_ci if (!handle) { 4928bf80f4bSopenharmony_ci PLUGIN_LOG_E( 4938bf80f4bSopenharmony_ci "error creating graphics state (name: %s, variant: %s)", uri.data(), variant.variantName.data()); 4948bf80f4bSopenharmony_ci } 4958bf80f4bSopenharmony_ci } 4968bf80f4bSopenharmony_ci} 4978bf80f4bSopenharmony_ci 4988bf80f4bSopenharmony_civoid ShaderLoader::LoadVids(const string_view currentPath, const IDirectory& directory) 4998bf80f4bSopenharmony_ci{ 5008bf80f4bSopenharmony_ci for (auto const& entry : directory.GetEntries()) { 5018bf80f4bSopenharmony_ci switch (entry.type) { 5028bf80f4bSopenharmony_ci default: 5038bf80f4bSopenharmony_ci case IDirectory::Entry::Type::UNKNOWN: 5048bf80f4bSopenharmony_ci break; 5058bf80f4bSopenharmony_ci case IDirectory::Entry::Type::FILE: { 5068bf80f4bSopenharmony_ci HandleVertexInputDeclarationFile(currentPath + entry.name, entry); 5078bf80f4bSopenharmony_ci break; 5088bf80f4bSopenharmony_ci } 5098bf80f4bSopenharmony_ci case IDirectory::Entry::Type::DIRECTORY: { 5108bf80f4bSopenharmony_ci PLUGIN_LOG_I("recursive vertex input declarations directories not supported"); 5118bf80f4bSopenharmony_ci break; 5128bf80f4bSopenharmony_ci } 5138bf80f4bSopenharmony_ci } 5148bf80f4bSopenharmony_ci } 5158bf80f4bSopenharmony_ci} 5168bf80f4bSopenharmony_ci 5178bf80f4bSopenharmony_ciRenderHandleReference ShaderLoader::CreateVertexInputDeclaration(const VertexInputDeclarationLoader& loader) 5188bf80f4bSopenharmony_ci{ 5198bf80f4bSopenharmony_ci const string_view uri = loader.GetUri(); 5208bf80f4bSopenharmony_ci VertexInputDeclarationView dataView = loader.GetVertexInputDeclarationView(); 5218bf80f4bSopenharmony_ci return shaderMgr_.CreateVertexInputDeclaration({ uri, dataView }); 5228bf80f4bSopenharmony_ci} 5238bf80f4bSopenharmony_ci 5248bf80f4bSopenharmony_civoid ShaderLoader::LoadPipelineLayouts(const string_view currentPath, const IDirectory& directory) 5258bf80f4bSopenharmony_ci{ 5268bf80f4bSopenharmony_ci for (auto const& entry : directory.GetEntries()) { 5278bf80f4bSopenharmony_ci switch (entry.type) { 5288bf80f4bSopenharmony_ci default: 5298bf80f4bSopenharmony_ci case IDirectory::Entry::Type::UNKNOWN: 5308bf80f4bSopenharmony_ci break; 5318bf80f4bSopenharmony_ci case IDirectory::Entry::Type::FILE: { 5328bf80f4bSopenharmony_ci HandlePipelineLayoutFile(currentPath + entry.name, entry); 5338bf80f4bSopenharmony_ci break; 5348bf80f4bSopenharmony_ci } 5358bf80f4bSopenharmony_ci case IDirectory::Entry::Type::DIRECTORY: { 5368bf80f4bSopenharmony_ci PLUGIN_LOG_I("recursive pipeline layout directories not supported"); 5378bf80f4bSopenharmony_ci break; 5388bf80f4bSopenharmony_ci } 5398bf80f4bSopenharmony_ci } 5408bf80f4bSopenharmony_ci } 5418bf80f4bSopenharmony_ci} 5428bf80f4bSopenharmony_ci 5438bf80f4bSopenharmony_ciRenderHandleReference ShaderLoader::CreatePipelineLayout(const PipelineLayoutLoader& loader) 5448bf80f4bSopenharmony_ci{ 5458bf80f4bSopenharmony_ci const string_view uri = loader.GetUri(); 5468bf80f4bSopenharmony_ci const PipelineLayout& pipelineLayout = loader.GetPipelineLayout(); 5478bf80f4bSopenharmony_ci return shaderMgr_.CreatePipelineLayout({ uri, pipelineLayout }); 5488bf80f4bSopenharmony_ci} 5498bf80f4bSopenharmony_ciRENDER_END_NAMESPACE() 550