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