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