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 "vertex_input_declaration_loader.h"
17
18 #include <algorithm>
19
20 #include <core/io/intf_file_manager.h>
21 #include <core/namespace.h>
22 #include <render/device/pipeline_state_desc.h>
23
24 #include "json_format_serialization.h"
25 #include "json_util.h"
26 #include "util/log.h"
27
28 using namespace BASE_NS;
29 using namespace CORE_NS;
30
31 RENDER_BEGIN_NAMESPACE()
32 // clang-format off
33 RENDER_JSON_SERIALIZE_ENUM(VertexInputRate,
34 {
35 { CORE_VERTEX_INPUT_RATE_VERTEX, "vertex" },
36 { CORE_VERTEX_INPUT_RATE_INSTANCE, "instance" },
37 })
38 // clang-format on
FromJson(const json::value & jsonData,JsonContext<VertexInputDeclaration::VertexInputBindingDescription> & context)39 void FromJson(const json::value& jsonData, JsonContext<VertexInputDeclaration::VertexInputBindingDescription>& context)
40 {
41 SafeGetJsonValue(jsonData, "binding", context.error, context.data.binding);
42 SafeGetJsonValue(jsonData, "stride", context.error, context.data.stride);
43 SafeGetJsonEnum(jsonData, "vertexInputRate", context.error, context.data.vertexInputRate);
44 }
45
FromJson(const json::value & jsonData,JsonContext<VertexInputDeclaration::VertexInputAttributeDescription> & context)46 void FromJson(
47 const json::value& jsonData, JsonContext<VertexInputDeclaration::VertexInputAttributeDescription>& context)
48 {
49 SafeGetJsonValue(jsonData, "location", context.error, context.data.location);
50 SafeGetJsonValue(jsonData, "binding", context.error, context.data.binding);
51 SafeGetJsonEnum(jsonData, "format", context.error, context.data.format);
52 SafeGetJsonValue(jsonData, "offset", context.error, context.data.offset);
53 }
54
55 namespace {
LoadState(const json::value & jsonData,const string_view uri,VertexInputDeclarationData & vertexInputDeclarationData_,string & renderSlotName,bool & defaultRenderSlot)56 VertexInputDeclarationLoader::LoadResult LoadState(const json::value& jsonData, const string_view uri,
57 VertexInputDeclarationData& vertexInputDeclarationData_, string& renderSlotName, bool& defaultRenderSlot)
58 {
59 VertexInputDeclarationLoader::LoadResult result;
60
61 SafeGetJsonValue(jsonData, "renderSlot", result.error, renderSlotName);
62 SafeGetJsonValue(jsonData, "renderSlotDefault", result.error, defaultRenderSlot);
63
64 vector<VertexInputDeclaration::VertexInputBindingDescription> bindings;
65 vector<VertexInputDeclaration::VertexInputAttributeDescription> attributes;
66
67 ParseArray<decltype(bindings)::value_type>(jsonData, "vertexInputBindingDescriptions", bindings, result);
68 ParseArray<decltype(attributes)::value_type>(jsonData, "vertexInputAttributeDescriptions", attributes, result);
69
70 if (result.success) {
71 PLUGIN_ASSERT(bindings.size() <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
72 PLUGIN_ASSERT(attributes.size() <= PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
73
74 vertexInputDeclarationData_.bindingDescriptionCount =
75 std::min((uint32_t)bindings.size(), PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
76 vertexInputDeclarationData_.attributeDescriptionCount =
77 std::min((uint32_t)attributes.size(), PipelineStateConstants::MAX_VERTEX_BUFFER_COUNT);
78
79 for (uint32_t idx = 0; idx < vertexInputDeclarationData_.bindingDescriptionCount; ++idx) {
80 vertexInputDeclarationData_.bindingDescriptions[idx] = bindings[idx];
81 }
82 for (uint32_t idx = 0; idx < vertexInputDeclarationData_.attributeDescriptionCount; ++idx) {
83 vertexInputDeclarationData_.attributeDescriptions[idx] = attributes[idx];
84 if (vertexInputDeclarationData_.attributeDescriptions[idx].format == Format::BASE_FORMAT_UNDEFINED) {
85 result.success = false;
86 result.error += "undefined format for vertex input attribute\n";
87 PLUGIN_LOG_E("undefined format in vertex input attribute (%u), in %s", idx, uri.data());
88 }
89 }
90 }
91
92 return result;
93 }
94
Load(const json::value & jsonData,const string_view uri,VertexInputDeclarationData & vertexInputDeclarationData,string & renderSlotName,bool & renderSlotDefault)95 VertexInputDeclarationLoader::LoadResult Load(const json::value& jsonData, const string_view uri,
96 VertexInputDeclarationData& vertexInputDeclarationData, string& renderSlotName, bool& renderSlotDefault)
97 {
98 VertexInputDeclarationLoader::LoadResult result;
99
100 if (const json::value* stateIter = jsonData.find("vertexInputState"); stateIter) {
101 result = LoadState(*stateIter, uri, vertexInputDeclarationData, renderSlotName, renderSlotDefault);
102 } else {
103 result.error += "vertex input state not found\n";
104 result.success = false;
105 }
106
107 return result;
108 }
109 } // namespace
110
GetUri() const111 string_view VertexInputDeclarationLoader::GetUri() const
112 {
113 return uri_;
114 }
115
GetVertexInputDeclarationView() const116 VertexInputDeclarationView VertexInputDeclarationLoader::GetVertexInputDeclarationView() const
117 {
118 return {
119 array_view<const VertexInputDeclaration::VertexInputBindingDescription>(
120 vertexInputDeclarationData_.bindingDescriptions, vertexInputDeclarationData_.bindingDescriptionCount),
121 array_view<const VertexInputDeclaration::VertexInputAttributeDescription>(
122 vertexInputDeclarationData_.attributeDescriptions, vertexInputDeclarationData_.attributeDescriptionCount),
123 };
124 }
125
GetRenderSlot() const126 BASE_NS::string_view VertexInputDeclarationLoader::GetRenderSlot() const
127 {
128 return renderSlotName_;
129 }
130
GetDefaultRenderSlot() const131 bool VertexInputDeclarationLoader::GetDefaultRenderSlot() const
132 {
133 return renderSlotDefaultVid_;
134 }
135
Load(const string_view jsonString)136 VertexInputDeclarationLoader::LoadResult VertexInputDeclarationLoader::Load(const string_view jsonString)
137 {
138 VertexInputDeclarationLoader::LoadResult result;
139 const auto json = json::parse(jsonString.data());
140 if (json) {
141 result = RENDER_NS::Load(json, uri_, vertexInputDeclarationData_, renderSlotName_, renderSlotDefaultVid_);
142 } else {
143 result.success = false;
144 result.error = "Invalid json file.";
145 }
146
147 return result;
148 }
149
Load(IFileManager & fileManager,const string_view uri)150 VertexInputDeclarationLoader::LoadResult VertexInputDeclarationLoader::Load(
151 IFileManager& fileManager, const string_view uri)
152 {
153 uri_ = uri;
154 LoadResult result;
155
156 IFile::Ptr file = fileManager.OpenFile(uri);
157 if (!file) {
158 PLUGIN_LOG_E("Error loading '%s'", string(uri).c_str());
159 return LoadResult("Failed to open file.");
160 }
161
162 const uint64_t byteLength = file->GetLength();
163
164 string raw;
165 raw.resize(static_cast<size_t>(byteLength));
166
167 if (file->Read(raw.data(), byteLength) != byteLength) {
168 PLUGIN_LOG_E("Error loading '%s'", string(uri).c_str());
169 return LoadResult("Failed to read file.");
170 }
171
172 return Load(string_view(raw));
173 }
174
175 RENDER_END_NAMESPACE()
176