• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "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,
48 	    "image_dimension_1d_bit" },
49         { AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_2D_BIT,
50 	    "image_dimension_2d_bit" },
51         { AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_3D_BIT,
52 	    "image_dimension_3d_bit" },
53         { AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_CUBE_BIT,
54 	    "image_dimension_cube_bit" },
55         { AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_BUFFER_BIT,
56 	    "image_dimension_buffer_bit" },
57         { AdditionalDescriptorTypeImageFlagBits::CORE_DESCRIPTOR_TYPE_IMAGE_DIMENSION_SUBPASS_BIT,
58 	    "image_dimension_subpass_bit" },
59     })
60 
61 RENDER_JSON_SERIALIZE_ENUM(DescriptorType,
62     {
63         { DescriptorType::CORE_DESCRIPTOR_TYPE_MAX_ENUM, nullptr }, // default
64         { DescriptorType::CORE_DESCRIPTOR_TYPE_SAMPLER, "sampler" },
65         { DescriptorType::CORE_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "combined_image_sampler" },
66         { DescriptorType::CORE_DESCRIPTOR_TYPE_SAMPLED_IMAGE, "sampled_image" },
67         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_IMAGE, "storage_image" },
68         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_texel_buffer" },
69         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_texel_buffer" },
70         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER, "uniform_buffer" },
71         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER, "storage_buffer" },
72         { DescriptorType::CORE_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC, "uniform_buffer_dynamic" },
73         { DescriptorType::CORE_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "storage_buffer_dynamic" },
74         { DescriptorType::CORE_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, "input_attachment" },
75         { DescriptorType::CORE_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE, "acceleration_structure" },
76     })
77 // clang-format on
FromJson(const json::value & jsonData,JsonContext<DescriptorSetLayoutBinding> & context)78 void FromJson(const json::value& jsonData, JsonContext<DescriptorSetLayoutBinding>& context)
79 {
80     SafeGetJsonValue(jsonData, "binding", context.error, context.data.binding);
81     SafeGetJsonEnum(jsonData, "descriptorType", context.error, context.data.descriptorType);
82     SafeGetJsonValue(jsonData, "descriptorCount", context.error, context.data.descriptorCount);
83     SafeGetJsonBitfield<ShaderStageFlagBits>(
84         jsonData, "shaderStageFlags", context.error, context.data.shaderStageFlags);
85     SafeGetJsonBitfield<AdditionalDescriptorTypeImageFlagBits>(
86         jsonData, "additionalDescriptorTypeFlags", context.error, context.data.additionalDescriptorTypeFlags);
87 }
88 
FromJson(const json::value & jsonData,JsonContext<DescriptorSetLayout> & context)89 void FromJson(const json::value& jsonData, JsonContext<DescriptorSetLayout>& context)
90 {
91     SafeGetJsonValue(jsonData, "set", context.error, context.data.set);
92 
93     PipelineLayoutLoader::LoadResult loadResult;
94     ParseArray<decltype(context.data.bindings)::value_type>(jsonData, "bindings", context.data.bindings, loadResult);
95     context.error = loadResult.error;
96     // NOTE: does not fetch descriptor set arrays
97 }
98 
Load(const json::value & jsonData,const string_view uri,PipelineLayout & pl,string & renderSlotName,bool & defaultRenderSlot)99 PipelineLayoutLoader::LoadResult Load(const json::value& jsonData, [[maybe_unused]] const string_view uri,
100     PipelineLayout& pl, string& renderSlotName, bool& defaultRenderSlot)
101 {
102     PipelineLayoutLoader::LoadResult result;
103     pl = {}; // reset
104 
105     SafeGetJsonValue(jsonData, "renderSlot", result.error, renderSlotName);
106     SafeGetJsonValue(jsonData, "renderSlotDefault", result.error, defaultRenderSlot);
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(
116                 "RENDER_VALIDATION: Invalid push constant size clamped (name:%s). push constant size %u <= %u",
117                 uri.data(), pl.pushConstant.byteSize, PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE);
118         }
119 #endif
120         pl.pushConstant.byteSize =
121             Math::min(PipelineLayoutConstants::MAX_PUSH_CONSTANT_BYTE_SIZE, pl.pushConstant.byteSize);
122     }
123 
124     vector<DescriptorSetLayout> descriptorSetLayouts;
125     ParseArray<decltype(descriptorSetLayouts)::value_type>(
126         jsonData, "descriptorSetLayouts", descriptorSetLayouts, result);
127     if (!descriptorSetLayouts.empty()) {
128         const auto inputDescriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size());
129 #if (RENDER_VALIDATION_ENABLED == 1)
130         if (inputDescriptorSetCount > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
131             PLUGIN_LOG_W("RENDER_VALIDATION: Invalid pipeline layout sizes clamped (name:%s). Set count %u <= %u",
132                 uri.data(), inputDescriptorSetCount, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT);
133         }
134         for (const auto& descRef : descriptorSetLayouts) {
135             if (descRef.bindings.size() > PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT) {
136                 PLUGIN_LOG_W(
137                     "RENDER_VALIDATION: Binding count exceeds the maximum (name:%s). Binding count count %u <= %u",
138                     uri.data(), static_cast<uint32_t>(descRef.bindings.size()),
139                     PipelineLayoutConstants::MAX_DESCRIPTOR_SET_BINDING_COUNT);
140             }
141             for (const auto& bindingRef : descRef.bindings) {
142                 if (bindingRef.descriptorType == DescriptorType::CORE_DESCRIPTOR_TYPE_MAX_ENUM) {
143                     PLUGIN_LOG_W("RENDER_VALIDATION: Unknown descriptor type (name:%s) (set:%u, binding:%u).",
144                         uri.data(), descRef.set, bindingRef.binding);
145                 }
146             }
147         }
148 #endif
149         // pipeline layout descriptor sets might have gaps and only some sets defined
150         for (uint32_t idx = 0; idx < inputDescriptorSetCount; ++idx) {
151             const uint32_t setIndex = descriptorSetLayouts[idx].set;
152             if (setIndex < PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT) {
153                 pl.descriptorSetLayouts[setIndex] = move(descriptorSetLayouts[idx]);
154                 pl.descriptorSetCount++;
155             }
156         }
157         // reassure
158         pl.descriptorSetCount = Math::min(pl.descriptorSetCount, PipelineLayoutConstants::MAX_DESCRIPTOR_SET_COUNT);
159     } else {
160         result.error += "invalid descriptor set layout count";
161     }
162 
163     result.success = result.error.empty();
164     if (!result.success) {
165         PLUGIN_LOG_E("error loading pipeline layout from json: %s", result.error.c_str());
166     }
167 
168     return result;
169 }
170 
GetUri() const171 string_view PipelineLayoutLoader::GetUri() const
172 {
173     return uri_;
174 }
175 
GetPipelineLayout() const176 const PipelineLayout& PipelineLayoutLoader::GetPipelineLayout() const
177 {
178     return pipelineLayout_;
179 }
180 
GetRenderSlot() const181 BASE_NS::string_view PipelineLayoutLoader::GetRenderSlot() const
182 {
183     return renderSlotName_;
184 }
185 
GetDefaultRenderSlot() const186 bool PipelineLayoutLoader::GetDefaultRenderSlot() const
187 {
188     return renderSlotDefaultPl_;
189 }
190 
Load(const string_view jsonString)191 PipelineLayoutLoader::LoadResult PipelineLayoutLoader::Load(const string_view jsonString)
192 {
193     if (json::value jsonData = json::parse(jsonString.data()); jsonData) {
194         return RENDER_NS::Load(jsonData, uri_, pipelineLayout_, renderSlotName_, renderSlotDefaultPl_);
195     }
196     return LoadResult("Invalid json file.");
197 }
198 
Load(IFileManager & fileManager,const string_view uri)199 PipelineLayoutLoader::LoadResult PipelineLayoutLoader::Load(IFileManager& fileManager, const string_view uri)
200 {
201     uri_ = uri;
202 
203     IFile::Ptr file = fileManager.OpenFile(uri);
204     if (!file) {
205         PLUGIN_LOG_E("Error loading '%s'", string(uri).c_str());
206         return LoadResult("Failed to open file.");
207     }
208 
209     const uint64_t byteLength = file->GetLength();
210 
211     string raw;
212     raw.resize(static_cast<size_t>(byteLength));
213 
214     if (file->Read(raw.data(), byteLength) != byteLength) {
215         PLUGIN_LOG_E("Error loading '%s'", string(uri).c_str());
216         return LoadResult("Failed to read file.");
217     }
218 
219     return Load(string_view(raw));
220 }
221 RENDER_END_NAMESPACE()
222