• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "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(const string_view fullFilename)65 ShaderDataFileType GetShaderDataFileType(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(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 
HandleShaderFile(const string_view fullFileName,const IDirectory::Entry & entry,const bool forceReload)160 void ShaderLoader::HandleShaderFile(
161     const string_view fullFileName, const IDirectory::Entry& entry, const bool forceReload)
162 {
163     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER].data(), entry.name)) {
164         ShaderDataLoader loader;
165         const auto result = loader.Load(fileManager_, fullFileName);
166         if (result.success) {
167             auto const handle = CreateShader(loader, forceReload);
168 #if (RENDER_DEV_ENABLED == 1)
169             const auto shaderVariants = loader.GetShaderVariants();
170             for (const auto& shaderVariant : shaderVariants) {
171                 // Dev related book-keeping for reloading of spv files
172                 auto const handleType = handle.GetHandleType();
173                 string compShader {};
174                 string vertShader {};
175                 string fragShader {};
176                 for (const auto& spvInfo : shaderVariant.shaders) {
177                     switch (spvInfo.shaderType) {
178                         case CORE_SHADER_STAGE_COMPUTE_BIT:
179                             compShader = spvInfo.shaderSpvPath;
180                             break;
181                         case CORE_SHADER_STAGE_FRAGMENT_BIT:
182                             fragShader = spvInfo.shaderSpvPath;
183                             break;
184                         case CORE_SHADER_STAGE_VERTEX_BIT:
185                             vertShader = spvInfo.shaderSpvPath;
186                             break;
187                         default:
188                             break;
189                     }
190                 }
191                 if ((!compShader.empty()) && (handleType == RenderHandleType::COMPUTE_SHADER_STATE_OBJECT)) {
192                     auto& ref = fileToShaderNames_[move(compShader)];
193                     ref.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT;
194                     ref.shaderNames.emplace_back(fullFileName);
195                 } else if ((!vertShader.empty()) && (!fragShader.empty()) &&
196                            (handleType == RenderHandleType::SHADER_STATE_OBJECT)) {
197                     auto& refVert = fileToShaderNames_[move(vertShader)];
198                     refVert.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT;
199                     refVert.shaderNames.emplace_back(fullFileName);
200                     auto& refFrag = fileToShaderNames_[move(fragShader)];
201                     refFrag.shaderStageFlags = ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT;
202                     refFrag.shaderNames.emplace_back(fullFileName);
203                 }
204             }
205 #endif
206         } else {
207             PLUGIN_LOG_E("unable to load shader json %s : %s", fullFileName.data(), result.error.c_str());
208         }
209     }
210 }
211 
HandleShaderStateFile(const string_view fullFileName,const IDirectory::Entry & entry)212 void ShaderLoader::HandleShaderStateFile(const string_view fullFileName, const IDirectory::Entry& entry)
213 {
214     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::SHADER_STATE].data(), entry.name)) {
215         ShaderStateLoader loader;
216         const auto result = loader.Load(fileManager_, fullFileName);
217         if (result.success) {
218             CreateShaderStates(loader.GetUri(), loader.GetGraphicsStateVariantData(), loader.GetGraphicsStates());
219         } else {
220             PLUGIN_LOG_E("unable to load shader state json %s : %s", fullFileName.data(), result.error.c_str());
221         }
222     }
223 }
224 
HandlePipelineLayoutFile(const string_view fullFileName,const IDirectory::Entry & entry)225 void ShaderLoader::HandlePipelineLayoutFile(const string_view fullFileName, const IDirectory::Entry& entry)
226 {
227     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::PIPELINE_LAYOUT].data(), entry.name)) {
228         PipelineLayoutLoader loader;
229         const auto result = loader.Load(fileManager_, fullFileName);
230         if (result.success) {
231             auto const handle = CreatePipelineLayout(loader);
232             if (!handle) {
233                 PLUGIN_LOG_E(
234                     "pipeline layout could not be created (%s) (%s)", fullFileName.data(), loader.GetUri().data());
235             }
236         } else {
237             PLUGIN_LOG_E("unable to load pipeline layout json %s : %s", fullFileName.data(), result.error.c_str());
238         }
239     }
240 }
241 
HandleVertexInputDeclarationFile(const string_view fullFileName,const IDirectory::Entry & entry)242 void ShaderLoader::HandleVertexInputDeclarationFile(const string_view fullFileName, const IDirectory::Entry& entry)
243 {
244     if (HasExtension(ShaderDataFileExtensions[ShaderDataFileType::VERTEX_INPUT_DECLARATION].data(), entry.name)) {
245         VertexInputDeclarationLoader loader;
246         const auto result = loader.Load(fileManager_, fullFileName);
247         if (result.success) {
248             auto const vidName = loader.GetUri();
249             auto const handle = CreateVertexInputDeclaration(loader);
250             if (!handle) {
251                 PLUGIN_LOG_E(
252                     "vertex input declaration could not be created (%s) (%s)", fullFileName.data(), vidName.data());
253             }
254         } else {
255             PLUGIN_LOG_E(
256                 "unable to load vertex input declaration json %s : %s", fullFileName.data(), result.error.c_str());
257         }
258     }
259 }
260 
RecurseDirectory(const string_view currentPath,const IDirectory & directory)261 void ShaderLoader::RecurseDirectory(const string_view currentPath, const IDirectory& directory)
262 {
263     for (auto const& entry : directory.GetEntries()) {
264         switch (entry.type) {
265             default:
266             case IDirectory::Entry::Type::UNKNOWN:
267                 break;
268             case IDirectory::Entry::Type::FILE: {
269                 // does not force the shader module re-creations
270                 HandleShaderFile(currentPath + entry.name, entry, false);
271                 break;
272             }
273             case IDirectory::Entry::Type::DIRECTORY: {
274                 if (entry.name == "." || entry.name == "..") {
275                     continue;
276                 }
277                 auto nextDirectory = currentPath + entry.name + '/';
278                 auto dir = fileManager_.OpenDirectory(nextDirectory);
279                 if (dir) {
280                     RecurseDirectory(nextDirectory, *dir);
281                 }
282                 break;
283             }
284         }
285     }
286 }
287 
LoadShaderFile(const string_view shader,const ShaderStageFlags stageBits)288 ShaderLoader::ShaderFile ShaderLoader::LoadShaderFile(const string_view shader, const ShaderStageFlags stageBits)
289 {
290     ShaderLoader::ShaderFile info;
291     IFile::Ptr shaderFile;
292     switch (type_) {
293         case DeviceBackendType::VULKAN:
294             shaderFile = fileManager_.OpenFile(shader);
295             break;
296         case DeviceBackendType::OPENGLES:
297             shaderFile = fileManager_.OpenFile(shader + ".gles");
298             break;
299         case DeviceBackendType::OPENGL:
300             shaderFile = fileManager_.OpenFile(shader + ".gl");
301             break;
302         default:
303             break;
304     }
305     if (shaderFile) {
306         info.data = ReadFile(*shaderFile);
307 
308         if (IFile::Ptr reflectionFile = fileManager_.OpenFile(shader + ".lsb"); reflectionFile) {
309             info.reflectionData = ReadFile(*reflectionFile);
310         }
311         info.info = { stageBits, info.data, ShaderReflectionData { info.reflectionData } };
312     } else {
313         PLUGIN_LOG_E("shader file not found (%s)", shader.data());
314     }
315     return info;
316 }
317 
CreateComputeShader(const ShaderDataLoader & dataLoader,const bool forceReload)318 RenderHandleReference ShaderLoader::CreateComputeShader(const ShaderDataLoader& dataLoader, const bool forceReload)
319 {
320     RenderHandleReference firstShaderVariantRhr;
321     const array_view<const IShaderManager::ShaderVariant> shaderVariants = dataLoader.GetShaderVariants();
322     for (const auto& svRef : shaderVariants) {
323         string_view computeShader {};
324         for (const auto& shader : svRef.shaders) {
325             switch (shader.shaderType) {
326                 case CORE_SHADER_STAGE_COMPUTE_BIT:
327                     computeShader = shader.shaderSpvPath;
328                     break;
329                 case CORE_SHADER_STAGE_FRAGMENT_BIT:
330                 case CORE_SHADER_STAGE_VERTEX_BIT:
331                 default:
332                     break;
333             }
334         }
335 
336         uint32_t index = INVALID_SM_INDEX;
337         if (!forceReload) {
338             index = shaderMgr_.GetShaderModuleIndex(computeShader);
339         }
340         if (index == INVALID_SM_INDEX) {
341             const auto shaderFile = LoadShaderFile(computeShader, ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT);
342             if (!shaderFile.data.empty()) {
343                 index = shaderMgr_.CreateShaderModule(computeShader, shaderFile.info);
344             } else {
345                 PLUGIN_LOG_E("shader file not found (%s)", computeShader.data());
346             }
347         }
348         if (index != INVALID_SM_INDEX) {
349             const string_view uri = dataLoader.GetUri();
350             const string_view baseCategory = dataLoader.GetBaseCategory();
351             const string_view variantName = svRef.variantName;
352             const string_view displayName = svRef.displayName;
353             const string_view pipelineLayout = svRef.pipelineLayout;
354             const string_view renderSlot = svRef.renderSlot;
355             const string_view shaderFileStr = svRef.shaderFileStr;
356             const string_view matMetadataStr = svRef.materialMetadata;
357             const uint32_t rsId = shaderMgr_.CreateRenderSlotId(renderSlot);
358             const uint32_t catId = shaderMgr_.CreateCategoryId(baseCategory);
359             const uint32_t plIndex =
360                 (pipelineLayout.empty())
361                     ? INVALID_SM_INDEX
362                     : RenderHandleUtil::GetIndexPart(shaderMgr_.GetPipelineLayoutHandle(pipelineLayout).GetHandle());
363             // if many variants, the first is shader created without variant name
364             // it will have additional name for searching though
365             RenderHandleReference rhr;
366             if (!firstShaderVariantRhr) {
367                 // NOTE: empty variant name
368                 rhr = shaderMgr_.Create(
369                     ComputeShaderCreateData { uri, rsId, catId, plIndex, index, shaderFileStr, matMetadataStr },
370                     { {}, displayName }, { svRef.ownBaseShader, svRef.addBaseShader });
371                 firstShaderVariantRhr = rhr;
372                 // add additional fullname with variant for the base shader
373                 if (!variantName.empty()) {
374                     shaderMgr_.AddAdditionalNameForHandle(rhr, uri);
375                 }
376             } else {
377                 rhr = shaderMgr_.Create(
378                     ComputeShaderCreateData { uri, rsId, catId, plIndex, index, shaderFileStr, matMetadataStr },
379                     { variantName, displayName }, { svRef.ownBaseShader, svRef.addBaseShader });
380             }
381             if (svRef.renderSlotDefaultShader) {
382                 shaderMgr_.SetRenderSlotData({ rsId, rhr, {}, {}, {} });
383             }
384         } else {
385             PLUGIN_LOG_E("Failed to load shader : %s", computeShader.data());
386         }
387     }
388     return firstShaderVariantRhr;
389 }
390 
CreateGraphicsShader(const ShaderDataLoader & dataLoader,const bool forceReload)391 RenderHandleReference ShaderLoader::CreateGraphicsShader(const ShaderDataLoader& dataLoader, const bool forceReload)
392 {
393     RenderHandleReference firstShaderVariantRhr;
394     const array_view<const IShaderManager::ShaderVariant> shaderVariants = dataLoader.GetShaderVariants();
395     for (const auto& svRef : shaderVariants) {
396         string_view vertexShader {};
397         string_view fragmentShader {};
398 
399         for (const auto& shader : svRef.shaders) {
400             switch (shader.shaderType) {
401                 case CORE_SHADER_STAGE_VERTEX_BIT:
402                     vertexShader = shader.shaderSpvPath;
403                     break;
404                 case CORE_SHADER_STAGE_FRAGMENT_BIT:
405                     fragmentShader = shader.shaderSpvPath;
406                     break;
407                 case CORE_SHADER_STAGE_COMPUTE_BIT:
408                 default:
409                     break;
410             }
411         }
412 
413         uint32_t vertIndex = (forceReload) ? INVALID_SM_INDEX : shaderMgr_.GetShaderModuleIndex(vertexShader);
414         if (vertIndex == INVALID_SM_INDEX) {
415             const auto shaderFile = LoadShaderFile(vertexShader, ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT);
416             if (!shaderFile.data.empty()) {
417                 vertIndex = shaderMgr_.CreateShaderModule(vertexShader, shaderFile.info);
418             }
419         }
420         uint32_t fragIndex = (forceReload) ? INVALID_SM_INDEX : shaderMgr_.GetShaderModuleIndex(fragmentShader);
421         if (fragIndex == INVALID_SM_INDEX) {
422             const auto shaderFile = LoadShaderFile(fragmentShader, ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT);
423             if (!shaderFile.data.empty()) {
424                 fragIndex = shaderMgr_.CreateShaderModule(fragmentShader, shaderFile.info);
425             }
426         }
427         if ((vertIndex != INVALID_SM_INDEX) && (fragIndex != INVALID_SM_INDEX)) {
428             const string_view uri = dataLoader.GetUri();
429             // creating the default graphics state with full name
430             const string fullName = uri + svRef.variantName;
431             // default graphics state is created beforehand
432             const RenderHandleReference defaultGfxState = shaderMgr_.CreateGraphicsState(
433                 { fullName, svRef.graphicsState }, { svRef.renderSlot, {}, {}, {}, svRef.stateFlags });
434             const uint32_t rsId = shaderMgr_.CreateRenderSlotId(svRef.renderSlot);
435             const uint32_t catId = shaderMgr_.CreateCategoryId(dataLoader.GetBaseCategory());
436             const uint32_t plIndex = svRef.pipelineLayout.empty()
437                                          ? INVALID_SM_INDEX
438                                          : RenderHandleUtil::GetIndexPart(
439                                                shaderMgr_.GetPipelineLayoutHandle(svRef.pipelineLayout).GetHandle());
440             const uint32_t vidIndex =
441                 svRef.vertexInputDeclaration.empty()
442                     ? INVALID_SM_INDEX
443                     : RenderHandleUtil::GetIndexPart(
444                           shaderMgr_.GetVertexInputDeclarationHandle(svRef.vertexInputDeclaration).GetHandle());
445             const uint32_t stateIndex = RenderHandleUtil::GetIndexPart(defaultGfxState.GetHandle());
446             const string_view shaderStr = svRef.shaderFileStr;
447             const string_view matMeta = svRef.materialMetadata;
448             // if many variants, the first is shader created without variant name
449             // it will have additional name for searching though
450             RenderHandleReference rhr;
451             if (!firstShaderVariantRhr) {
452                 // NOTE: empty variant name
453                 rhr = shaderMgr_.Create(
454                     { uri, rsId, catId, vidIndex, plIndex, stateIndex, vertIndex, fragIndex, shaderStr, matMeta },
455                     { {}, svRef.displayName }, { svRef.ownBaseShader, svRef.addBaseShader });
456                 firstShaderVariantRhr = rhr;
457                 // add additional fullname with variant for the base shader
458                 if (!svRef.variantName.empty()) {
459                     shaderMgr_.AddAdditionalNameForHandle(firstShaderVariantRhr, fullName);
460                 }
461             } else {
462                 rhr = shaderMgr_.Create(
463                     { uri, rsId, catId, vidIndex, plIndex, stateIndex, vertIndex, fragIndex, shaderStr, matMeta },
464                     { svRef.variantName, svRef.displayName }, { svRef.ownBaseShader, svRef.addBaseShader });
465             }
466             if (svRef.renderSlotDefaultShader) {
467                 shaderMgr_.SetRenderSlotData({ rsId, rhr, {}, {}, {} });
468             }
469         } else {
470             PLUGIN_LOG_E("Failed to load shader : %s %s", vertexShader.data(), fragmentShader.data());
471         }
472     }
473     return firstShaderVariantRhr;
474 }
475 
CreateShader(const ShaderDataLoader & dataLoader,const bool forceReload)476 RenderHandleReference ShaderLoader::CreateShader(const ShaderDataLoader& dataLoader, const bool forceReload)
477 {
478     const array_view<const IShaderManager::ShaderVariant> shaderVariants = dataLoader.GetShaderVariants();
479     if (shaderVariants.empty()) {
480         return {};
481     }
482 
483     string_view compShader {};
484     string_view vertShader {};
485     string_view fragShader {};
486 
487     for (const auto& shader : shaderVariants[0].shaders) {
488         switch (shader.shaderType) {
489             case CORE_SHADER_STAGE_VERTEX_BIT:
490                 vertShader = shader.shaderSpvPath;
491                 break;
492             case CORE_SHADER_STAGE_FRAGMENT_BIT:
493                 fragShader = shader.shaderSpvPath;
494                 break;
495             case CORE_SHADER_STAGE_COMPUTE_BIT:
496                 compShader = shader.shaderSpvPath;
497                 break;
498         }
499     }
500 
501     if (!compShader.empty()) {
502         return CreateComputeShader(dataLoader, forceReload);
503     } else {
504         if (!vertShader.empty() && !fragShader.empty()) {
505             return CreateGraphicsShader(dataLoader, forceReload);
506         }
507     }
508     return {};
509 }
510 
LoadShaderStates(const string_view currentPath,const IDirectory & directory)511 void ShaderLoader::LoadShaderStates(const string_view currentPath, const IDirectory& directory)
512 {
513     for (auto const& entry : directory.GetEntries()) {
514         switch (entry.type) {
515             default:
516             case IDirectory::Entry::Type::UNKNOWN:
517                 break;
518             case IDirectory::Entry::Type::FILE: {
519                 HandleShaderStateFile(currentPath + entry.name, entry);
520                 break;
521             }
522             case IDirectory::Entry::Type::DIRECTORY: {
523                 PLUGIN_LOG_I("recursive vertex input declarations directories not supported");
524                 break;
525             }
526         }
527     }
528 }
529 
CreateShaderStates(const string_view uri,const array_view<const IShaderManager::ShaderStateLoaderVariantData> & variantData,const array_view<const GraphicsState> & states)530 void ShaderLoader::CreateShaderStates(const string_view uri,
531     const array_view<const IShaderManager::ShaderStateLoaderVariantData>& variantData,
532     const array_view<const GraphicsState>& states)
533 {
534     for (size_t stateIdx = 0; stateIdx < states.size(); ++stateIdx) {
535         const ShaderManager::GraphicsStateCreateInfo createInfo { uri, states[stateIdx] };
536         const auto& variant = variantData[stateIdx];
537         const ShaderManager::GraphicsStateVariantCreateInfo variantCreateInfo { variant.renderSlot, variant.variantName,
538             variant.baseShaderState, variant.baseVariantName, variant.stateFlags };
539         const RenderHandleReference handle = shaderMgr_.CreateGraphicsState(createInfo, variantCreateInfo);
540         if (variant.renderSlotDefaultState && (!variant.renderSlot.empty())) {
541             const uint32_t renderSlotId = shaderMgr_.GetRenderSlotId(variant.renderSlot);
542             shaderMgr_.SetRenderSlotData({ renderSlotId, {}, handle, {}, {} });
543         }
544         if (!handle) {
545             PLUGIN_LOG_E(
546                 "error creating graphics state (name: %s, variant: %s)", uri.data(), variant.variantName.data());
547         }
548     }
549 }
550 
LoadVids(const string_view currentPath,const IDirectory & directory)551 void ShaderLoader::LoadVids(const string_view currentPath, const IDirectory& directory)
552 {
553     for (auto const& entry : directory.GetEntries()) {
554         switch (entry.type) {
555             default:
556             case IDirectory::Entry::Type::UNKNOWN:
557                 break;
558             case IDirectory::Entry::Type::FILE: {
559                 HandleVertexInputDeclarationFile(currentPath + entry.name, entry);
560                 break;
561             }
562             case IDirectory::Entry::Type::DIRECTORY: {
563                 PLUGIN_LOG_I("recursive vertex input declarations directories not supported");
564                 break;
565             }
566         }
567     }
568 }
569 
CreateVertexInputDeclaration(const VertexInputDeclarationLoader & loader)570 RenderHandleReference ShaderLoader::CreateVertexInputDeclaration(const VertexInputDeclarationLoader& loader)
571 {
572     const string_view uri = loader.GetUri();
573     VertexInputDeclarationView dataView = loader.GetVertexInputDeclarationView();
574     uint32_t renderSlotId = ~0U;
575     // handles only render slot data if default
576     const bool defaultRenderSlot = loader.GetDefaultRenderSlot();
577     if (defaultRenderSlot) {
578         renderSlotId = shaderMgr_.CreateRenderSlotId(loader.GetRenderSlot());
579     }
580     return shaderMgr_.CreateVertexInputDeclaration({ uri, dataView, renderSlotId, defaultRenderSlot });
581 }
582 
LoadPipelineLayouts(const string_view currentPath,const IDirectory & directory)583 void ShaderLoader::LoadPipelineLayouts(const string_view currentPath, const IDirectory& directory)
584 {
585     for (auto const& entry : directory.GetEntries()) {
586         switch (entry.type) {
587             default:
588             case IDirectory::Entry::Type::UNKNOWN:
589                 break;
590             case IDirectory::Entry::Type::FILE: {
591                 HandlePipelineLayoutFile(currentPath + entry.name, entry);
592                 break;
593             }
594             case IDirectory::Entry::Type::DIRECTORY: {
595                 PLUGIN_LOG_I("recursive pipeline layout directories not supported");
596                 break;
597             }
598         }
599     }
600 }
601 
CreatePipelineLayout(const PipelineLayoutLoader & loader)602 RenderHandleReference ShaderLoader::CreatePipelineLayout(const PipelineLayoutLoader& loader)
603 {
604     const string_view uri = loader.GetUri();
605     const PipelineLayout& pipelineLayout = loader.GetPipelineLayout();
606     // handles only render slot data if default
607     const bool defaultRenderSlot = loader.GetDefaultRenderSlot();
608     uint32_t renderSlotId = { ~0U };
609     if (defaultRenderSlot) {
610         renderSlotId = shaderMgr_.CreateRenderSlotId(loader.GetRenderSlot());
611     }
612     return shaderMgr_.CreatePipelineLayout({ uri, pipelineLayout, renderSlotId, defaultRenderSlot });
613 }
614 
615 RENDER_END_NAMESPACE()
616