| Flutter Impeller |

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"
14 #include "impeller/compiler/compiler_backend.h"
15 #include "impeller/compiler/runtime_stage_data.h"
16 #include "impeller/compiler/shader_bundle_data.h"
17 #include "inja/inja.hpp"
18 #include "spirv_common.hpp"
19 #include "spirv_msl.hpp"
20 #include "spirv_parser.hpp"
21
22 namespace impeller {
23 namespace compiler {
24
25 struct StructMember {
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 {
29 kPadding,
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 UnderlyingType underlying_type = UnderlyingType::kOther;
43
44 static std::string BaseTypeToString(spirv_cross::SPIRType::BaseType type) {
45 using Type = spirv_cross::SPIRType::BaseType;
46 switch (type) {
47 case Type::Void:
48 return "ShaderType::kVoid";
49 case Type::Boolean:
50 return "ShaderType::kBoolean";
51 case Type::SByte:
52 return "ShaderType::kSignedByte";
53 case Type::UByte:
54 return "ShaderType::kUnsignedByte";
55 case Type::Short:
56 return "ShaderType::kSignedShort";
57 case Type::UShort:
58 return "ShaderType::kUnsignedShort";
59 case Type::Int:
60 return "ShaderType::kSignedInt";
61 case Type::UInt:
62 return "ShaderType::kUnsignedInt";
63 case Type::Int64:
64 return "ShaderType::kSignedInt64";
65 case Type::UInt64:
66 return "ShaderType::kUnsignedInt64";
67 case Type::AtomicCounter:
68 return "ShaderType::kAtomicCounter";
69 case Type::Half:
70 return "ShaderType::kHalfFloat";
71 case Type::Float:
72 return "ShaderType::kFloat";
73 case Type::Double:
74 return "ShaderType::kDouble";
75 case Type::Struct:
76 return "ShaderType::kStruct";
77 case Type::Image:
78 return "ShaderType::kImage";
79 case Type::SampledImage:
80 return "ShaderType::kSampledImage";
81 case Type::Sampler:
82 return "ShaderType::kSampler";
83 default:
84 return "ShaderType::kUnknown";
85 }
86 FML_UNREACHABLE();
87 }
88
89 static UnderlyingType DetermineUnderlyingType(
90 spirv_cross::SPIRType::BaseType type) {
91 switch (type) {
92 case spirv_cross::SPIRType::Void:
93 return UnderlyingType::kPadding;
94 case spirv_cross::SPIRType::Float:
95 return UnderlyingType::kFloat;
96 case spirv_cross::SPIRType::Unknown:
97 case spirv_cross::SPIRType::Boolean:
98 case spirv_cross::SPIRType::SByte:
99 case spirv_cross::SPIRType::UByte:
100 case spirv_cross::SPIRType::Short:
101 case spirv_cross::SPIRType::UShort:
102 case spirv_cross::SPIRType::Int:
103 case spirv_cross::SPIRType::UInt:
104 case spirv_cross::SPIRType::Int64:
105 case spirv_cross::SPIRType::UInt64:
106 case spirv_cross::SPIRType::AtomicCounter:
107 case spirv_cross::SPIRType::Half:
108 case spirv_cross::SPIRType::Double:
109 case spirv_cross::SPIRType::Struct:
110 case spirv_cross::SPIRType::Image:
111 case spirv_cross::SPIRType::SampledImage:
112 case spirv_cross::SPIRType::Sampler:
113 case spirv_cross::SPIRType::AccelerationStructure:
114 case spirv_cross::SPIRType::RayQuery:
115 case spirv_cross::SPIRType::ControlPointArray:
116 case spirv_cross::SPIRType::Interpolant:
117 case spirv_cross::SPIRType::Char:
118 default:
119 return UnderlyingType::kOther;
120 }
121 FML_UNREACHABLE();
122 }
123
124 /// @brief Constructs a new StructMember.
125 ///
126 /// @param p_type The string type name (e.g. "float", "Point", "Matrix").
127 /// @param p_base_type The SPIR-V base type.
128 /// @param p_name The name of the struct member.
129 /// @param p_offset The offset in bytes from the start of the parent struct.
130 /// @param p_size The size in bytes of a single element of this type
131 /// (ignoring padding/stride).
132 /// @param p_byte_length The total size in bytes this member occupies in
133 /// the struct, including all array elements and padding.
134 /// @param p_array_elements The number of array elements. For matrices
135 /// treated as arrays of columns, this includes the column count.
136 /// @param p_element_padding The padding in bytes after each array
137 /// element to satisfy alignment requirements (stride - size).
138 /// @param p_underlying_type The underlying type category, used for
139 /// runtime validation.
140 StructMember(std::string p_type,
141 spirv_cross::SPIRType::BaseType p_base_type,
142 std::string p_name,
143 size_t p_offset,
144 size_t p_size,
145 size_t p_byte_length,
146 std::optional<size_t> p_array_elements,
147 size_t p_element_padding,
148 UnderlyingType p_underlying_type = UnderlyingType::kOther)
149 : type(std::move(p_type)),
150 base_type(p_base_type),
151 name(std::move(p_name)),
152 offset(p_offset),
153 size(p_size),
154 byte_length(p_byte_length),
155 array_elements(p_array_elements),
156 element_padding(p_element_padding),
157 underlying_type(DetermineUnderlyingType(p_base_type)) {}
158 };
159
160 class Reflector {
161 public:
162 struct Options {
163 TargetPlatform target_platform = TargetPlatform::kUnknown;
164 std::string entry_point_name;
165 std::string shader_name;
166 std::string header_file_name;
167 };
168
169 Reflector(Options options,
170 const std::shared_ptr<const spirv_cross::ParsedIR>& ir,
171 const std::shared_ptr<fml::Mapping>& shader_data,
172 const CompilerBackend& compiler);
173
174 ~Reflector();
175
176 bool IsValid() const;
177
178 std::shared_ptr<fml::Mapping> GetReflectionJSON() const;
179
180 std::shared_ptr<fml::Mapping> GetReflectionHeader() const;
181
182 std::shared_ptr<fml::Mapping> GetReflectionCC() const;
183
184 std::shared_ptr<RuntimeStageData::Shader> GetRuntimeStageShaderData() const;
185
186 std::shared_ptr<ShaderBundleData> GetShaderBundleData() const;
187
188 private:
189 struct StructDefinition {
190 std::string name;
191 size_t byte_length = 0u;
192 std::vector<StructMember> members;
193 };
194
195 struct BindPrototypeArgument {
196 std::string type_name;
197 std::string argument_name;
198 };
199
200 struct BindPrototype {
201 std::string name;
202 std::string return_type;
203 std::string docstring;
204 std::string descriptor_type = "";
205 std::vector<BindPrototypeArgument> args;
206 };
207
208 const Options options_;
209 const std::shared_ptr<const spirv_cross::ParsedIR> ir_;
210 const std::shared_ptr<fml::Mapping> shader_data_;
211 const CompilerBackend compiler_;
212 std::unique_ptr<const nlohmann::json> template_arguments_;
213 std::shared_ptr<fml::Mapping> reflection_header_;
214 std::shared_ptr<fml::Mapping> reflection_cc_;
215 std::shared_ptr<RuntimeStageData::Shader> runtime_stage_shader_;
216 std::shared_ptr<ShaderBundleData> shader_bundle_data_;
217 bool is_valid_ = false;
218
219 std::optional<nlohmann::json> GenerateTemplateArguments() const;
220
221 std::shared_ptr<fml::Mapping> GenerateReflectionHeader() const;
222
223 std::shared_ptr<fml::Mapping> GenerateReflectionCC() const;
224
225 std::shared_ptr<RuntimeStageData::Shader> GenerateRuntimeStageData() const;
226
227 std::shared_ptr<ShaderBundleData> GenerateShaderBundleData() const;
228
229 std::shared_ptr<fml::Mapping> InflateTemplate(std::string_view tmpl) const;
230
231 std::optional<nlohmann::json::object_t> ReflectResource(
232 const spirv_cross::Resource& resource,
233 std::optional<size_t> offset) const;
234
235 std::optional<nlohmann::json::array_t> ReflectResources(
236 const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
237 bool compute_offsets = false) const;
238
239 std::vector<size_t> ComputeOffsets(
240 const spirv_cross::SmallVector<spirv_cross::Resource>& resources) const;
241
242 std::optional<size_t> GetOffset(spirv_cross::ID id,
243 const std::vector<size_t>& offsets) const;
244
245 std::optional<nlohmann::json::object_t> ReflectType(
246 const spirv_cross::TypeID& type_id) const;
247
248 nlohmann::json::object_t EmitStructDefinition(
249 std::optional<Reflector::StructDefinition> struc) const;
250
251 std::optional<StructDefinition> ReflectStructDefinition(
252 const spirv_cross::TypeID& type_id) const;
253
254 std::vector<BindPrototype> ReflectBindPrototypes(
255 const spirv_cross::ShaderResources& resources,
256 spv::ExecutionModel execution_model) const;
257
258 nlohmann::json::array_t EmitBindPrototypes(
259 const spirv_cross::ShaderResources& resources,
260 spv::ExecutionModel execution_model) const;
261
262 std::optional<StructDefinition> ReflectPerVertexStructDefinition(
263 const spirv_cross::SmallVector<spirv_cross::Resource>& stage_inputs)
264 const;
265
266 std::optional<std::string> GetMemberNameAtIndexIfExists(
267 const spirv_cross::SPIRType& parent_type,
268 size_t index) const;
269
270 std::string GetMemberNameAtIndex(const spirv_cross::SPIRType& parent_type,
271 size_t index,
272 std::string suffix = "") const;
273
274 std::vector<StructMember> ReadStructMembers(
275 const spirv_cross::TypeID& type_id) const;
276
277 std::optional<uint32_t> GetArrayElements(
278 const spirv_cross::SPIRType& type) const;
279
280 template <uint32_t Size>
281 uint32_t GetArrayStride(const spirv_cross::SPIRType& struct_type,
282 const spirv_cross::SPIRType& member_type,
283 uint32_t index) const {
284 auto element_count = GetArrayElements(member_type).value_or(1);
285 if (element_count <= 1) {
286 return Size;
287 }
288 return compiler_->type_struct_member_array_stride(struct_type, index);
289 };
290
291 Reflector(const Reflector&) = delete;
292
293 Reflector& operator=(const Reflector&) = delete;
294 };
295
296 } // namespace compiler
297 } // namespace impeller
298
299 #endif // FLUTTER_IMPELLER_COMPILER_REFLECTOR_H_
type
GLenum type
Definition: blit_command_gles.cc:153
impeller::compiler::Reflector
Definition: reflector.h:160
impeller::compiler::Reflector::Reflector
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
impeller::compiler::Reflector::GetReflectionJSON
std::shared_ptr< fml::Mapping > GetReflectionJSON() const
Definition: reflector.cc:110
impeller::compiler::Reflector::IsValid
bool IsValid() const
Definition: reflector.cc:106
impeller::compiler::Reflector::GetReflectionCC
std::shared_ptr< fml::Mapping > GetReflectionCC() const
Definition: reflector.cc:127
impeller::compiler::Reflector::~Reflector
~Reflector()
impeller::compiler::Reflector::GetRuntimeStageShaderData
std::shared_ptr< RuntimeStageData::Shader > GetRuntimeStageShaderData() const
Definition: reflector.cc:131
impeller::compiler::Reflector::GetShaderBundleData
std::shared_ptr< ShaderBundleData > GetShaderBundleData() const
Definition: reflector.cc:136
impeller::compiler::Reflector::GetReflectionHeader
std::shared_ptr< fml::Mapping > GetReflectionHeader() const
Definition: reflector.cc:123
compiler_backend.h
type_name
std::string type_name
Definition: compiler_unittests.cc:130
impeller::compiler::TargetPlatform
TargetPlatform
Definition: types.h:30
impeller::compiler::TargetPlatform::kUnknown
@ kUnknown
impeller
Definition: allocation.cc:12
impeller::Size
TSize< Scalar > Size
Definition: size.h:159
std
Definition: comparable.h:95
runtime_stage_data.h
shader_bundle_data.h
impeller::compiler::CompilerBackend
Definition: compiler_backend.h:19
impeller::compiler::Reflector::Options
Definition: reflector.h:162
impeller::compiler::Reflector::Options::target_platform
TargetPlatform target_platform
Definition: reflector.h:163
impeller::compiler::Reflector::Options::entry_point_name
std::string entry_point_name
Definition: reflector.h:164
impeller::compiler::Reflector::Options::shader_name
std::string shader_name
Definition: reflector.h:165
impeller::compiler::Reflector::Options::header_file_name
std::string header_file_name
Definition: reflector.h:166
impeller::compiler::StructMember
Definition: reflector.h:25
impeller::compiler::StructMember::element_padding
size_t element_padding
Definition: reflector.h:41
impeller::compiler::StructMember::underlying_type
UnderlyingType underlying_type
Definition: reflector.h:42
impeller::compiler::StructMember::BaseTypeToString
static std::string BaseTypeToString(spirv_cross::SPIRType::BaseType type)
Definition: reflector.h:44
impeller::compiler::StructMember::type
std::string type
Definition: reflector.h:34
impeller::compiler::StructMember::array_elements
std::optional< size_t > array_elements
Definition: reflector.h:40
impeller::compiler::StructMember::size
size_t size
Definition: reflector.h:38
impeller::compiler::StructMember::StructMember
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, UnderlyingType p_underlying_type=UnderlyingType::kOther)
Constructs a new StructMember.
Definition: reflector.h:140
impeller::compiler::StructMember::offset
size_t offset
Definition: reflector.h:37
impeller::compiler::StructMember::UnderlyingType
UnderlyingType
Definition: reflector.h:28
impeller::compiler::StructMember::UnderlyingType::kOther
@ kOther
impeller::compiler::StructMember::UnderlyingType::kPadding
@ kPadding
impeller::compiler::StructMember::UnderlyingType::kFloat
@ kFloat
impeller::compiler::StructMember::byte_length
size_t byte_length
Definition: reflector.h:39
impeller::compiler::StructMember::DetermineUnderlyingType
static UnderlyingType DetermineUnderlyingType(spirv_cross::SPIRType::BaseType type)
Definition: reflector.h:89
impeller::compiler::StructMember::name
std::string name
Definition: reflector.h:36
impeller::compiler::StructMember::base_type
spirv_cross::SPIRType::BaseType base_type
Definition: reflector.h:35