Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
reflector.h
Go to the documentation of this file.
1// Copyright 2013 The Flutter Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef FLUTTER_IMPELLER_COMPILER_REFLECTOR_H_
6#define FLUTTER_IMPELLER_COMPILER_REFLECTOR_H_
7
8#include <cstdint>
9#include <memory>
10#include <optional>
11
12#include "flutter/fml/mapping.h"
13#include "fml/logging.h"
17#include "inja/inja.hpp"
18#include "spirv_common.hpp"
19#include "spirv_msl.hpp"
20#include "spirv_parser.hpp"
21
22namespace impeller {
23namespace compiler {
24
26 // Runtime stages on Vulkan use this information to validate that a struct
27 // only contains floats and encode where padding gets inserted.
28 enum class UnderlyingType {
30 kFloat,
31 kOther,
32 };
33
34 std::string type;
35 spirv_cross::SPIRType::BaseType base_type;
36 std::string name;
37 size_t offset = 0u;
38 size_t size = 0u;
39 size_t byte_length = 0u;
40 std::optional<size_t> array_elements = std::nullopt;
41 size_t element_padding = 0u;
42 std::optional<std::string> float_type = std::nullopt;
43 // Component count of a single column. For non-matrix types this is the
44 // vector length; for matrices this is the row count. Combined with
45 // `columns`, this disambiguates types that share the same `size`, e.g.
46 // vec4 and mat2.
47 size_t vec_size = 0u;
48 // The number of columns. 1 for scalars and vectors; N for an NxN matrix.
49 size_t columns = 0u;
51
52 static std::string BaseTypeToString(spirv_cross::SPIRType::BaseType type) {
53 using Type = spirv_cross::SPIRType::BaseType;
54 switch (type) {
55 case Type::Void:
56 return "ShaderType::kVoid";
57 case Type::Boolean:
58 return "ShaderType::kBoolean";
59 case Type::SByte:
60 return "ShaderType::kSignedByte";
61 case Type::UByte:
62 return "ShaderType::kUnsignedByte";
63 case Type::Short:
64 return "ShaderType::kSignedShort";
65 case Type::UShort:
66 return "ShaderType::kUnsignedShort";
67 case Type::Int:
68 return "ShaderType::kSignedInt";
69 case Type::UInt:
70 return "ShaderType::kUnsignedInt";
71 case Type::Int64:
72 return "ShaderType::kSignedInt64";
73 case Type::UInt64:
74 return "ShaderType::kUnsignedInt64";
75 case Type::AtomicCounter:
76 return "ShaderType::kAtomicCounter";
77 case Type::Half:
78 return "ShaderType::kHalfFloat";
79 case Type::Float:
80 return "ShaderType::kFloat";
81 case Type::Double:
82 return "ShaderType::kDouble";
83 case Type::Struct:
84 return "ShaderType::kStruct";
85 case Type::Image:
86 return "ShaderType::kImage";
87 case Type::SampledImage:
88 return "ShaderType::kSampledImage";
89 case Type::Sampler:
90 return "ShaderType::kSampler";
91 default:
92 return "ShaderType::kUnknown";
93 }
95 }
96
98 spirv_cross::SPIRType::BaseType type) {
99 switch (type) {
100 case spirv_cross::SPIRType::Void:
102 case spirv_cross::SPIRType::Float:
104 case spirv_cross::SPIRType::Unknown:
105 case spirv_cross::SPIRType::Boolean:
106 case spirv_cross::SPIRType::SByte:
107 case spirv_cross::SPIRType::UByte:
108 case spirv_cross::SPIRType::Short:
109 case spirv_cross::SPIRType::UShort:
110 case spirv_cross::SPIRType::Int:
111 case spirv_cross::SPIRType::UInt:
112 case spirv_cross::SPIRType::Int64:
113 case spirv_cross::SPIRType::UInt64:
114 case spirv_cross::SPIRType::AtomicCounter:
115 case spirv_cross::SPIRType::Half:
116 case spirv_cross::SPIRType::Double:
117 case spirv_cross::SPIRType::Struct:
118 case spirv_cross::SPIRType::Image:
119 case spirv_cross::SPIRType::SampledImage:
120 case spirv_cross::SPIRType::Sampler:
121 case spirv_cross::SPIRType::AccelerationStructure:
122 case spirv_cross::SPIRType::RayQuery:
123 case spirv_cross::SPIRType::ControlPointArray:
124 case spirv_cross::SPIRType::Interpolant:
125 case spirv_cross::SPIRType::Char:
126 default:
128 }
130 }
131
132 /// @brief Constructs a new StructMember.
133 ///
134 /// @param p_type The string type name (e.g. "float", "Point", "Matrix").
135 /// @param p_base_type The SPIR-V base type.
136 /// @param p_name The name of the struct member.
137 /// @param p_offset The offset in bytes from the start of the parent struct.
138 /// @param p_size The size in bytes of a single element of this type
139 /// (ignoring padding/stride).
140 /// @param p_byte_length The total size in bytes this member occupies in
141 /// the struct, including all array elements and padding.
142 /// @param p_array_elements The number of array elements. For matrices
143 /// treated as arrays of columns, this includes the column count.
144 /// @param p_element_padding The padding in bytes after each array
145 /// element to satisfy alignment requirements (stride - size).
146 /// @param p_float_type The float type of the member.
147 /// @param p_vec_size The component count of a single column (vector
148 /// length for non-matrix types, row count for matrices). 0 if not
149 /// applicable.
150 /// @param p_columns The number of columns. 1 for scalars and vectors;
151 /// N for an NxN matrix. 0 if not applicable.
152 /// @param p_underlying_type The underlying type category, used for
153 /// runtime validation.
154 StructMember(std::string p_type,
155 spirv_cross::SPIRType::BaseType p_base_type,
156 std::string p_name,
157 size_t p_offset,
158 size_t p_size,
159 size_t p_byte_length,
160 std::optional<size_t> p_array_elements,
161 size_t p_element_padding,
162 std::optional<std::string> p_float_type = std::nullopt,
163 size_t p_vec_size = 0u,
164 size_t p_columns = 0u,
165 UnderlyingType p_underlying_type = UnderlyingType::kOther)
166 : type(std::move(p_type)),
167 base_type(p_base_type),
168 name(std::move(p_name)),
169 offset(p_offset),
170 size(p_size),
171 byte_length(p_byte_length),
172 array_elements(p_array_elements),
173 element_padding(p_element_padding),
174 float_type(std::move(p_float_type)),
175 vec_size(p_vec_size),
176 columns(p_columns),
178};
179
181 public:
188
189 Reflector(Options options,
190 const std::shared_ptr<const spirv_cross::ParsedIR>& ir,
191 const std::shared_ptr<fml::Mapping>& shader_data,
192 const CompilerBackend& compiler);
193
195
196 bool IsValid() const;
197
198 std::shared_ptr<fml::Mapping> GetReflectionJSON() const;
199
200 std::shared_ptr<fml::Mapping> GetReflectionHeader() const;
201
202 std::shared_ptr<fml::Mapping> GetReflectionCC() const;
203
204 std::shared_ptr<RuntimeStageData::Shader> GetRuntimeStageShaderData() const;
205
206 std::shared_ptr<ShaderBundleData> GetShaderBundleData() const;
207
208 private:
209 struct StructDefinition {
210 std::string name;
211 size_t byte_length = 0u;
212 std::vector<StructMember> members;
213 };
214
215 struct BindPrototypeArgument {
216 std::string type_name;
217 std::string argument_name;
218 };
219
220 struct BindPrototype {
221 std::string name;
222 std::string return_type;
223 std::string docstring;
224 std::string descriptor_type = "";
225 std::vector<BindPrototypeArgument> args;
226 };
227
228 const Options options_;
229 const std::shared_ptr<const spirv_cross::ParsedIR> ir_;
230 const std::shared_ptr<fml::Mapping> shader_data_;
231 const CompilerBackend compiler_;
232 std::unique_ptr<const nlohmann::json> template_arguments_;
233 std::shared_ptr<fml::Mapping> reflection_header_;
234 std::shared_ptr<fml::Mapping> reflection_cc_;
235 std::shared_ptr<RuntimeStageData::Shader> runtime_stage_shader_;
236 std::shared_ptr<ShaderBundleData> shader_bundle_data_;
237 bool is_valid_ = false;
238
239 std::optional<nlohmann::json> GenerateTemplateArguments() const;
240
241 std::shared_ptr<fml::Mapping> GenerateReflectionHeader() const;
242
243 std::shared_ptr<fml::Mapping> GenerateReflectionCC() const;
244
245 std::shared_ptr<RuntimeStageData::Shader> GenerateRuntimeStageData() const;
246
247 std::shared_ptr<ShaderBundleData> GenerateShaderBundleData() const;
248
249 std::shared_ptr<fml::Mapping> InflateTemplate(std::string_view tmpl) const;
250
251 std::optional<nlohmann::json::object_t> ReflectResource(
252 const spirv_cross::Resource& resource,
253 std::optional<size_t> offset) const;
254
255 std::optional<nlohmann::json::array_t> ReflectResources(
256 const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
257 bool compute_offsets = false) const;
258
259 std::vector<size_t> ComputeOffsets(
260 const spirv_cross::SmallVector<spirv_cross::Resource>& resources) const;
261
262 std::optional<size_t> GetOffset(spirv_cross::ID id,
263 const std::vector<size_t>& offsets) const;
264
265 std::optional<nlohmann::json::object_t> ReflectType(
266 const spirv_cross::TypeID& type_id) const;
267
268 nlohmann::json::object_t EmitStructDefinition(
269 std::optional<Reflector::StructDefinition> struc) const;
270
271 std::optional<StructDefinition> ReflectStructDefinition(
272 const spirv_cross::TypeID& type_id) const;
273
274 std::vector<BindPrototype> ReflectBindPrototypes(
275 const spirv_cross::ShaderResources& resources,
276 spv::ExecutionModel execution_model) const;
277
278 nlohmann::json::array_t EmitBindPrototypes(
279 const spirv_cross::ShaderResources& resources,
280 spv::ExecutionModel execution_model) const;
281
282 std::optional<StructDefinition> ReflectPerVertexStructDefinition(
283 const spirv_cross::SmallVector<spirv_cross::Resource>& stage_inputs)
284 const;
285
286 std::optional<std::string> GetMemberNameAtIndexIfExists(
287 const spirv_cross::SPIRType& parent_type,
288 size_t index) const;
289
290 std::string GetMemberNameAtIndex(const spirv_cross::SPIRType& parent_type,
291 size_t index,
292 std::string suffix = "") const;
293
294 std::vector<StructMember> ReadStructMembers(
295 const spirv_cross::TypeID& type_id) const;
296
297 std::optional<uint32_t> GetArrayElements(
298 const spirv_cross::SPIRType& type) const;
299
300 template <uint32_t Size>
301 uint32_t GetArrayStride(const spirv_cross::SPIRType& struct_type,
302 const spirv_cross::SPIRType& member_type,
303 uint32_t index) const {
304 auto element_count = GetArrayElements(member_type).value_or(1);
305 if (element_count <= 1) {
306 return Size;
307 }
308 return compiler_->type_struct_member_array_stride(struct_type, index);
309 };
310
311 Reflector(const Reflector&) = delete;
312
313 Reflector& operator=(const Reflector&) = delete;
314};
315
316} // namespace compiler
317} // namespace impeller
318
319#endif // FLUTTER_IMPELLER_COMPILER_REFLECTOR_H_
Reflector(Options options, const std::shared_ptr< const spirv_cross::ParsedIR > &ir, const std::shared_ptr< fml::Mapping > &shader_data, const CompilerBackend &compiler)
Definition reflector.cc:64
std::shared_ptr< fml::Mapping > GetReflectionJSON() const
Definition reflector.cc:110
std::shared_ptr< fml::Mapping > GetReflectionCC() const
Definition reflector.cc:127
std::shared_ptr< RuntimeStageData::Shader > GetRuntimeStageShaderData() const
Definition reflector.cc:131
std::shared_ptr< ShaderBundleData > GetShaderBundleData() const
Definition reflector.cc:136
std::shared_ptr< fml::Mapping > GetReflectionHeader() const
Definition reflector.cc:123
std::string type_name
G_BEGIN_DECLS G_MODULE_EXPORT FlValue * args
#define FML_UNREACHABLE()
Definition logging.h:128
TSize< Scalar > Size
Definition size.h:159
Definition ref_ptr.h:261
impeller::ShaderType type
static std::string BaseTypeToString(spirv_cross::SPIRType::BaseType type)
Definition reflector.h:52
std::optional< size_t > array_elements
Definition reflector.h:40
std::optional< std::string > float_type
Definition reflector.h:42
StructMember(std::string p_type, spirv_cross::SPIRType::BaseType p_base_type, std::string p_name, size_t p_offset, size_t p_size, size_t p_byte_length, std::optional< size_t > p_array_elements, size_t p_element_padding, std::optional< std::string > p_float_type=std::nullopt, size_t p_vec_size=0u, size_t p_columns=0u, UnderlyingType p_underlying_type=UnderlyingType::kOther)
Constructs a new StructMember.
Definition reflector.h:154
static UnderlyingType DetermineUnderlyingType(spirv_cross::SPIRType::BaseType type)
Definition reflector.h:97
spirv_cross::SPIRType::BaseType base_type
Definition reflector.h:35