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