1 /*
2  * Copyright (c) 2024 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 "render_node_parser_util.h"
17 
18 #include <cstdint>
19 
20 #include <base/containers/fixed_string.h>
21 #include <base/containers/string.h>
22 #include <render/device/pipeline_state_desc.h>
23 #include <render/namespace.h>
24 #include <render/render_data_structures.h>
25 
26 #include "device/gpu_resource_manager.h"
27 #include "device/shader_manager.h"
28 #include "loader/json_format_serialization.h"
29 #include "loader/json_util.h"
30 
31 using namespace BASE_NS;
32 using namespace CORE_NS;
33 
34 RENDER_BEGIN_NAMESPACE()
35 // clang-format off
36 CORE_JSON_SERIALIZE_ENUM(RenderSlotSortType,
37     {
38         { RenderSlotSortType::NONE, "none" },
39         { RenderSlotSortType::FRONT_TO_BACK, "front_to_back" },
40         { RenderSlotSortType::BACK_TO_FRONT, "back_to_front" },
41         { RenderSlotSortType::BY_MATERIAL, "by_material" },
42     })
43 
44 CORE_JSON_SERIALIZE_ENUM(RenderSlotCullType,
45     {
46         { RenderSlotCullType::NONE, "none" },
47         { RenderSlotCullType::VIEW_FRUSTUM_CULL, "view_frustum_cull" },
48     })
49 
50 CORE_JSON_SERIALIZE_ENUM(GpuQueue::QueueType,
51     { { GpuQueue::QueueType::UNDEFINED, nullptr }, { GpuQueue::QueueType::GRAPHICS, "graphics" },
52         { GpuQueue::QueueType::COMPUTE, "compute" }, { GpuQueue::QueueType::TRANSFER, "transfer" } })
53 
54 CORE_JSON_SERIALIZE_ENUM(DescriptorType,
55     {
56         { DescriptorType::CORE_DESCRIPTOR_TYPE_MAX_ENUM, nullptr },
57         { DescriptorType::CORE_DESCRIPTOR_TYPE_SAMPLER, "sampler" },
58         { DescriptorType::CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler" },
59         { DescriptorType::CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image" },
60         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image" },
61         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_texel_buffer" },
62         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_texel_buffer" },
63         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer" },
64         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer" },
65         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic" },
66         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic" },
67         { DescriptorType::CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, "input_attachment" },
68     })
69 
70 CORE_JSON_SERIALIZE_ENUM(AttachmentLoadOp,
71     {
72         { AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_LOAD, "load" },
73         { AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_CLEAR, "clear" },
74         { AttachmentLoadOp::CORE_ATTACHMENT_LOAD_OP_DONT_CARE, "dont_care" },
75     })
76 
77 CORE_JSON_SERIALIZE_ENUM(AttachmentStoreOp,
78     {
79         { AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_STORE, "store" },
80         { AttachmentStoreOp::CORE_ATTACHMENT_STORE_OP_DONT_CARE, "dont_care" },
81     })
82 
83 CORE_JSON_SERIALIZE_ENUM(ImageType,
84     {
85         { ImageType::CORE_IMAGE_TYPE_2D, nullptr }, // default
86         { ImageType::CORE_IMAGE_TYPE_1D, "1d" },
87         { ImageType::CORE_IMAGE_TYPE_2D, "2d" },
88         { ImageType::CORE_IMAGE_TYPE_3D, "3d" },
89     })
90 
91 CORE_JSON_SERIALIZE_ENUM(ImageViewType,
92     {
93         { ImageViewType::CORE_IMAGE_VIEW_TYPE_2D, nullptr }, // default
94         { ImageViewType::CORE_IMAGE_VIEW_TYPE_1D, "1d" }, { ImageViewType::CORE_IMAGE_VIEW_TYPE_2D, "2d" },
95         { ImageViewType::CORE_IMAGE_VIEW_TYPE_3D, "3d" }, { ImageViewType::CORE_IMAGE_VIEW_TYPE_CUBE, "cube" },
96         { ImageViewType::CORE_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" },
97         { ImageViewType::CORE_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" },
98         { ImageViewType::CORE_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" },
99     })
100 
101 CORE_JSON_SERIALIZE_ENUM(ImageTiling,
102     {
103         { ImageTiling::CORE_IMAGE_TILING_OPTIMAL, nullptr }, // default
104         { ImageTiling::CORE_IMAGE_TILING_OPTIMAL, "optimal" },
105         { ImageTiling::CORE_IMAGE_TILING_LINEAR, "linear" },
106     })
107 
108 CORE_JSON_SERIALIZE_ENUM(ImageUsageFlagBits,
109     {
110         { (ImageUsageFlagBits)0, nullptr },
111         { ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_SRC_BIT, "transfer_src" },
112         { ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSFER_DST_BIT, "transfer_dst" },
113         { ImageUsageFlagBits::CORE_IMAGE_USAGE_SAMPLED_BIT, "sampled" },
114         { ImageUsageFlagBits::CORE_IMAGE_USAGE_STORAGE_BIT, "storage" },
115         { ImageUsageFlagBits::CORE_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, "color_attachment" },
116         { ImageUsageFlagBits::CORE_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, "depth_stencil_attachment" },
117         { ImageUsageFlagBits::CORE_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT, "transient_attachment" },
118         { ImageUsageFlagBits::CORE_IMAGE_USAGE_INPUT_ATTACHMENT_BIT, "input_attachment" },
119         { ImageUsageFlagBits::CORE_IMAGE_USAGE_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT, "fragment_shading_rate_attachment" },
120     })
121 
122 CORE_JSON_SERIALIZE_ENUM(ImageCreateFlagBits,
123     {
124         { (ImageCreateFlagBits)0, nullptr },
125         { ImageCreateFlagBits::CORE_IMAGE_CREATE_CUBE_COMPATIBLE_BIT, "cube_compatible" },
126         { ImageCreateFlagBits::CORE_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT, "2d_array_compatible" },
127     })
128 
129 CORE_JSON_SERIALIZE_ENUM(EngineImageCreationFlagBits,
130     {
131         { (EngineImageCreationFlagBits)0, nullptr },
132         { EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_DYNAMIC_BARRIERS, "dynamic_barriers" },
133         { EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_RESET_STATE_ON_FRAME_BORDERS,
134             "reset_state_on_frame_borders" },
135         { EngineImageCreationFlagBits::CORE_ENGINE_IMAGE_CREATION_GENERATE_MIPS, "generate_mips" },
136     })
137 
138 CORE_JSON_SERIALIZE_ENUM(SampleCountFlagBits,
139     {
140         { (SampleCountFlagBits)0, nullptr },
141         { SampleCountFlagBits::CORE_SAMPLE_COUNT_1_BIT, "1bit" },
142         { SampleCountFlagBits::CORE_SAMPLE_COUNT_2_BIT, "2bit" },
143         { SampleCountFlagBits::CORE_SAMPLE_COUNT_4_BIT, "4bit" },
144         { SampleCountFlagBits::CORE_SAMPLE_COUNT_8_BIT, "8bit" },
145         { SampleCountFlagBits::CORE_SAMPLE_COUNT_16_BIT, "16bit" },
146         { SampleCountFlagBits::CORE_SAMPLE_COUNT_32_BIT, "32bit" },
147         { SampleCountFlagBits::CORE_SAMPLE_COUNT_64_BIT, "64bit" },
148     })
149 
150 CORE_JSON_SERIALIZE_ENUM(MemoryPropertyFlagBits,
151     {
152         { (MemoryPropertyFlagBits)0, nullptr },
153         { MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, "device_local" },
154         { MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_VISIBLE_BIT, "host_visible" },
155         { MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_COHERENT_BIT, "host_coherent" },
156         { MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_HOST_CACHED_BIT, "host_cached" },
157         { MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT, "lazily_allocated" },
158         { MemoryPropertyFlagBits::CORE_MEMORY_PROPERTY_PROTECTED_BIT, "protected" },
159     })
160 
161 CORE_JSON_SERIALIZE_ENUM(EngineBufferCreationFlagBits,
162     {
163         { (EngineBufferCreationFlagBits)0, nullptr },
164         { EngineBufferCreationFlagBits::CORE_ENGINE_BUFFER_CREATION_DYNAMIC_BARRIERS, "dynamic_barriers" },
165     })
166 
167 CORE_JSON_SERIALIZE_ENUM(BufferUsageFlagBits,
168     {
169         { (BufferUsageFlagBits)0, nullptr },
170         { BufferUsageFlagBits::CORE_BUFFER_USAGE_TRANSFER_SRC_BIT, "transfer_src" },
171         { BufferUsageFlagBits::CORE_BUFFER_USAGE_TRANSFER_DST_BIT, "transfer_dst" },
172         { BufferUsageFlagBits::CORE_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, "uniform_texel" },
173         { BufferUsageFlagBits::CORE_BUFFER_USAGE_UNIFORM_BUFFER_BIT, "uniform" },
174         { BufferUsageFlagBits::CORE_BUFFER_USAGE_STORAGE_BUFFER_BIT, "storage_texel" },
175         { BufferUsageFlagBits::CORE_BUFFER_USAGE_STORAGE_BUFFER_BIT, "storage" },
176         { BufferUsageFlagBits::CORE_BUFFER_USAGE_INDEX_BUFFER_BIT, "index" },
177         { BufferUsageFlagBits::CORE_BUFFER_USAGE_VERTEX_BUFFER_BIT, "vertex" },
178         { BufferUsageFlagBits::CORE_BUFFER_USAGE_INDIRECT_BUFFER_BIT, "indirect" },
179         { BufferUsageFlagBits::CORE_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT, "shader_binding_table" },
180         { BufferUsageFlagBits::CORE_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT, "shader_device_address" },
181         { BufferUsageFlagBits::CORE_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT, "acceleration_structure_build_input_read_only" },
182         { BufferUsageFlagBits::CORE_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT, "acceleration_structure_storage" },
183     })
184 
185 CORE_JSON_SERIALIZE_ENUM(RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits,
186     {
187         { RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits::MAX_DEPENDENCY_FLAG_ENUM, nullptr },
188         { RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits::FORMAT, "format" },
189         { RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits::SIZE, "size" },
190         { RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits::MIP_COUNT, "mipCount" },
191         { RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits::LAYER_COUNT, "layerCount" },
192         { RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits::SAMPLES, "samples" },
193     })
194 
195 CORE_JSON_SERIALIZE_ENUM(RenderNodeGraphResourceLocationType,
196     {
197         { RenderNodeGraphResourceLocationType::DEFAULT, "default" },
198         { RenderNodeGraphResourceLocationType::FROM_RENDER_GRAPH_INPUT, "from_render_graph_input" },
199         { RenderNodeGraphResourceLocationType::FROM_RENDER_GRAPH_OUTPUT, "from_render_graph_output" },
200         { RenderNodeGraphResourceLocationType::FROM_PREVIOUS_RENDER_NODE_OUTPUT, "from_previous_render_node_output" },
201         { RenderNodeGraphResourceLocationType::FROM_NAMED_RENDER_NODE_OUTPUT, "from_named_render_node_output" },
202         { RenderNodeGraphResourceLocationType::FROM_PREVIOUS_RENDER_NODE_GRAPH_OUTPUT, "from_previous_render_node_graph_output" },
203     })
204 
205 CORE_JSON_SERIALIZE_ENUM(ResolveModeFlagBits,
206     {
207         { ResolveModeFlagBits::CORE_RESOLVE_MODE_NONE, "none" },
208         { ResolveModeFlagBits::CORE_RESOLVE_MODE_SAMPLE_ZERO_BIT, "sample_zero" },
209         { ResolveModeFlagBits::CORE_RESOLVE_MODE_AVERAGE_BIT, "average" },
210         { ResolveModeFlagBits::CORE_RESOLVE_MODE_MIN_BIT, "min" },
211         { ResolveModeFlagBits::CORE_RESOLVE_MODE_MAX_BIT, "max" },
212     })
213 
214 CORE_JSON_SERIALIZE_ENUM(SubpassContents,
215     {
216         { SubpassContents::CORE_SUBPASS_CONTENTS_INLINE, "inline" },
217         { SubpassContents::CORE_SUBPASS_CONTENTS_SECONDARY_COMMAND_LISTS, "secondary_command_lists" },
218     })
219 // clang-format on
220 inline void FromJson(const json::value& jsonData, JsonContext<RenderNodeGraphInputs::Resource>& context)
221 {
222     SafeGetJsonValue(jsonData, "set", context.error, context.data.set);
223     SafeGetJsonValue(jsonData, "binding", context.error, context.data.binding);
224     SafeGetJsonValue(jsonData, "name", context.error, context.data.name);
225     SafeGetJsonEnum(jsonData, "resourceLocation", context.error, context.data.resourceLocation);
226     SafeGetJsonValue(jsonData, "resourceIndex", context.error, context.data.resourceIndex);
227     SafeGetJsonValue(jsonData, "nodeName", context.error, context.data.nodeName);
228     SafeGetJsonValue(jsonData, "usageName", context.error, context.data.usageName);
229     SafeGetJsonValue(jsonData, "mip", context.error, context.data.mip);
230     SafeGetJsonValue(jsonData, "layer", context.error, context.data.layer);
231 }
232 
FromJson(const json::value & jsonData,JsonContext<RenderNodeGraphInputs::Attachment> & context)233 inline void FromJson(const json::value& jsonData, JsonContext<RenderNodeGraphInputs::Attachment>& context)
234 {
235     SafeGetJsonEnum(jsonData, "loadOp", context.error, context.data.loadOp);
236     SafeGetJsonEnum(jsonData, "storeOp", context.error, context.data.storeOp);
237     SafeGetJsonEnum(jsonData, "stencilLoadOp", context.error, context.data.stencilLoadOp);
238     SafeGetJsonEnum(jsonData, "stencilStoreOp", context.error, context.data.stencilStoreOp);
239     if (auto const pos = jsonData.find("clearColor"); pos) {
240         if (pos->is_array() && pos->array_.size() == 4) {
241             FromJson(*pos, context.data.clearValue.color.float32);
242         } else {
243             const auto asString = to_string(*pos);
244             context.error +=
245                 "clearColor must be an array of length 4 : (" + string_view(asString.data(), asString.size()) + ")\n";
246         }
247     }
248     if (auto const pos = jsonData.find("clearDepth"); pos) {
249         if (pos->is_array() && pos->array_.size() == 2) {
250             if (pos->array_[0].is_number()) {
251                 context.data.clearValue.depthStencil.depth = pos->array_[0].as_number<float>();
252             } else {
253                 const auto asString = to_string(*pos);
254                 context.error += "depthAttachment.clearValue[0] must be a float: (" +
255                                  string_view(asString.data(), asString.size()) + ")\n";
256             }
257 
258             if (pos->array_[1].is_number()) {
259                 context.data.clearValue.depthStencil.stencil = pos->array_[1].as_number<uint32_t>();
260             } else {
261                 const auto asString = to_string(*pos);
262                 context.error += "depthAttachment.clearValue[1] must be an uint: (" +
263                                  string_view(asString.data(), asString.size()) + ")\n";
264             }
265         } else {
266             const auto asString = to_string(*pos);
267             context.error += "Failed to read depthAttachment.clearValue, invalid datatype: (" +
268                              string_view(asString.data(), asString.size()) + ")\n";
269         }
270     }
271     SafeGetJsonValue(jsonData, "name", context.error, context.data.name);
272     SafeGetJsonEnum(jsonData, "resourceLocation", context.error, context.data.resourceLocation);
273     SafeGetJsonValue(jsonData, "resourceIndex", context.error, context.data.resourceIndex);
274     SafeGetJsonValue(jsonData, "nodeName", context.error, context.data.nodeName);
275 
276     SafeGetJsonValue(jsonData, "mip", context.error, context.data.mip);
277     SafeGetJsonValue(jsonData, "layer", context.error, context.data.layer);
278 }
279 
FromJson(const json::value & jsonData,JsonContext<RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc> & context)280 inline void FromJson(
281     const json::value& jsonData, JsonContext<RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc>& context)
282 {
283     SafeGetJsonValue(jsonData, "name", context.error, context.data.name);
284     SafeGetJsonValue(jsonData, "shareName", context.error, context.data.shareName);
285     SafeGetJsonValue(jsonData, "dependencyImageName", context.error, context.data.dependencyImageName);
286 
287     SafeGetJsonEnum(jsonData, "imageType", context.error, context.data.desc.imageType);
288     SafeGetJsonEnum(jsonData, "imageViewType", context.error, context.data.desc.imageViewType);
289     SafeGetJsonEnum(jsonData, "format", context.error, context.data.desc.format);
290     SafeGetJsonEnum(jsonData, "imageTiling", context.error, context.data.desc.imageTiling);
291     SafeGetJsonBitfield<ImageUsageFlagBits>(jsonData, "usageFlags", context.error, context.data.desc.usageFlags);
292     SafeGetJsonBitfield<MemoryPropertyFlagBits>(
293         jsonData, "memoryPropertyFlags", context.error, context.data.desc.memoryPropertyFlags);
294     SafeGetJsonBitfield<ImageCreateFlagBits>(jsonData, "createFlags", context.error, context.data.desc.createFlags);
295     SafeGetJsonBitfield<EngineImageCreationFlagBits>(
296         jsonData, "engineCreationFlags", context.error, context.data.desc.engineCreationFlags);
297     SafeGetJsonValue(jsonData, "width", context.error, context.data.desc.width);
298     SafeGetJsonValue(jsonData, "height", context.error, context.data.desc.height);
299     SafeGetJsonValue(jsonData, "depth", context.error, context.data.desc.depth);
300     SafeGetJsonValue(jsonData, "mipCount", context.error, context.data.desc.mipCount);
301     SafeGetJsonValue(jsonData, "layerCount", context.error, context.data.desc.layerCount);
302     SafeGetJsonBitfield<SampleCountFlagBits>(
303         jsonData, "sampleCountFlags", context.error, context.data.desc.sampleCountFlags);
304 
305     SafeGetJsonBitfield<RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc::DependencyFlagBits>(
306         jsonData, "dependencyFlags", context.error, context.data.dependencyFlags);
307     SafeGetJsonValue(jsonData, "dependencySizeScale", context.error, context.data.dependencySizeScale);
308 
309     if (auto const pos = jsonData.find("shadingRateTexelSize"); pos) {
310         if (pos->is_array() && pos->array_.size() == 2) {
311             if (pos->array_[0].is_number() && pos->array_[1u].is_number()) {
312                 context.data.shadingRateTexelSize.width = pos->array_[0].as_number<uint32_t>();
313                 context.data.shadingRateTexelSize.height = pos->array_[1].as_number<uint32_t>();
314             }
315         }
316     }
317 
318     if ((context.data.desc.format == Format::BASE_FORMAT_UNDEFINED) && context.data.dependencyImageName.empty()) {
319         context.error += "undefined gpu image desc format\n";
320     }
321 }
322 
FromJson(const json::value & jsonData,JsonContext<RenderNodeGraphInputs::RenderNodeGraphGpuBufferDesc> & context)323 inline void FromJson(
324     const json::value& jsonData, JsonContext<RenderNodeGraphInputs::RenderNodeGraphGpuBufferDesc>& context)
325 {
326     SafeGetJsonValue(jsonData, "name", context.error, context.data.name);
327     SafeGetJsonValue(jsonData, "shareName", context.error, context.data.shareName);
328     SafeGetJsonValue(jsonData, "dependencyBufferName", context.error, context.data.dependencyBufferName);
329 
330     SafeGetJsonBitfield<BufferUsageFlagBits>(jsonData, "usageFlags", context.error, context.data.desc.usageFlags);
331     SafeGetJsonBitfield<EngineBufferCreationFlagBits>(
332         jsonData, "engineCreationFlags", context.error, context.data.desc.engineCreationFlags);
333     SafeGetJsonBitfield<MemoryPropertyFlagBits>(
334         jsonData, "memoryPropertyFlags", context.error, context.data.desc.memoryPropertyFlags);
335     SafeGetJsonValue(jsonData, "byteSize", context.error, context.data.desc.byteSize);
336 }
337 
FromJson(const json::value & jsonData,JsonContext<DescriptorCounts::TypedCount> & context)338 inline void FromJson(const json::value& jsonData, JsonContext<DescriptorCounts::TypedCount>& context)
339 {
340     SafeGetJsonEnum(jsonData, "type", context.error, context.data.type);
341     SafeGetJsonValue(jsonData, "count", context.error, context.data.count);
342 }
343 
344 namespace {
345 struct LoadResult {
346     string error;
347 };
348 
ParseRenderpass(const string_view name,const json::value & node,RenderNodeGraphInputs::InputRenderPass & renderPass,LoadResult & result)349 void ParseRenderpass(const string_view name, const json::value& node,
350     RenderNodeGraphInputs::InputRenderPass& renderPass, LoadResult& result)
351 {
352     if (auto const rp = node.find(name); rp) {
353         ParseArray<decltype(renderPass.attachments)::value_type>(*rp, "attachments", renderPass.attachments, result);
354         SafeGetJsonValue(*rp, "subpassIndex", result.error, renderPass.subpassIndex);
355         SafeGetJsonValue(*rp, "subpassCount", result.error, renderPass.subpassCount);
356         SafeGetJsonEnum(*rp, "subpassContents", result.error, renderPass.subpassContents);
357 #if (RENDER_VALIDATION_ENABLED == 1)
358         if (renderPass.subpassIndex >= renderPass.subpassCount) {
359             PLUGIN_LOG_E("RENDER_VALIDATION: render pass subpass index must be smaller than subpass index");
360         }
361 #endif
362         if (auto const sp = rp->find("subpass"); sp) {
363             SafeGetJsonValue(*sp, "depthAttachmentIndex", result.error, renderPass.depthAttachmentIndex);
364             SafeGetJsonValue(*sp, "depthResolveAttachmentIndex", result.error, renderPass.depthResolveAttachmentIndex);
365             SafeGetJsonEnum(*sp, "depthResolveModeFlagBit", result.error, renderPass.depthResolveModeFlagBit);
366             SafeGetJsonEnum(*sp, "stencilResolveModeFlagBit", result.error, renderPass.stencilResolveModeFlagBit);
367             SafeGetJsonEnum(
368                 *sp, "fragmentShadingRateAttachmentIndex", result.error, renderPass.fragmentShadingRateAttachmentIndex);
369 #if (RENDER_VALIDATION_ENABLED == 1)
370             if ((renderPass.depthResolveAttachmentIndex != ~0u) &&
371                 ((renderPass.depthResolveModeFlagBit | renderPass.stencilResolveModeFlagBit) == 0)) {
372                 PLUGIN_LOG_W("RENDER_VALIDATION: depth resolve mode flags not set for depth resolve image");
373             }
374 #endif
375 
376             const auto getAttachmentIndices = [](const char* attachmentName, const auto& subpass,
377                                                   auto& attachmentVector) {
378                 if (auto const iIter = subpass.find(attachmentName); iIter) {
379                     if (iIter->is_array()) {
380                         std::transform(iIter->array_.begin(), iIter->array_.end(), std::back_inserter(attachmentVector),
381                             [](const json::value& value) {
382                                 if (value.is_number()) {
383                                     return value.template as_number<uint32_t>();
384                                 }
385                                 return 0u;
386                             });
387                     } else {
388                         attachmentVector = { iIter->template as_number<uint32_t>() };
389                     }
390                 }
391             };
392 
393             getAttachmentIndices("inputAttachmentIndices", *sp, renderPass.inputAttachmentIndices);
394             getAttachmentIndices("colorAttachmentIndices", *sp, renderPass.colorAttachmentIndices);
395             getAttachmentIndices("resolveAttachmentIndices", *sp, renderPass.resolveAttachmentIndices);
396 
397             if (auto const pos = sp->find("shadingRateTexelSize"); pos) {
398                 if (pos->is_array() && pos->array_.size() == 2) { // 2 :size
399                     if (pos->array_[0].is_number() && pos->array_[1u].is_number()) {
400                         renderPass.shadingRateTexelSize.width = pos->array_[0].as_number<uint32_t>();
401                         renderPass.shadingRateTexelSize.height = pos->array_[1].as_number<uint32_t>();
402                     }
403                 }
404             }
405 
406             SafeGetJsonValue(*sp, "viewMask", result.error, renderPass.viewMask);
407         }
408     }
409 }
410 
ParseResources(const string_view name,const json::value & node,RenderNodeGraphInputs::InputResources & resources,LoadResult & result)411 void ParseResources(const string_view name, const json::value& node, RenderNodeGraphInputs::InputResources& resources,
412     LoadResult& result)
413 {
414     if (auto const res = node.find(name); res) {
415         ParseArray<decltype(resources.buffers)::value_type>(*res, "buffers", resources.buffers, result);
416         ParseArray<decltype(resources.images)::value_type>(*res, "images", resources.images, result);
417         ParseArray<decltype(resources.samplers)::value_type>(*res, "samplers", resources.samplers, result);
418 
419         ParseArray<decltype(resources.customInputBuffers)::value_type>(
420             *res, "customInputBuffers", resources.customInputBuffers, result);
421         ParseArray<decltype(resources.customOutputBuffers)::value_type>(
422             *res, "customOutputBuffers", resources.customOutputBuffers, result);
423 
424         ParseArray<decltype(resources.customInputImages)::value_type>(
425             *res, "customInputImages", resources.customInputImages, result);
426         ParseArray<decltype(resources.customOutputImages)::value_type>(
427             *res, "customOutputImages", resources.customOutputImages, result);
428     }
429 }
430 } // namespace
431 
RenderNodeParserUtil(const CreateInfo & createInfo)432 RenderNodeParserUtil::RenderNodeParserUtil(const CreateInfo& createInfo) {}
433 
434 RenderNodeParserUtil::~RenderNodeParserUtil() = default;
435 
GetUintValue(const json::value & jsonValue,const string_view name) const436 uint64_t RenderNodeParserUtil::GetUintValue(const json::value& jsonValue, const string_view name) const
437 {
438     uint64_t val = std::numeric_limits<uint64_t>::max();
439     string error;
440     if (!SafeGetJsonValue(jsonValue, name, error, val)) {
441         PLUGIN_LOG_W("GetUintValue: %s", error.c_str());
442     }
443     return val;
444 }
445 
GetIntValue(const json::value & jsonValue,const string_view name) const446 int64_t RenderNodeParserUtil::GetIntValue(const json::value& jsonValue, const string_view name) const
447 {
448     int64_t val = std::numeric_limits<int64_t>::max();
449     string error;
450     if (!SafeGetJsonValue(jsonValue, name, error, val)) {
451         PLUGIN_LOG_W("GetIntValue: %s", error.c_str());
452     }
453     return val;
454 }
455 
GetFloatValue(const json::value & jsonValue,const string_view name) const456 float RenderNodeParserUtil::GetFloatValue(const json::value& jsonValue, const string_view name) const
457 {
458     float val = std::numeric_limits<float>::max();
459     string error;
460     if (!SafeGetJsonValue(jsonValue, name, error, val)) {
461         PLUGIN_LOG_W("GetFloatValue: %s", error.c_str());
462     }
463     return val;
464 }
465 
GetStringValue(const json::value & jsonValue,const string_view name) const466 string RenderNodeParserUtil::GetStringValue(const json::value& jsonValue, const string_view name) const
467 {
468     string parsedString;
469     string error;
470     if (!SafeGetJsonValue(jsonValue, name, error, parsedString)) {
471         PLUGIN_LOG_W("GetStringValue: %s", error.c_str());
472     }
473     return parsedString;
474 }
475 
GetInputRenderPass(const json::value & jsonValue,const string_view name) const476 RenderNodeGraphInputs::InputRenderPass RenderNodeParserUtil::GetInputRenderPass(
477     const json::value& jsonValue, const string_view name) const
478 {
479     RenderNodeGraphInputs::InputRenderPass renderPass;
480     LoadResult result;
481     ParseRenderpass(name, jsonValue, renderPass, result);
482     if (!result.error.empty()) {
483         PLUGIN_LOG_W("GetInputRenderPass: %s", result.error.c_str());
484     }
485     return renderPass;
486 }
487 
GetInputResources(const json::value & jsonValue,const string_view name) const488 RenderNodeGraphInputs::InputResources RenderNodeParserUtil::GetInputResources(
489     const json::value& jsonValue, const string_view name) const
490 {
491     RenderNodeGraphInputs::InputResources resources;
492     LoadResult result;
493     ParseResources(name, jsonValue, resources, result);
494     if (!result.error.empty()) {
495         PLUGIN_LOG_W("GetInputResources: %s", result.error.c_str());
496     }
497     return resources;
498 }
499 
GetRenderDataStore(const json::value & jsonValue,const string_view name) const500 RenderNodeGraphInputs::RenderDataStore RenderNodeParserUtil::GetRenderDataStore(
501     const json::value& jsonValue, const string_view name) const
502 {
503     RenderNodeGraphInputs::RenderDataStore renderDataStore;
504     LoadResult result;
505     if (auto const dataStore = jsonValue.find(name); dataStore) {
506         SafeGetJsonValue(*dataStore, "dataStoreName", result.error, renderDataStore.dataStoreName);
507         SafeGetJsonValue(*dataStore, "typeName", result.error, renderDataStore.typeName);
508         SafeGetJsonValue(*dataStore, "configurationName", result.error, renderDataStore.configurationName);
509     }
510     if (!result.error.empty()) {
511         PLUGIN_LOG_W("GetRenderDataStore: %s", result.error.c_str());
512     }
513     return renderDataStore;
514 }
515 
GetGpuImageDescs(const json::value & jsonValue,const string_view name) const516 vector<RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc> RenderNodeParserUtil::GetGpuImageDescs(
517     const json::value& jsonValue, const string_view name) const
518 {
519     vector<RenderNodeGraphInputs::RenderNodeGraphGpuImageDesc> resources;
520     LoadResult result;
521     if (const auto ref = jsonValue.find(name); ref) {
522         if (ref->is_array()) {
523             ParseArray<decltype(resources)::value_type>(jsonValue, name.data(), resources, result);
524         } else {
525             result.error += "expecting array";
526         }
527     }
528     if (!result.error.empty()) {
529         PLUGIN_LOG_W("GetGpuImageDescs: %s", result.error.c_str());
530     }
531     return resources;
532 }
533 
GetGpuBufferDescs(const json::value & jsonValue,const string_view name) const534 vector<RenderNodeGraphInputs::RenderNodeGraphGpuBufferDesc> RenderNodeParserUtil::GetGpuBufferDescs(
535     const json::value& jsonValue, const string_view name) const
536 {
537     vector<RenderNodeGraphInputs::RenderNodeGraphGpuBufferDesc> resources;
538     LoadResult result;
539     if (const auto ref = jsonValue.find(name); ref) {
540         if (ref->is_array()) {
541             ParseArray<decltype(resources)::value_type>(jsonValue, name.data(), resources, result);
542         } else {
543             result.error += "expecting array";
544         }
545     }
546     if (!result.error.empty()) {
547         PLUGIN_LOG_W("GetGpuBufferDescs: %s", result.error.c_str());
548     }
549     return resources;
550 }
551 
GetRenderSlotSortType(const json::value & jsonValue,const string_view name) const552 RenderSlotSortType RenderNodeParserUtil::GetRenderSlotSortType(
553     const json::value& jsonValue, const string_view name) const
554 {
555     RenderSlotSortType sortType = RenderSlotSortType::NONE;
556     string error;
557     if (!SafeGetJsonEnum(jsonValue, name, error, sortType)) {
558         PLUGIN_LOG_W("GetRenderSlotSortType: %s", error.c_str());
559     }
560     return sortType;
561 }
562 
GetRenderSlotCullType(const json::value & jsonValue,const string_view name) const563 RenderSlotCullType RenderNodeParserUtil::GetRenderSlotCullType(
564     const json::value& jsonValue, const string_view name) const
565 {
566     RenderSlotCullType cullType = RenderSlotCullType::NONE;
567     string error;
568     if (!SafeGetJsonEnum(jsonValue, name, error, cullType)) {
569         PLUGIN_LOG_W("GetRenderSlotCullType: %s", error.c_str());
570     }
571     return cullType;
572 }
573 
GetInterface(const BASE_NS::Uid & uid) const574 const CORE_NS::IInterface* RenderNodeParserUtil::GetInterface(const BASE_NS::Uid& uid) const
575 {
576     if ((uid == IRenderNodeParserUtil::UID) || (uid == IInterface::UID)) {
577         return this;
578     }
579     return nullptr;
580 }
581 
GetInterface(const BASE_NS::Uid & uid)582 CORE_NS::IInterface* RenderNodeParserUtil::GetInterface(const BASE_NS::Uid& uid)
583 {
584     if ((uid == IRenderNodeParserUtil::UID) || (uid == IInterface::UID)) {
585         return this;
586     }
587     return nullptr;
588 }
589 
Ref()590 void RenderNodeParserUtil::Ref() {}
591 
Unref()592 void RenderNodeParserUtil::Unref() {}
593 RENDER_END_NAMESPACE()
594