• 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 "render_node_graph_loader.h"
17 
18 #include <cctype>
19 #include <charconv>
20 #include <cstring>
21 
22 #include <base/containers/fixed_string.h>
23 #include <base/containers/vector.h>
24 #include <base/math/matrix_util.h>
25 #include <core/io/intf_file.h>
26 #include <core/io/intf_file_manager.h>
27 #include <render/namespace.h>
28 #include <render/nodecontext/intf_render_node_graph_manager.h>
29 #include <render/render_data_structures.h>
30 
31 #include "json_format_serialization.h"
32 #include "json_util.h"
33 #include "util/log.h"
34 
35 using namespace BASE_NS;
36 using namespace CORE_NS;
37 
38 RENDER_BEGIN_NAMESPACE()
39 CORE_JSON_SERIALIZE_ENUM(GpuQueue::QueueType,
40     { { GpuQueue::QueueType::UNDEFINED, nullptr }, { GpuQueue::QueueType::GRAPHICS, "graphics" },
41         { GpuQueue::QueueType::COMPUTE, "compute" }, { GpuQueue::QueueType::TRANSFER, "transfer" } })
42 
43 namespace {
44 constexpr size_t VERSION_SIZE { 5u };
45 constexpr uint32_t VERSION_MAJOR { 22u };
46 
ParseQueueWaitSignals(const json::value & node,RenderNodeDesc & data,IRenderNodeGraphLoader::LoadResult & nodeResult)47 void ParseQueueWaitSignals(
48     const json::value& node, RenderNodeDesc& data, IRenderNodeGraphLoader::LoadResult& nodeResult)
49 {
50     if (auto const queueSignals = node.find("gpuQueueWaitSignals"); queueSignals) {
51         if (auto const typeNames = queueSignals->find("typeNames"); typeNames) {
52             if (typeNames->is_array()) {
53                 FromJson(*typeNames, data.description.gpuQueueWaitForSignals.typeNames);
54             }
55         }
56         if (auto const nodeNames = queueSignals->find("nodeNames"); nodeNames) {
57             if (nodeNames->is_array()) {
58                 FromJson(*nodeNames, data.description.gpuQueueWaitForSignals.nodeNames);
59             }
60         }
61 #if (RENDER_VALIDATION_ENABLED == 1)
62         if (data.description.gpuQueueWaitForSignals.nodeNames.size() >
63             PipelineStateConstants::MAX_RENDER_NODE_GPU_WAIT_SIGNALS) {
64             nodeResult.error += "gpuQueueWaitSignal count must be smaller than" +
65                                 to_string(PipelineStateConstants::MAX_RENDER_NODE_GPU_WAIT_SIGNALS) + ")\n";
66         }
67         if (data.description.gpuQueueWaitForSignals.typeNames.size() >
68             PipelineStateConstants::MAX_RENDER_NODE_GPU_WAIT_SIGNALS) {
69             nodeResult.error += "gpuQueueWaitSignal count must be smaller than" +
70                                 to_string(PipelineStateConstants::MAX_RENDER_NODE_GPU_WAIT_SIGNALS) + ")\n";
71         }
72 #endif
73     }
74 }
75 
ParseRenderNode(const json::value & node,RenderNodeDesc & data)76 IRenderNodeGraphLoader::LoadResult ParseRenderNode(const json::value& node, RenderNodeDesc& data)
77 {
78     IRenderNodeGraphLoader::LoadResult nodeResult;
79 
80     SafeGetJsonValue(node, "typeName", nodeResult.error, data.typeName);
81     SafeGetJsonValue(node, "nodeName", nodeResult.error, data.nodeName);
82     // render node specific json
83     data.nodeJson = json::to_string(node);
84     SafeGetJsonValue(node, "nodeDataStoreName", nodeResult.error, data.description.nodeDataStoreName);
85 
86     if (auto const queue = node.find("queue"); queue) {
87         SafeGetJsonEnum(*queue, "type", nodeResult.error, data.description.queue.type);
88         SafeGetJsonValue(*queue, "index", nodeResult.error, data.description.queue.index);
89     }
90 
91     if (auto const cpuDependencies = node.find("cpuDependencies"); cpuDependencies) {
92         if (auto const typeNames = cpuDependencies->find("typeNames"); typeNames) {
93             if (typeNames->is_array()) {
94                 FromJson(*typeNames, data.description.cpuDependencies.typeNames);
95             }
96         }
97         if (auto const nodeNames = cpuDependencies->find("nodeNames"); nodeNames) {
98             if (nodeNames->is_array()) {
99                 FromJson(*nodeNames, data.description.cpuDependencies.nodeNames);
100             }
101         }
102     }
103     ParseQueueWaitSignals(node, data, nodeResult);
104 
105     return nodeResult;
106 }
107 
CompatibilityCheck(const json::value & json,RenderNodeGraphLoader::LoadResult & result)108 void CompatibilityCheck(const json::value& json, RenderNodeGraphLoader::LoadResult& result)
109 {
110     string ver;
111     string type;
112     uint32_t verMajor { ~0u };
113     uint32_t verMinor { ~0u };
114     if (const json::value* iter = json.find("compatibility_info"); iter) {
115         SafeGetJsonValue(*iter, "version", result.error, ver);
116         SafeGetJsonValue(*iter, "type", result.error, type);
117         if (ver.size() == VERSION_SIZE) {
118             if (const auto delim = ver.find('.'); delim != string::npos) {
119                 std::from_chars(ver.data(), ver.data() + delim, verMajor);
120                 std::from_chars(ver.data() + delim + 1, ver.data() + ver.size(), verMinor);
121             }
122         }
123     }
124     if ((type != "rendernodegraph") || (verMajor != VERSION_MAJOR)) {
125         result.error += "invalid render node graph type (" + type + ") and/or version (" + ver + ").";
126         result.success = false;
127     }
128 }
129 } // namespace
130 
RenderNodeGraphLoader(IFileManager & fileManager)131 RenderNodeGraphLoader::RenderNodeGraphLoader(IFileManager& fileManager) : fileManager_(fileManager) {}
132 
Load(const string_view uri)133 RenderNodeGraphLoader::LoadResult RenderNodeGraphLoader::Load(const string_view uri)
134 {
135     IFile::Ptr file = fileManager_.OpenFile(uri);
136     if (!file) {
137         PLUGIN_LOG_D("Error loading '%s'", string(uri).c_str());
138         return LoadResult("Failed to open file.");
139     }
140 
141     const uint64_t byteLength = file->GetLength();
142 
143     string raw(static_cast<size_t>(byteLength), string::value_type());
144     if (file->Read(raw.data(), byteLength) != byteLength) {
145         PLUGIN_LOG_D("Error loading '%s'", string(uri).c_str());
146         return LoadResult("Failed to read file.");
147     }
148 
149     return LoadString(uri, raw);
150 }
151 
LoadString(const string_view jsonString)152 RenderNodeGraphLoader::LoadResult RenderNodeGraphLoader::LoadString(const string_view jsonString)
153 {
154     return LoadString("", jsonString);
155 }
156 
LoadString(const string_view uri,const string_view jsonString)157 RenderNodeGraphLoader::LoadResult RenderNodeGraphLoader::LoadString(const string_view uri, const string_view jsonString)
158 {
159     if (const auto json = json::parse(jsonString.data()); json) {
160         LoadResult finalResult;
161         CompatibilityCheck(json, finalResult);
162         if (!finalResult.success) {
163             return finalResult; // compatibility check failed
164         }
165 
166         string renderNodeGraphName;
167         string renderNodeGraphDataStoreName;
168         SafeGetJsonValue(json, "renderNodeGraphName", finalResult.error, renderNodeGraphName);
169         SafeGetJsonValue(json, "renderNodeGraphDataStoreName", finalResult.error, renderNodeGraphDataStoreName);
170 
171         vector<RenderNodeDesc> nodeDescriptors;
172         if (const auto nodes = json.find("nodes"); nodes) {
173             nodeDescriptors.reserve(nodes->array_.size());
174             for (auto const& node : nodes->array_) {
175                 RenderNodeDesc data;
176                 LoadResult nodeResult = ParseRenderNode(node, data);
177                 if (nodeResult.error.empty()) {
178                     nodeDescriptors.emplace_back(move(data));
179                 } else {
180                     finalResult.error += nodeResult.error;
181                 }
182             }
183         }
184 
185         finalResult.success = finalResult.error.empty();
186         if (finalResult.error.empty()) {
187             finalResult.desc.renderNodeGraphName = renderNodeGraphName;
188             finalResult.desc.renderNodeGraphDataStoreName = renderNodeGraphDataStoreName;
189             finalResult.desc.renderNodeGraphUri = uri;
190             finalResult.desc.nodes = move(nodeDescriptors);
191         }
192 
193         return finalResult;
194     } else {
195         return LoadResult("Invalid render node graph json file.");
196     }
197 }
198 RENDER_END_NAMESPACE()
199