• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "pipeline_layout_loader.h"
17 
18 #include <base/math/mathf.h>
19 #include <core/io/intf_file_manager.h>
20 #include <render/device/pipeline_layout_desc.h>
21 #include <render/namespace.h>
22 
23 #include "json_util.h"
24 #include "util/log.h"
25 
26 using namespace BASE_NS;
27 using namespace CORE_NS;
28 
29 RENDER_BEGIN_NAMESPACE()
30 // clang-format off
31 RENDER_JSON_SERIALIZE_ENUM(ShaderStageFlagBits,
32     {
33         { (ShaderStageFlagBits)0, nullptr },
34         { ShaderStageFlagBits::CORE_SHADER_STAGE_VERTEX_BIT, "vertex_bit" },
35         { ShaderStageFlagBits::CORE_SHADER_STAGE_FRAGMENT_BIT, "fragment_bit" },
36         { ShaderStageFlagBits::CORE_SHADER_STAGE_COMPUTE_BIT, "compute_bit" },
37     })
38 
39 RENDER_JSON_SERIALIZE_ENUM(AdditionalDescriptorTypeImageFlagBits,
40     {
41         {(AdditionalDescriptorTypeImageFlagBits)0, nullptr},
42         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DEPTH_BIT, "image_depth_bit"},
43         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_ARRAY_BIT, "image_array_bit"},
44         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_MULTISAMPLE_BIT, "image_multisample_bit"},
45         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_SAMPLED_BIT, "image_sampled_bit"},
46         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_LOAD_STORE_BIT, "image_load_store_bit"},
47         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_1D_BIT, "image_dimension_1d_bit"},
48         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_2D_BIT, "image_dimension_2d_bit"},
49         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_3D_BIT, "image_dimension_3d_bit"},
50         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_CUBE_BIT,
51          "image_dimension_cube_bit"},
52         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_BUFFER_BIT,
53          "image_dimension_buffer_bit"},
54         {AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_SUBPASS_BIT,
55          "image_dimension_subpass_bit"},
56     })
57 
58 RENDER_JSON_SERIALIZE_ENUM(DescriptorType,
59     {
60         { DescriptorType::CORE_DESCRIPTOR_TYPE_MAX_ENUM, nullptr }, // default
61         { DescriptorType::CORE_DESCRIPTOR_TYPE_SAMPLER, "sampler" },
62         { DescriptorType::CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler" },
63         { DescriptorType::CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image" },
64         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image" },
65         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_texel_buffer" },
66         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_texel_buffer" },
67         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer" },
68         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer" },
69         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic" },
70         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic" },
71         { DescriptorType::CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, "input_attachment" },
72         { DescriptorType::CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE, "acceleration_structure" },
73     })
74 // clang-format on
FromJson(const json::value & jsonData,JsonContext<DescriptorSetLayoutBinding> & context)75 void FromJson(const json::value& jsonData, JsonContext<DescriptorSetLayoutBinding>& context)
76 {
77     SafeGetJsonValue(jsonData, "binding", context.error, context.data.binding);
78     SafeGetJsonEnum(jsonData, "descriptorType", context.error, context.data.descriptorType);
79     SafeGetJsonValue(jsonData, "descriptorCount", context.error, context.data.descriptorCount);
80     SafeGetJsonBitfield<ShaderStageFlagBits>(
81         jsonData, "shaderStageFlags", context.error, context.data.shaderStageFlags);
82     SafeGetJsonBitfield<AdditionalDescriptorTypeImageFlagBits>(
83         jsonData, "additionalDescriptorTypeFlags", context.error, context.data.additionalDescriptorTypeFlags);
84 }
85 
FromJson(const json::value & jsonData,JsonContext<DescriptorSetLayout> & context)86 void FromJson(const json::value& jsonData, JsonContext<DescriptorSetLayout>& context)
87 {
88     SafeGetJsonValue(jsonData, "set", context.error, context.data.set);
89 
90     PipelineLayoutLoader::LoadResult loadResult;
91     ParseArray<decltype(context.data.bindings)::value_type>(jsonData, "bindings", context.data.bindings, loadResult);
92     context.error = loadResult.error;
93     // NOTE: does not fetch descriptor set arrays
94 }
95 
Load(const json::value & jsonData,const string_view uri,PipelineLayout & pl,string & renderSlotName,bool & defaultRenderSlot)96 PipelineLayoutLoader::LoadResult Load(const json::value& jsonData, [[maybe_unused]] const string_view uri,
97     PipelineLayout& pl, string& renderSlotName, bool& defaultRenderSlot)
98 {
99     PipelineLayoutLoader::LoadResult result;
100     pl = {}; // reset
101 
102     SafeGetJsonValue(jsonData, "renderSlot", result.error, renderSlotName);
103     SafeGetJsonValue(jsonData, "renderSlotDefault", result.error, defaultRenderSlot);
104     if (!defaultRenderSlot) {
105         SafeGetJsonValue(jsonData, "renderSlotDefaultPipelineLayout", result.error, defaultRenderSlot);
106     }
107 
108     if (const auto pcIter = jsonData.find("pushConstant"); pcIter) {
109         SafeGetJsonValue(*pcIter, "size", result.error, pl.pushConstant.byteSize);
110         SafeGetJsonValue(*pcIter, "byteSize", result.error, pl.pushConstant.byteSize);
111         SafeGetJsonBitfield<ShaderStageFlagBits>(
112             *pcIter, "shaderStageFlags", result.error, pl.pushConstant.shaderStageFlags);
113 #if (RENDER_VALIDATION_ENABLED == 1)
114         if (pl.pushConstant.byteSize > PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE) {
115             PLUGIN_LOG_W("RENDER_VALIDATION: Invalid push constant size clamped (name:%s). push constant size %u <= %u",
116                 uri.data(), pl.pushConstant.byteSize, PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE);
117         }
118 #endif
119         pl.pushConstant.byteSize =
120             Math::min(PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE, pl.pushConstant.byteSize);
121     }
122 
123     vector<DescriptorSetLayout> descriptorSetLayouts;
124     ParseArray<decltype(descriptorSetLayouts)::value_type>(
125         jsonData, "descriptorSetLayouts", descriptorSetLayouts, result);
126     if (!descriptorSetLayouts.empty()) {
127         const auto inputDescriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
128 #if (RENDER_VALIDATION_ENABLED == 1)
129         if (inputDescriptorSetCount > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
130             PLUGIN_LOG_W("RENDER_VALIDATION: Invalid pipeline layout sizes clamped (name:%s). Set count %u <= %u",
131                 uri.data(), inputDescriptorSetCount, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT);
132         }
133         for (const auto& descRef : descriptorSetLayouts) {
134             if (descRef.bindings.size() > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
135                 PLUGIN_LOG_W(
136                     "RENDER_VALIDATION: Binding count exceeds the maximum (name:%s). Binding count count %u <= %u",
137                     uri.data(), static_cast<uint32_t>(descRef.bindings.size()),
138                     PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT);
139             }
140             for (const auto& bindingRef : descRef.bindings) {
141                 if (bindingRef.descriptorType == DescriptorType::CORE_DESCRIPTOR_TYPE_MAX_ENUM) {
142                     PLUGIN_LOG_W("RENDER_VALIDATION: Unknown descriptor type (name:%s) (set:%u, binding:%u).",
143                         uri.data(), descRef.set, bindingRef.binding);
144                 }
145             }
146         }
147 #endif
148         // pipeline layout descriptor sets might have gaps and only some sets defined
149         for (uint32_t idx = 0; idx < inputDescriptorSetCount; ++idx) {
150             const uint32_t setIndex = descriptorSetLayouts[idx].set;
151             if (setIndex < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
152                 pl.descriptorSetLayouts[setIndex] = move(descriptorSetLayouts[idx]);
153             }
154         }
155     } else {
156         result.error += "invalid descriptor set layout count";
157     }
158 
159     result.success = result.error.empty();
160     if (!result.success) {
161         PLUGIN_LOG_E("error loading pipeline layout from json: %s", result.error.c_str());
162     }
163 
164     return result;
165 }
166 
GetUri() const167 string_view PipelineLayoutLoader::GetUri() const
168 {
169     return uri_;
170 }
171 
GetPipelineLayout() const172 const PipelineLayout& PipelineLayoutLoader::GetPipelineLayout() const
173 {
174     return pipelineLayout_;
175 }
176 
GetRenderSlot() const177 BASE_NS::string_view PipelineLayoutLoader::GetRenderSlot() const
178 {
179     return renderSlotName_;
180 }
181 
GetDefaultRenderSlot() const182 bool PipelineLayoutLoader::GetDefaultRenderSlot() const
183 {
184     return renderSlotDefaultPl_;
185 }
186 
Load(const string_view jsonString)187 PipelineLayoutLoader::LoadResult PipelineLayoutLoader::Load(const string_view jsonString)
188 {
189     if (json::value jsonData = json::parse(jsonString.data()); jsonData) {
190         return RENDER_NS::Load(jsonData, uri_, pipelineLayout_, renderSlotName_, renderSlotDefaultPl_);
191     }
192     return LoadResult("Invalid json file.");
193 }
194 
Load(IFileManager & fileManager,const string_view uri)195 PipelineLayoutLoader::LoadResult PipelineLayoutLoader::Load(IFileManager& fileManager, const string_view uri)
196 {
197     uri_ = uri;
198 
199     IFile::Ptr file = fileManager.OpenFile(uri);
200     if (!file) {
201         PLUGIN_LOG_E("Error loading '%s'", string(uri).c_str());
202         return LoadResult("Failed to open file.");
203     }
204 
205     const uint64_t byteLength = file->GetLength();
206 
207     string raw;
208     raw.resize(static_cast<size_t>(byteLength));
209 
210     if (file->Read(raw.data(), byteLength) != byteLength) {
211         PLUGIN_LOG_E("Error loading '%s'", string(uri).c_str());
212         return LoadResult("Failed to read file.");
213     }
214 
215     return Load(string_view(raw));
216 }
217 RENDER_END_NAMESPACE()
218