• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "loader/shader_loader.h"
17 
18 #include <cstring>
19 #include <set>
20 
21 #include <base/containers/array_view.h>
22 #include <base/containers/vector.h>
23 #include <core/io/intf_file_manager.h>
24 #include <render/device/gpu_resource_desc.h>
25 #include <render/device/pipeline_layout_desc.h>
26 #include <render/namespace.h>
27 
28 #include "device/shader_manager.h"
29 #include "loader/json_util.h"
30 #include "loader/pipeline_layout_loader.h"
31 #include "loader/shader_data_loader.h"
32 #include "loader/shader_state_loader.h"
33 #include "loader/vertex_input_declaration_loader.h"
34 #include "util/log.h"
35 
36 using namespace BASE_NS;
37 using namespace CORE_NS;
38 
39 RENDER_BEGIN_NAMESPACE()
40 namespace {
41 enum ShaderDataFileType : uint32_t {
42     UNDEFINED = 0,
43     SHADER = 1,
44     SHADER_STATE = 2,
45     VERTEX_INPUT_DECLARATION = 3,
46     PIPELINE_LAYOUT = 4,
47 };
48 
49 constexpr string_view ShaderDataFileExtensions[] {
50     "",
51     ".shader",
52     ".shadergs",
53     ".shadervid",
54     ".shaderpl",
55 };
56 
HasExtension(const char * ext,const string_view fileUri)57 bool HasExtension(const char* ext, const string_view fileUri)
58 {
59     if (auto const pos = fileUri.rfind(ext); pos != string_view::npos) {
60         return std::strlen(ext) == (fileUri.length() - pos);
61     }
62     return false;
63 }
64 
GetShaderDataFileType(IFileManager & fileMgr,const string_view fullFilename)65 ShaderDataFileType GetShaderDataFileType(IFileManager& fileMgr, const string_view fullFilename)
66 {
67     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER].data(), fullFilename)) {
68         return ShaderDataFileType::SHADER;
69     } else if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER_STATE].data(), fullFilename)) {
70         return ShaderDataFileType::SHADER_STATE;
71     } else if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::PIPELINE_LAYOUT].data(), fullFilename)) {
72         return ShaderDataFileType::PIPELINE_LAYOUT;
73     } else if (HasExtension(
74                    ShaderDataFileExtensions[ShaderDataFileType::VERTEX_INPUT_DECLARATION].data(), fullFilename)) {
75         return ShaderDataFileType::VERTEX_INPUT_DECLARATION;
76     }
77     return ShaderDataFileType::UNDEFINED;
78 }
79 
ReadFile(IFile & file)80 vector<uint8_t> ReadFile(IFile& file)
81 {
82     auto fileData = vector<uint8_t>(static_cast<std::size_t>(file.GetLength()));
83     file.Read(fileData.data(), fileData.size());
84     return fileData;
85 }
86 } // namespace
87 
ShaderLoader(IFileManager & fileManager,ShaderManager & shaderManager,const DeviceBackendType type)88 ShaderLoader::ShaderLoader(IFileManager& fileManager, ShaderManager& shaderManager, const DeviceBackendType type)
89     : fileManager_(fileManager), shaderMgr_(shaderManager), type_(type)
90 {}
91 
Load(const ShaderManager::ShaderFilePathDesc & desc)92 void ShaderLoader::Load(const ShaderManager::ShaderFilePathDesc& desc)
93 {
94     if (!desc.shaderStatePath.empty()) {
95         auto const shaderStatesPath = fileManager_.OpenDirectory(desc.shaderStatePath);
96         if (shaderStatesPath) {
97             LoadShaderStates(desc.shaderStatePath, *shaderStatesPath);
98         } else {
99             PLUGIN_LOG_W("graphics state path (%s) not found.", desc.shaderStatePath.data());
100         }
101     }
102     if (!desc.vertexInputDeclarationPath.empty()) {
103         auto const vidsPath = fileManager_.OpenDirectory(desc.vertexInputDeclarationPath);
104         if (vidsPath) {
105             LoadVids(desc.vertexInputDeclarationPath, *vidsPath);
106         } else {
107             PLUGIN_LOG_W("vertex input declaration path (%s) not found.", desc.vertexInputDeclarationPath.data());
108         }
109     }
110     if (!desc.pipelineLayoutPath.empty()) {
111         auto const pipelineLayoutsPath = fileManager_.OpenDirectory(desc.pipelineLayoutPath);
112         if (pipelineLayoutsPath) {
113             LoadPipelineLayouts(desc.pipelineLayoutPath, *pipelineLayoutsPath);
114         } else {
115             PLUGIN_LOG_W("pipeline layout path (%s) not found.", desc.pipelineLayoutPath.data());
116         }
117     }
118     if (!desc.shaderPath.empty()) {
119         auto const shadersPath = fileManager_.OpenDirectory(desc.shaderPath);
120         if (shadersPath) {
121             RecurseDirectory(desc.shaderPath, *shadersPath);
122         } else {
123             PLUGIN_LOG_W("shader path (%s) not found.", desc.shaderPath.data());
124         }
125     }
126 }
127 
LoadFile(const string_view uri,const bool forceReload)128 void ShaderLoader::LoadFile(const string_view uri, const bool forceReload)
129 {
130     const IDirectory::Entry entry = fileManager_.GetEntry(uri);
131     if (entry.type == IDirectory::Entry::FILE) {
132         // NOTE: currently there's no info within the shader json files
133         // we do type evaluation based on some key names in the json
134         const ShaderDataFileType shaderDataFileType = GetShaderDataFileType(fileManager_, uri);
135         switch (shaderDataFileType) {
136             case ShaderDataFileType::SHADER: {
137                 // Force re-loads the shader module creation
138                 HandleShaderFile(uri, entry, forceReload);
139                 break;
140             }
141             case ShaderDataFileType::SHADER_STATE: {
142                 HandleShaderStateFile(uri, entry);
143                 break;
144             }
145             case ShaderDataFileType::PIPELINE_LAYOUT: {
146                 HandlePipelineLayoutFile(uri, entry);
147                 break;
148             }
149             case ShaderDataFileType::VERTEX_INPUT_DECLARATION: {
150                 HandleVertexInputDeclarationFile(uri, entry);
151                 break;
152             }
153             default: {
154                 break;
155             }
156         }
157     }
158 }
159 
Reload(const array_view<string> & shaderSpvFiles)160 void ShaderLoader::Reload(const array_view<string>& shaderSpvFiles)
161 {
162     std::set<string> names;
163     for (auto const& file : shaderSpvFiles) {
164         ShaderStageFlags shaderStageFlags = 0;
165 #if (RENDER_DEV_ENABLED == 1)
166         // re-load only works properly with dev enabled
167         if (auto const pos = fileToShaderNames_.find(file); pos != fileToShaderNames_.end()) {
168             shaderStageFlags = pos->second.shaderStageFlags;
169             names.insert(pos->second.shaderNames.begin(), pos->second.shaderNames.end());
170         }
171 #endif
172         // re-create shader module
173         const auto shaderFile = LoadShaderFile(file, shaderStageFlags);
174         if (!shaderFile.data.empty() && (shaderStageFlags != 0)) {
175             const ShaderModuleCreateInfo moduleCreateInfo { shaderStageFlags, shaderFile.data,
176                 { shaderFile.reflectionData } };
177             shaderMgr_.CreateShaderModule(file, moduleCreateInfo);
178         }
179 #if (RENDER_VALIDATION_ENABLED == 1)
180         PLUGIN_LOG_W("RENDER_VALIDATION: cannot reload spv files due to missing shader stage flags info");
181 #endif
182     }
183 }
184 
HandleShaderFile(const string_view fullFileName,const IDirectory::Entry & entry,const bool forceReload)185 void ShaderLoader::HandleShaderFile(
186     const string_view fullFileName, const IDirectory::Entry& entry, const bool forceReload)
187 {
188     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER].data(), entry.name)) {
189         ShaderDataLoader loader;
190         const auto result = loader.Load(fileManager_, fullFileName);
191         if (result.success) {
192             auto const handle = CreateShader(loader, forceReload);
193 #if (RENDER_DEV_ENABLED == 1)
194             const auto shaderVariants = loader.GetShaderVariants();
195             for (const auto& shaderVariant : shaderVariants) {
196                 // Dev related book-keeping for reloading of spv files
197                 auto const handleType = handle.GetHandleType();
198                 if (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT) {
199                     string compShader = shaderVariant.computeShader;
200                     PLUGIN_ASSERT(!compShader.empty());
201 
202                     auto& ref = fileToShaderNames_[move(compShader)];
203                     ref.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT;
204                     ref.shaderNames.emplace_back(fullFileName);
205                 } else if (handleType == RenderHandleType::SHADER_STATE_OBJECT) {
206                     string vertShader = shaderVariant.vertexShader;
207                     string fragShader = shaderVariant.fragmentShader;
208                     PLUGIN_ASSERT_MSG(
209                         (!vertShader.empty()) && (!fragShader.empty()), "shader name: %s", fullFileName.data());
210 
211                     auto& refVert = fileToShaderNames_[move(vertShader)];
212                     refVert.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT;
213                     refVert.shaderNames.emplace_back(fullFileName);
214                     auto& refFrag = fileToShaderNames_[move(fragShader)];
215                     refFrag.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT;
216                     refFrag.shaderNames.emplace_back(fullFileName);
217                 }
218             }
219 #endif
220         } else {
221             PLUGIN_LOG_E("unable to load shader json %s : %s", fullFileName.data(), result.error.c_str());
222         }
223     }
224 }
225 
HandleShaderStateFile(const string_view fullFileName,const IDirectory::Entry & entry)226 void ShaderLoader::HandleShaderStateFile(const string_view fullFileName, const IDirectory::Entry& entry)
227 {
228     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER_STATE].data(), entry.name)) {
229         ShaderStateLoader loader;
230         const auto result = loader.Load(fileManager_, fullFileName);
231         if (result.success) {
232             CreateShaderStates(loader.GetUri(), loader.GetGraphicsStateVariantData(), loader.GetGraphicsStates());
233         } else {
234             PLUGIN_LOG_E("unable to load shader state json %s : %s", fullFileName.data(), result.error.c_str());
235         }
236     }
237 }
238 
HandlePipelineLayoutFile(const string_view fullFileName,const IDirectory::Entry & entry)239 void ShaderLoader::HandlePipelineLayoutFile(const string_view fullFileName, const IDirectory::Entry& entry)
240 {
241     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::PIPELINE_LAYOUT].data(), entry.name)) {
242         PipelineLayoutLoader loader;
243         const auto result = loader.Load(fileManager_, fullFileName);
244         if (result.success) {
245             auto const handle = CreatePipelineLayout(loader);
246             if (!handle) {
247                 PLUGIN_LOG_E(
248                     "pipeline layout could not be created (%s) (%s)", fullFileName.data(), loader.GetUri().data());
249             }
250         } else {
251             PLUGIN_LOG_E("unable to load pipeline layout json %s : %s", fullFileName.data(), result.error.c_str());
252         }
253     }
254 }
255 
HandleVertexInputDeclarationFile(const string_view fullFileName,const IDirectory::Entry & entry)256 void ShaderLoader::HandleVertexInputDeclarationFile(const string_view fullFileName, const IDirectory::Entry& entry)
257 {
258     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::VERTEX_INPUT_DECLARATION].data(), entry.name)) {
259         VertexInputDeclarationLoader loader;
260         const auto result = loader.Load(fileManager_, fullFileName);
261         if (result.success) {
262             auto const vidName = loader.GetUri();
263             auto const handle = CreateVertexInputDeclaration(loader);
264             if (!handle) {
265                 PLUGIN_LOG_E(
266                     "vertex input declaration could not be created (%s) (%s)", fullFileName.data(), vidName.data());
267             }
268         } else {
269             PLUGIN_LOG_E(
270                 "unable to load vertex input declaration json %s : %s", fullFileName.data(), result.error.c_str());
271         }
272     }
273 }
274 
RecurseDirectory(const string_view currentPath,const IDirectory & directory)275 void ShaderLoader::RecurseDirectory(const string_view currentPath, const IDirectory& directory)
276 {
277     for (auto const& entry : directory.GetEntries()) {
278         switch (entry.type) {
279             default:
280             case IDirectory::Entry::Type::UNKNOWN:
281                 break;
282             case IDirectory::Entry::Type::FILE: {
283                 // does not force the shader module re-creations
284                 HandleShaderFile(currentPath + entry.name, entry, false);
285                 break;
286             }
287             case IDirectory::Entry::Type::DIRECTORY: {
288                 if (entry.name == "." || entry.name == "..") {
289                     continue;
290                 }
291                 auto nextDirectory = currentPath + entry.name + '/';
292                 auto dir = fileManager_.OpenDirectory(nextDirectory);
293                 if (dir) {
294                     RecurseDirectory(nextDirectory, *dir);
295                 }
296                 break;
297             }
298         }
299     }
300 }
301 
LoadShaderFile(const string_view shader,const ShaderStageFlags stageBits)302 ShaderLoader::ShaderFile ShaderLoader::LoadShaderFile(const string_view shader, const ShaderStageFlags stageBits)
303 {
304     ShaderLoader::ShaderFile info;
305     IFile::Ptr shaderFile;
306     switch (type_) {
307         case DeviceBackendType::VULKAN:
308             shaderFile = fileManager_.OpenFile(shader);
309             break;
310         case DeviceBackendType::OPENGLES:
311             shaderFile = fileManager_.OpenFile(shader + ".gles");
312             break;
313         case DeviceBackendType::OPENGL:
314             shaderFile = fileManager_.OpenFile(shader + ".gl");
315             break;
316         default:
317             break;
318     }
319     if (shaderFile) {
320         info.data = ReadFile(*shaderFile);
321 
322         if (IFile::Ptr reflectionFile = fileManager_.OpenFile(shader + ".lsb"); reflectionFile) {
323             info.reflectionData = ReadFile(*reflectionFile);
324         }
325         info.info = { stageBits, info.data, { info.reflectionData } };
326     } else {
327         PLUGIN_LOG_E("shader file not found (%s)", shader.data());
328     }
329     return info;
330 }
331 
CreateComputeShader(const ShaderDataLoader & shaderDataLoader,const bool forceReload)332 RenderHandleReference ShaderLoader::CreateComputeShader(
333     const ShaderDataLoader& shaderDataLoader, const bool forceReload)
334 {
335     RenderHandleReference firstShaderVariantRhr;
336     const array_view<const ShaderDataLoader::ShaderVariant> shaderVariants = shaderDataLoader.GetShaderVariants();
337     for (const auto& shaderVariant : shaderVariants) {
338         const string_view computeShader = shaderVariant.computeShader;
339         uint32_t index = INVALID_SM_INDEX;
340         if (!forceReload) {
341             index = shaderMgr_.GetShaderModuleIndex(computeShader);
342         }
343         if (index == INVALID_SM_INDEX) {
344             const auto shaderFile = LoadShaderFile(computeShader, ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT);
345             if (!shaderFile.data.empty()) {
346                 index = shaderMgr_.CreateShaderModule(computeShader, shaderFile.info);
347             } else {
348                 PLUGIN_LOG_E("shader file not found (%s)", computeShader.data());
349             }
350         }
351         if (index != INVALID_SM_INDEX) {
352             const string_view uri = shaderDataLoader.GetUri();
353             const string_view baseShaderPath = shaderDataLoader.GetBaseShader();
354             const string_view variantName = shaderVariant.variantName;
355             const string_view pipelineLayout = shaderVariant.pipelineLayout;
356             const string_view renderSlot = shaderVariant.renderSlot;
357             const uint32_t rsId = renderSlot.empty() ? INVALID_SM_INDEX : shaderMgr_.CreateRenderSlotId(renderSlot);
358             const uint32_t plIndex =
359                 (pipelineLayout.empty())
360                     ? INVALID_SM_INDEX
361                     : RenderHandleUtil::GetIndexPart(shaderMgr_.GetPipelineLayoutHandle(pipelineLayout).GetHandle());
362             // if many variants, the first is shader created without variant name
363             // it will have additional name for searching though
364             RenderHandleReference rhr;
365             if (!firstShaderVariantRhr) {
366                 // NOTE: empty variant name
367                 rhr = shaderMgr_.Create(ComputeShaderCreateData { uri, rsId, plIndex, index }, baseShaderPath, {});
368                 firstShaderVariantRhr = rhr;
369                 // add additional fullname with variant for the base shader
370                 if (!variantName.empty()) {
371                     shaderMgr_.AddAdditionalNameForHandle(rhr, uri);
372                 }
373             } else {
374                 rhr = shaderMgr_.Create(
375                     ComputeShaderCreateData { uri, rsId, plIndex, index }, baseShaderPath, variantName);
376             }
377             if (shaderVariant.renderSlotDefaultShader) {
378                 shaderMgr_.SetRenderSlotData(rsId, rhr, {});
379             }
380         } else {
381             PLUGIN_LOG_E("Failed to load shader : %s", computeShader.data());
382         }
383     }
384     return firstShaderVariantRhr;
385 }
386 
CreateGraphicsShader(const ShaderDataLoader & shaderDataLoader,const bool forceReload)387 RenderHandleReference ShaderLoader::CreateGraphicsShader(
388     const ShaderDataLoader& shaderDataLoader, const bool forceReload)
389 {
390     RenderHandleReference firstShaderVariantRhr;
391     const array_view<const ShaderDataLoader::ShaderVariant> shaderVariants = shaderDataLoader.GetShaderVariants();
392     for (const auto& svRef : shaderVariants) {
393         const string_view vertexShader = svRef.vertexShader;
394         const string_view fragmentShader = svRef.fragmentShader;
395         uint32_t vertIndex = (forceReload) ? INVALID_SM_INDEX : shaderMgr_.GetShaderModuleIndex(vertexShader);
396         if (vertIndex == INVALID_SM_INDEX) {
397             const auto shaderFile = LoadShaderFile(vertexShader, ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT);
398             if (!shaderFile.data.empty()) {
399                 vertIndex = shaderMgr_.CreateShaderModule(vertexShader, shaderFile.info);
400             }
401         }
402         uint32_t fragIndex = (forceReload) ? INVALID_SM_INDEX : shaderMgr_.GetShaderModuleIndex(fragmentShader);
403         if (fragIndex == INVALID_SM_INDEX) {
404             const auto shaderFile = LoadShaderFile(fragmentShader, ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT);
405             if (!shaderFile.data.empty()) {
406                 fragIndex = shaderMgr_.CreateShaderModule(fragmentShader, shaderFile.info);
407             }
408         }
409         if ((vertIndex != INVALID_SM_INDEX) && (fragIndex != INVALID_SM_INDEX)) {
410             const string_view uri = shaderDataLoader.GetUri();
411             // creating the default graphics state with full name
412             const string fullName = uri + svRef.variantName;
413             // default graphics state is created beforehand
414             const RenderHandleReference defaultGfxState =
415                 shaderMgr_.CreateGraphicsState({ fullName, svRef.graphicsState }, { svRef.renderSlot, {}, {}, {} });
416             const uint32_t rsId =
417                 svRef.renderSlot.empty() ? INVALID_SM_INDEX : shaderMgr_.CreateRenderSlotId(svRef.renderSlot);
418             const uint32_t plIndex = svRef.pipelineLayout.empty()
419                                          ? INVALID_SM_INDEX
420                                          : RenderHandleUtil::GetIndexPart(
421                                                shaderMgr_.GetPipelineLayoutHandle(svRef.pipelineLayout).GetHandle());
422             const uint32_t vidIndex =
423                 svRef.vertexInputDeclaration.empty()
424                     ? INVALID_SM_INDEX
425                     : RenderHandleUtil::GetIndexPart(
426                         shaderMgr_.GetVertexInputDeclarationHandle(svRef.vertexInputDeclaration).GetHandle());
427             const uint32_t stateIndex = RenderHandleUtil::GetIndexPart(defaultGfxState.GetHandle());
428             const string_view matMeta = svRef.materialMetadata;
429             // if many variants, the first is shader created without variant name
430             // it will have additional name for searching though
431             RenderHandleReference rhr;
432             if (!firstShaderVariantRhr) {
433                 // NOTE: empty variant name
434                 rhr = shaderMgr_.Create({ uri, rsId, vidIndex, plIndex, stateIndex, vertIndex, fragIndex, matMeta },
435                     shaderDataLoader.GetBaseShader(), {});
436                 firstShaderVariantRhr = rhr;
437                 // add additional fullname with variant for the base shader
438                 if (!svRef.variantName.empty()) {
439                     shaderMgr_.AddAdditionalNameForHandle(firstShaderVariantRhr, fullName);
440                 }
441             } else {
442                 rhr = shaderMgr_.Create({ uri, rsId, vidIndex, plIndex, stateIndex, vertIndex, fragIndex, matMeta },
443                     shaderDataLoader.GetBaseShader(), svRef.variantName);
444             }
445             if (svRef.renderSlotDefaultShader) {
446                 shaderMgr_.SetRenderSlotData(rsId, rhr, {});
447             }
448         } else {
449             PLUGIN_LOG_E("Failed to load shader : %s %s", vertexShader.data(), fragmentShader.data());
450         }
451     }
452     return firstShaderVariantRhr;
453 }
454 
CreateShader(const ShaderDataLoader & shaderDataLoader,const bool forceReload)455 RenderHandleReference ShaderLoader::CreateShader(const ShaderDataLoader& shaderDataLoader, const bool forceReload)
456 {
457     const array_view<const ShaderDataLoader::ShaderVariant> shaderVariants = shaderDataLoader.GetShaderVariants();
458     if (shaderVariants.empty()) {
459         return {};
460     }
461 
462     const string_view compShader = shaderVariants[0].computeShader;
463     if (!compShader.empty()) {
464         return CreateComputeShader(shaderDataLoader, forceReload);
465     } else {
466         const string_view vertShader = shaderVariants[0].vertexShader;
467         const string_view fragShader = shaderVariants[0].fragmentShader;
468         if (!vertShader.empty() && !fragShader.empty()) {
469             return CreateGraphicsShader(shaderDataLoader, forceReload);
470         }
471     }
472     return {};
473 }
474 
LoadShaderStates(const string_view currentPath,const IDirectory & directory)475 void ShaderLoader::LoadShaderStates(const string_view currentPath, const IDirectory& directory)
476 {
477     for (auto const& entry : directory.GetEntries()) {
478         switch (entry.type) {
479             default:
480             case IDirectory::Entry::Type::UNKNOWN:
481                 break;
482             case IDirectory::Entry::Type::FILE: {
483                 HandleShaderStateFile(currentPath + entry.name, entry);
484                 break;
485             }
486             case IDirectory::Entry::Type::DIRECTORY: {
487                 PLUGIN_LOG_I("recursive vertex input declarations directories not supported");
488                 break;
489             }
490         }
491     }
492 }
493 
CreateShaderStates(const string_view uri,const array_view<const ShaderStateLoaderVariantData> & variantData,const array_view<const GraphicsState> & states)494 void ShaderLoader::CreateShaderStates(const string_view uri,
495     const array_view<const ShaderStateLoaderVariantData>& variantData, const array_view<const GraphicsState>& states)
496 {
497     for (size_t stateIdx = 0; stateIdx < states.size(); ++stateIdx) {
498         const ShaderManager::GraphicsStateCreateInfo createInfo { uri, states[stateIdx] };
499         const auto& variant = variantData[stateIdx];
500         const ShaderManager::GraphicsStateVariantCreateInfo variantCreateInfo { variant.renderSlot, variant.variantName,
501             variant.baseShaderState, variant.baseVariantName };
502         const RenderHandleReference handle = shaderMgr_.CreateGraphicsState(createInfo, variantCreateInfo);
503         if (variant.renderSlotDefaultState && (!variant.renderSlot.empty())) {
504             const uint32_t renderSlotId = shaderMgr_.GetRenderSlotId(variant.renderSlot);
505             shaderMgr_.SetRenderSlotData(renderSlotId, {}, handle);
506         }
507         if (!handle) {
508             PLUGIN_LOG_E(
509                 "error creating graphics state (name: %s, variant: %s)", uri.data(), variant.variantName.data());
510         }
511     }
512 }
513 
LoadVids(const string_view currentPath,const IDirectory & directory)514 void ShaderLoader::LoadVids(const string_view currentPath, const IDirectory& directory)
515 {
516     for (auto const& entry : directory.GetEntries()) {
517         switch (entry.type) {
518             default:
519             case IDirectory::Entry::Type::UNKNOWN:
520                 break;
521             case IDirectory::Entry::Type::FILE: {
522                 HandleVertexInputDeclarationFile(currentPath + entry.name, entry);
523                 break;
524             }
525             case IDirectory::Entry::Type::DIRECTORY: {
526                 PLUGIN_LOG_I("recursive vertex input declarations directories not supported");
527                 break;
528             }
529         }
530     }
531 }
532 
CreateVertexInputDeclaration(const VertexInputDeclarationLoader & loader)533 RenderHandleReference ShaderLoader::CreateVertexInputDeclaration(const VertexInputDeclarationLoader& loader)
534 {
535     const string_view uri = loader.GetUri();
536     VertexInputDeclarationView dataView = loader.GetVertexInputDeclarationView();
537     return shaderMgr_.CreateVertexInputDeclaration({ uri, dataView });
538 }
539 
LoadPipelineLayouts(const string_view currentPath,const IDirectory & directory)540 void ShaderLoader::LoadPipelineLayouts(const string_view currentPath, const IDirectory& directory)
541 {
542     for (auto const& entry : directory.GetEntries()) {
543         switch (entry.type) {
544             default:
545             case IDirectory::Entry::Type::UNKNOWN:
546                 break;
547             case IDirectory::Entry::Type::FILE: {
548                 HandlePipelineLayoutFile(currentPath + entry.name, entry);
549                 break;
550             }
551             case IDirectory::Entry::Type::DIRECTORY: {
552                 PLUGIN_LOG_I("recursive pipeline layout directories not supported");
553                 break;
554             }
555         }
556     }
557 }
558 
CreatePipelineLayout(const PipelineLayoutLoader & loader)559 RenderHandleReference ShaderLoader::CreatePipelineLayout(const PipelineLayoutLoader& loader)
560 {
561     const string_view uri = loader.GetUri();
562     const PipelineLayout& pipelineLayout = loader.GetPipelineLayout();
563     return shaderMgr_.CreatePipelineLayout({ uri, pipelineLayout });
564 }
565 RENDER_END_NAMESPACE()
566