• 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 "shader_data_loader.h"
17 
18 #include <algorithm>
19 #include <cctype>
20 #include <charconv>
21 #include <locale>
22 
23 #include <base/containers/string.h>
24 #include <base/util/uid_util.h>
25 #include <core/io/intf_file_manager.h>
26 #include <core/namespace.h>
27 
28 #include "device/shader_manager.h"
29 #include "json_util.h"
30 #include "shader_state_loader.h"
31 #include "shader_state_loader_util.h"
32 #include "util/log.h"
33 
34 using namespace BASE_NS;
35 using namespace CORE_NS;
36 
37 RENDER_BEGIN_NAMESPACE()
38 namespace {
39 constexpr size_t VERSION_SIZE { 5u };
40 constexpr uint32_t VERSION_MAJOR { 22u };
41 
LoadState(const json::value & jsonData,GraphicsState & graphicsState,ShaderDataLoader::LoadResult & result)42 void LoadState(const json::value& jsonData, GraphicsState& graphicsState, ShaderDataLoader::LoadResult& result)
43 {
44     {
45         ShaderStateLoaderUtil::ShaderStateResult ssr;
46         ShaderStateLoaderUtil::ParseSingleState(jsonData, ssr);
47         if (ssr.res.success && (ssr.states.states.size() == 1u)) {
48             graphicsState = move(ssr.states.states[0u]);
49         } else {
50             result.error += ssr.res.error;
51         }
52     }
53 }
54 
LoadSingleShaderVariant(const json::value & jsonData,ShaderDataLoader::ShaderVariant & data,ShaderDataLoader::LoadResult & result)55 void LoadSingleShaderVariant(
56     const json::value& jsonData, ShaderDataLoader::ShaderVariant& data, ShaderDataLoader::LoadResult& result)
57 {
58     SafeGetJsonValue(jsonData, "renderSlotDefaultShader", result.error, data.renderSlotDefaultShader);
59     SafeGetJsonValue(jsonData, "variantName", result.error, data.variantName);
60     SafeGetJsonValue(jsonData, "vert", result.error, data.vertexShader);
61     SafeGetJsonValue(jsonData, "frag", result.error, data.fragmentShader);
62     SafeGetJsonValue(jsonData, "compute", result.error, data.computeShader);
63     if (data.computeShader.empty()) {
64         SafeGetJsonValue(jsonData, "comp", result.error, data.computeShader);
65     }
66     {
67         SafeGetJsonValue(jsonData, "slot", result.error, data.renderSlot);
68         SafeGetJsonValue(jsonData, "renderSlot", result.error, data.renderSlot);
69     }
70     SafeGetJsonValue(jsonData, "vertexInputDeclaration", result.error, data.vertexInputDeclaration);
71     SafeGetJsonValue(jsonData, "pipelineLayout", result.error, data.pipelineLayout);
72 
73     if (result.success) {
74         if (const json::value* iter = jsonData.find("state"); iter) {
75             LoadState(*iter, data.graphicsState, result);
76         }
77         if (const json::value* iter = jsonData.find("materialMetadata"); iter) {
78             data.materialMetadata = json::to_string(*iter);
79         }
80     }
81 }
82 
LoadFunc(const json::value & jsonData,string & baseShader,vector<ShaderDataLoader::ShaderVariant> & shaderVariants)83 ShaderDataLoader::LoadResult LoadFunc(
84     const json::value& jsonData, string& baseShader, vector<ShaderDataLoader::ShaderVariant>& shaderVariants)
85 {
86     ShaderDataLoader::LoadResult result;
87     // compatibility check with early out
88     {
89         string ver;
90         string type;
91         uint32_t verMajor { ~0u };
92         uint32_t verMinor { ~0u };
93         if (const json::value* iter = jsonData.find("compatibility_info"); iter) {
94             SafeGetJsonValue(*iter, "type", result.error, type);
95             SafeGetJsonValue(*iter, "version", result.error, ver);
96             if (ver.size() == VERSION_SIZE) {
97                 if (const auto delim = ver.find('.'); delim != string::npos) {
98                     std::from_chars(ver.data(), ver.data() + delim, verMajor);
99                     std::from_chars(ver.data() + delim + 1, ver.data() + ver.size(), verMinor);
100                 }
101             }
102         }
103         if ((type != "shader") || (verMajor != VERSION_MAJOR)) {
104             result.error += "invalid shader type (" + type + ") and/or version (" + ver + ").";
105             result.success = false;
106             return result;
107         }
108     }
109 
110 #if (RENDER_VALIDATION_ENABLED == 1)
111     {
112         string name;
113         SafeGetJsonValue(jsonData, "name", result.error, name);
114         if (!name.empty()) {
115             PLUGIN_LOG_W("RENDER_VALIDATION: name (%s) not supported in shader json", name.c_str());
116         }
117     }
118 #endif
119     // base shader
120     SafeGetJsonValue(jsonData, "baseShader", result.error, baseShader);
121 
122     // check all variants or use (older) single variant style
123     if (const json::value* iter = jsonData.find("shaders"); iter) {
124         if (iter->is_array()) {
125             for (const auto& variantRef : iter->array_) {
126                 ShaderDataLoader::ShaderVariant sv;
127                 LoadSingleShaderVariant(variantRef, sv, result);
128                 if (result.error.empty()) {
129                     shaderVariants.emplace_back(move(sv));
130                 }
131             }
132         }
133     } else {
134         ShaderDataLoader::ShaderVariant sv;
135         LoadSingleShaderVariant(jsonData, sv, result);
136         if (result.error.empty()) {
137             shaderVariants.emplace_back(move(sv));
138         }
139     }
140 
141     result.success = result.error.empty();
142     return result;
143 }
144 } // namespace
145 
GetUri() const146 string_view ShaderDataLoader::GetUri() const
147 {
148     return uri_;
149 }
150 
GetBaseShader() const151 string_view ShaderDataLoader::GetBaseShader() const
152 {
153     return baseShader_;
154 }
155 
GetShaderVariants() const156 array_view<const ShaderDataLoader::ShaderVariant> ShaderDataLoader::GetShaderVariants() const
157 {
158     return shaderVariants_;
159 }
160 
Load(IFileManager & fileManager,const string_view uri)161 ShaderDataLoader::LoadResult ShaderDataLoader::Load(IFileManager& fileManager, const string_view uri)
162 {
163     uri_ = uri;
164     IFile::Ptr file = fileManager.OpenFile(uri);
165     if (!file) {
166         PLUGIN_LOG_D("Error loading '%s'", string(uri).c_str());
167         return LoadResult("Failed to open file.");
168     }
169 
170     const uint64_t byteLength = file->GetLength();
171 
172     string raw;
173     raw.resize(static_cast<size_t>(byteLength));
174 
175     if (file->Read(raw.data(), byteLength) != byteLength) {
176         PLUGIN_LOG_D("Error loading '%s'", string(uri).c_str());
177         return LoadResult("Failed to read file.");
178     }
179 
180     return Load(move(raw));
181 }
182 
Load(string && jsonData)183 ShaderDataLoader::LoadResult ShaderDataLoader::Load(string&& jsonData)
184 {
185     LoadResult result;
186     const auto json = json::parse(jsonData.data());
187     if (json) {
188         result = RENDER_NS::LoadFunc(json, baseShader_, shaderVariants_);
189     } else {
190         result.success = false;
191         result.error = "Invalid json file.";
192     }
193 
194     return result;
195 }
196 RENDER_END_NAMESPACE()
197