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 "shader_state_loader_util.h"
17
18 #include <core/namespace.h>
19
20 #include "json_util.h"
21 #include "shader_state_loader.h"
22 #include "util/log.h"
23
24 using namespace BASE_NS;
25 using namespace CORE_NS;
26
27 RENDER_BEGIN_NAMESPACE()
28 // clang-format off
29 RENDER_JSON_SERIALIZE_ENUM(PrimitiveTopology,
30 {
31 { CORE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, nullptr }, // default
32 { CORE_PRIMITIVE_TOPOLOGY_POINT_LIST, "point_list" },
33 { CORE_PRIMITIVE_TOPOLOGY_LINE_LIST, "line_list" },
34 { CORE_PRIMITIVE_TOPOLOGY_LINE_STRIP, "line_strip" },
35 { CORE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, "triangle_list" },
36 { CORE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, "triangle_strip" },
37 { CORE_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN, "triangle_fan" },
38 { CORE_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY, "line_list_with_adjacency" },
39 { CORE_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY, "line_strip_with_adjacency" },
40 { CORE_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY, "triangle_list_with_adjacency" },
41 { CORE_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY, "triangle_strip_with_adjacency" },
42 { CORE_PRIMITIVE_TOPOLOGY_PATCH_LIST, "patch_list" },
43 })
44
45 RENDER_JSON_SERIALIZE_ENUM(PolygonMode,
46 {
47 { CORE_POLYGON_MODE_FILL, "fill" },
48 { CORE_POLYGON_MODE_LINE, "line" },
49 { CORE_POLYGON_MODE_POINT, "point" },
50 })
51
52 RENDER_JSON_SERIALIZE_ENUM(CullModeFlagBits,
53 {
54 { (CullModeFlagBits)0, nullptr },
55 { CORE_CULL_MODE_NONE, "none" },
56 { CORE_CULL_MODE_FRONT_BIT, "front" },
57 { CORE_CULL_MODE_BACK_BIT, "back" },
58 { CORE_CULL_MODE_FRONT_AND_BACK, "front_and_back" },
59 })
60
61 RENDER_JSON_SERIALIZE_ENUM(FrontFace,
62 {
63 { CORE_FRONT_FACE_COUNTER_CLOCKWISE, "counter_clockwise" },
64 { CORE_FRONT_FACE_CLOCKWISE, "clockwise" },
65 })
66
67 RENDER_JSON_SERIALIZE_ENUM(CompareOp,
68 {
69 { CORE_COMPARE_OP_NEVER, "never" },
70 { CORE_COMPARE_OP_LESS, "less" },
71 { CORE_COMPARE_OP_EQUAL, "equal" },
72 { CORE_COMPARE_OP_LESS_OR_EQUAL, "less_or_equal" },
73 { CORE_COMPARE_OP_GREATER, "greater" },
74 { CORE_COMPARE_OP_NOT_EQUAL, "not_equal" },
75 { CORE_COMPARE_OP_GREATER_OR_EQUAL, "greater_or_equal" },
76 { CORE_COMPARE_OP_ALWAYS, "always" },
77 })
78
79 RENDER_JSON_SERIALIZE_ENUM(StencilOp,
80 {
81 { CORE_STENCIL_OP_KEEP, "keep" },
82 { CORE_STENCIL_OP_ZERO, "zero" },
83 { CORE_STENCIL_OP_REPLACE, "replace" },
84 { CORE_STENCIL_OP_INCREMENT_AND_CLAMP, "increment_and_clamp" },
85 { CORE_STENCIL_OP_DECREMENT_AND_CLAMP, "decrement_and_clamp" },
86 { CORE_STENCIL_OP_INVERT, "invert" },
87 { CORE_STENCIL_OP_INCREMENT_AND_WRAP, "increment_and_wrap" },
88 { CORE_STENCIL_OP_DECREMENT_AND_WRAP, "decrement_and_wrap" },
89 })
90
91 RENDER_JSON_SERIALIZE_ENUM(BlendFactor,
92 {
93 { CORE_BLEND_FACTOR_ZERO, "zero" },
94 { CORE_BLEND_FACTOR_ONE, "one" },
95 { CORE_BLEND_FACTOR_SRC_COLOR, "src_color" },
96 { CORE_BLEND_FACTOR_ONE_MINUS_SRC_COLOR, "one_minus_src_color" },
97 { CORE_BLEND_FACTOR_DST_COLOR, "dst_color" },
98 { CORE_BLEND_FACTOR_ONE_MINUS_DST_COLOR, "one_minus_dst_color" },
99 { CORE_BLEND_FACTOR_SRC_ALPHA, "src_alpha" },
100 { CORE_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA, "one_minus_src_alpha" },
101 { CORE_BLEND_FACTOR_DST_ALPHA, "dst_alpha" },
102 { CORE_BLEND_FACTOR_ONE_MINUS_DST_ALPHA, "one_minus_dst_alpha" },
103 { CORE_BLEND_FACTOR_CONSTANT_COLOR, "constant_color" },
104 { CORE_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR, "one_minus_constant_color" },
105 { CORE_BLEND_FACTOR_CONSTANT_ALPHA, "constant_alpha" },
106 { CORE_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA, "one_minus_constant_alpha" },
107 { CORE_BLEND_FACTOR_SRC_ALPHA_SATURATE, "src_alpha_saturate" },
108 { CORE_BLEND_FACTOR_SRC1_COLOR, "src1_color" },
109 { CORE_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR, "one_minus_src1_color" },
110 { CORE_BLEND_FACTOR_SRC1_ALPHA, "src1_alpha" },
111 { CORE_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA, "one_minus_src1_alpha" },
112 })
113
114 RENDER_JSON_SERIALIZE_ENUM(BlendOp,
115 {
116 { CORE_BLEND_OP_ADD, "add" },
117 { CORE_BLEND_OP_SUBTRACT, "subtract" },
118 { CORE_BLEND_OP_REVERSE_SUBTRACT, "reverse_subtract" },
119 { CORE_BLEND_OP_MIN, "min" },
120 { CORE_BLEND_OP_MAX, "max" },
121 })
122
123 RENDER_JSON_SERIALIZE_ENUM(ColorComponentFlagBits,
124 {
125 { (ColorComponentFlagBits)0, nullptr },
126 { CORE_COLOR_COMPONENT_R_BIT, "r_bit" },
127 { CORE_COLOR_COMPONENT_G_BIT, "g_bit" },
128 { CORE_COLOR_COMPONENT_B_BIT, "b_bit" },
129 { CORE_COLOR_COMPONENT_A_BIT, "a_bit" },
130 })
131
132 RENDER_JSON_SERIALIZE_ENUM(GraphicsStateFlagBits,
133 {
134 { (GraphicsStateFlagBits)0, nullptr },
135 { CORE_GRAPHICS_STATE_INPUT_ASSEMBLY_BIT, "input_assembly_bit" },
136 { CORE_GRAPHICS_STATE_RASTERIZATION_STATE_BIT, "rasterization_state_bit" },
137 { CORE_GRAPHICS_STATE_DEPTH_STENCIL_STATE_BIT, "depth_stencil_state_bit" },
138 { CORE_GRAPHICS_STATE_COLOR_BLEND_STATE_BIT, "color_blend_state_bit" },
139 })
140
141 RENDER_JSON_SERIALIZE_ENUM(LogicOp,
142 {
143 { CORE_LOGIC_OP_CLEAR, "clear" },
144 { CORE_LOGIC_OP_AND, "and" },
145 { CORE_LOGIC_OP_AND_REVERSE, "and_reverse" },
146 { CORE_LOGIC_OP_COPY, "copy" },
147 { CORE_LOGIC_OP_AND_INVERTED, "and_inverted" },
148 { CORE_LOGIC_OP_NO_OP, "no_op" },
149 { CORE_LOGIC_OP_XOR, "xor" },
150 { CORE_LOGIC_OP_OR, "or" },
151 { CORE_LOGIC_OP_NOR, "nor" },
152 { CORE_LOGIC_OP_EQUIVALENT, "equivalent" },
153 { CORE_LOGIC_OP_INVERT, "invert" },
154 { CORE_LOGIC_OP_OR_REVERSE, "or_reverse" },
155 { CORE_LOGIC_OP_COPY_INVERTED, "copy_inverted" },
156 { CORE_LOGIC_OP_OR_INVERTED, "or_inverted" },
157 { CORE_LOGIC_OP_NAND, "nand" },
158 { CORE_LOGIC_OP_SET, "set" },
159 })
160 // clang-format on
FromJson(const json::value & jsonData,JsonContext<GraphicsState::InputAssembly> & context)161 void FromJson(const json::value& jsonData, JsonContext<GraphicsState::InputAssembly>& context)
162 {
163 SafeGetJsonValue(jsonData, "enablePrimitiveRestart", context.error, context.data.enablePrimitiveRestart);
164 SafeGetJsonEnum(jsonData, "primitiveTopology", context.error, context.data.primitiveTopology);
165 }
166
FromJson(const json::value & jsonData,JsonContext<GraphicsState::RasterizationState> & context)167 void FromJson(const json::value& jsonData, JsonContext<GraphicsState::RasterizationState>& context)
168 {
169 SafeGetJsonValue(jsonData, "enableDepthClamp", context.error, context.data.enableDepthClamp);
170 SafeGetJsonValue(jsonData, "enableDepthBias", context.error, context.data.enableDepthBias);
171 SafeGetJsonValue(jsonData, "enableRasterizerDiscard", context.error, context.data.enableRasterizerDiscard);
172
173 SafeGetJsonEnum(jsonData, "polygonMode", context.error, context.data.polygonMode);
174 SafeGetJsonBitfield<CullModeFlagBits>(jsonData, "cullModeFlags", context.error, context.data.cullModeFlags);
175 SafeGetJsonEnum(jsonData, "frontFace", context.error, context.data.frontFace);
176
177 SafeGetJsonValue(jsonData, "depthBiasConstantFactor", context.error, context.data.depthBiasConstantFactor);
178 SafeGetJsonValue(jsonData, "depthBiasClamp", context.error, context.data.depthBiasClamp);
179 SafeGetJsonValue(jsonData, "depthBiasSlopeFactor", context.error, context.data.depthBiasSlopeFactor);
180
181 SafeGetJsonValue(jsonData, "lineWidth", context.error, context.data.lineWidth);
182 }
183
FromJson(const json::value & jsonData,JsonContext<GraphicsState::StencilOpState> & context)184 void FromJson(const json::value& jsonData, JsonContext<GraphicsState::StencilOpState>& context)
185 {
186 SafeGetJsonEnum(jsonData, "failOp", context.error, context.data.failOp);
187 SafeGetJsonEnum(jsonData, "passOp", context.error, context.data.passOp);
188 SafeGetJsonEnum(jsonData, "depthFailOp", context.error, context.data.depthFailOp);
189 SafeGetJsonEnum(jsonData, "compareOp", context.error, context.data.compareOp);
190 SafeGetJsonMask(jsonData, "compareMask", context.error, context.data.compareMask);
191 SafeGetJsonMask(jsonData, "writeMask", context.error, context.data.writeMask);
192 SafeGetJsonMask(jsonData, "reference", context.error, context.data.reference);
193 }
194
FromJson(const json::value & jsonData,JsonContext<GraphicsState::DepthStencilState> & context)195 void FromJson(const json::value& jsonData, JsonContext<GraphicsState::DepthStencilState>& context)
196 {
197 SafeGetJsonValue(jsonData, "enableDepthTest", context.error, context.data.enableDepthTest);
198 SafeGetJsonValue(jsonData, "enableDepthWrite", context.error, context.data.enableDepthWrite);
199 SafeGetJsonValue(jsonData, "enableDepthBoundsTest", context.error, context.data.enableDepthBoundsTest);
200 SafeGetJsonValue(jsonData, "enableStencilTest", context.error, context.data.enableStencilTest);
201
202 SafeGetJsonValue(jsonData, "minDepthBounds", context.error, context.data.minDepthBounds);
203 SafeGetJsonValue(jsonData, "maxDepthBounds", context.error, context.data.maxDepthBounds);
204
205 SafeGetJsonEnum(jsonData, "depthCompareOp", context.error, context.data.depthCompareOp);
206
207 if (const json::value* frontStencilStateIt = jsonData.find("frontStencilOpState"); frontStencilStateIt) {
208 JsonContext<GraphicsState::StencilOpState> stencilContext;
209 FromJson(*frontStencilStateIt, stencilContext);
210 context.data.frontStencilOpState = stencilContext.data;
211 if (!stencilContext.error.empty()) {
212 context.error = stencilContext.error;
213 }
214 }
215
216 if (const json::value* backStencilStateIt = jsonData.find("backStencilOpState"); backStencilStateIt) {
217 JsonContext<GraphicsState::StencilOpState> stencilContext;
218 FromJson(*backStencilStateIt, stencilContext);
219 context.data.backStencilOpState = stencilContext.data;
220 if (!stencilContext.error.empty()) {
221 context.error = stencilContext.error;
222 }
223 }
224 }
225
FromJson(const json::value & jsonData,JsonContext<GraphicsState::ColorBlendState::Attachment> & context)226 void FromJson(const json::value& jsonData, JsonContext<GraphicsState::ColorBlendState::Attachment>& context)
227 {
228 SafeGetJsonValue(jsonData, "enableBlend", context.error, context.data.enableBlend);
229 SafeGetJsonBitfield<ColorComponentFlagBits>(jsonData, "colorWriteMask", context.error, context.data.colorWriteMask);
230
231 SafeGetJsonEnum(jsonData, "srcColorBlendFactor", context.error, context.data.srcColorBlendFactor);
232 SafeGetJsonEnum(jsonData, "dstColorBlendFactor", context.error, context.data.dstColorBlendFactor);
233 SafeGetJsonEnum(jsonData, "colorBlendOp", context.error, context.data.colorBlendOp);
234
235 SafeGetJsonEnum(jsonData, "srcAlphaBlendFactor", context.error, context.data.srcAlphaBlendFactor);
236 SafeGetJsonEnum(jsonData, "dstAlphaBlendFactor", context.error, context.data.dstAlphaBlendFactor);
237 SafeGetJsonEnum(jsonData, "alphaBlendOp", context.error, context.data.alphaBlendOp);
238 }
239
FromJson(const json::value & jsonData,JsonContext<GraphicsState::ColorBlendState> & context)240 void FromJson(const json::value& jsonData, JsonContext<GraphicsState::ColorBlendState>& context)
241 {
242 SafeGetJsonValue(jsonData, "enableLogicOp", context.error, context.data.enableLogicOp);
243 SafeGetJsonEnum(jsonData, "logicOp", context.error, context.data.logicOp);
244
245 if (const json::value* colorBlendConstantsIt = jsonData.find("colorBlendConstants"); colorBlendConstantsIt) {
246 FromJson(*colorBlendConstantsIt, context.data.colorBlendConstants);
247 }
248
249 if (const json::value* colorAttachmentsIt = jsonData.find("colorAttachments"); colorAttachmentsIt) {
250 vector<JsonContext<GraphicsState::ColorBlendState::Attachment>> colorContexts;
251 FromJson(*colorAttachmentsIt, colorContexts);
252 if (colorContexts.size() > BASE_NS::countof(context.data.colorAttachments)) {
253 colorContexts.resize(BASE_NS::countof(context.data.colorAttachments));
254 }
255 context.data.colorAttachmentCount = 0;
256 for (auto& colorContext : colorContexts) {
257 context.data.colorAttachments[context.data.colorAttachmentCount] = colorContext.data;
258 context.data.colorAttachmentCount++;
259
260 if (!colorContext.error.empty()) {
261 context.error = colorContext.error;
262 }
263 }
264 }
265 }
266
267 namespace ShaderStateLoaderUtil {
ParseStateFlags(const CORE_NS::json::value & jsonData,GraphicsStateFlags & stateFlags,ShaderStateResult & ssr)268 void ParseStateFlags(const CORE_NS::json::value& jsonData, GraphicsStateFlags& stateFlags, ShaderStateResult& ssr)
269 {
270 SafeGetJsonBitfield<GraphicsStateFlagBits>(jsonData, "stateFlags", ssr.res.error, stateFlags);
271 }
272
ParseSingleState(const json::value & jsonData,ShaderStateResult & ssr)273 void ParseSingleState(const json::value& jsonData, ShaderStateResult& ssr)
274 {
275 GraphicsState graphicsState;
276 // Read input assembly.
277 if (const json::value* inputAssemblyIt = jsonData.find("inputAssembly"); inputAssemblyIt) {
278 JsonContext<GraphicsState::InputAssembly> context;
279 FromJson(*inputAssemblyIt, context);
280 graphicsState.inputAssembly = context.data;
281
282 if (!context.error.empty()) {
283 ssr.res.error += context.error;
284 }
285 }
286
287 // Read rasterization state.
288 if (const json::value* rasterizationStateIt = jsonData.find("rasterizationState"); rasterizationStateIt) {
289 JsonContext<GraphicsState::RasterizationState> context;
290 FromJson(*rasterizationStateIt, context);
291 graphicsState.rasterizationState = context.data;
292
293 if (!context.error.empty()) {
294 ssr.res.error += context.error;
295 }
296 }
297
298 // Read depth stencil state
299 if (const json::value* depthStencilStateIt = jsonData.find("depthStencilState"); depthStencilStateIt) {
300 JsonContext<GraphicsState::DepthStencilState> context;
301 FromJson(*depthStencilStateIt, context);
302 graphicsState.depthStencilState = context.data;
303
304 if (!context.error.empty()) {
305 ssr.res.error += context.error;
306 }
307 }
308
309 // Read depth color blend state.
310 if (const json::value* colorBlendStateIt = jsonData.find("colorBlendState"); colorBlendStateIt) {
311 JsonContext<GraphicsState::ColorBlendState> context;
312 FromJson(*colorBlendStateIt, context);
313 graphicsState.colorBlendState = context.data;
314
315 if (!context.error.empty()) {
316 ssr.res.error += context.error;
317 }
318 }
319
320 ssr.res.success = ssr.res.error.empty();
321 if (ssr.res.success) {
322 ssr.states.states.push_back(move(graphicsState));
323 }
324 }
325
LoadStates(const json::value & jsonData)326 ShaderStateResult LoadStates(const json::value& jsonData)
327 {
328 ShaderStateResult ssr;
329 if (const json::value* iter = jsonData.find("shaderStates"); iter) {
330 const auto& allStates = iter->array_;
331 ssr.states.states.reserve(allStates.size());
332 for (auto const& state : allStates) {
333 IShaderManager::ShaderStateLoaderVariantData variant;
334 SafeGetJsonValue(state, "variantName", ssr.res.error, variant.variantName);
335 if (variant.variantName.empty()) {
336 ssr.res.error += "graphics state variant name needs to be given\n";
337 }
338 // if we get any errors, we break and don't write anymore variants
339 if (!ssr.res.error.empty()) {
340 break;
341 }
342
343 if (const json::value* graphicsStateIt = state.find("state"); graphicsStateIt) {
344 ParseSingleState(*graphicsStateIt, ssr);
345 if (ssr.res.error.empty()) {
346 SafeGetJsonValue(state, "baseShaderState", ssr.res.error, variant.baseShaderState);
347 SafeGetJsonValue(state, "baseVariantName", ssr.res.error, variant.baseVariantName);
348 SafeGetJsonValue(state, "slot", ssr.res.error, variant.renderSlot);
349 SafeGetJsonValue(state, "renderSlot", ssr.res.error, variant.renderSlot);
350 SafeGetJsonValue(
351 state, "renderSlotDefaultShaderState", ssr.res.error, variant.renderSlotDefaultState);
352 if (!variant.renderSlotDefaultState) {
353 SafeGetJsonValue(state, "renderSlotDefault", ssr.res.error, variant.renderSlotDefaultState);
354 }
355 SafeGetJsonBitfield<GraphicsStateFlagBits>(state, "stateFlags", ssr.res.error, variant.stateFlags);
356 ssr.states.variantData.push_back(move(variant));
357 }
358 }
359 }
360 }
361
362 ssr.res.success = ssr.res.error.empty();
363 if (!ssr.res.success) {
364 ssr.res.error += "error loading shader states\n";
365 PLUGIN_LOG_E("error loading shader states: %s", ssr.res.error.c_str());
366 ssr.states.states.clear();
367 }
368 return ssr;
369 }
370 } // namespace ShaderStateLoaderUtil
371 RENDER_END_NAMESPACE()
372