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"
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;
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 
90  spirv_cross::SPIRType::BaseType type) {
91  switch (type) {
92  case spirv_cross::SPIRType::Void:
94  case spirv_cross::SPIRType::Float:
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  StructMember(std::string p_type,
125  spirv_cross::SPIRType::BaseType p_base_type,
126  std::string p_name,
127  size_t p_offset,
128  size_t p_size,
129  size_t p_byte_length,
130  std::optional<size_t> p_array_elements,
131  size_t p_element_padding,
132  UnderlyingType p_underlying_type = UnderlyingType::kOther)
133  : type(std::move(p_type)),
134  base_type(p_base_type),
135  name(std::move(p_name)),
136  offset(p_offset),
137  size(p_size),
138  byte_length(p_byte_length),
139  array_elements(p_array_elements),
140  element_padding(p_element_padding),
142 };
143 
144 class Reflector {
145  public:
146  struct Options {
148  std::string entry_point_name;
149  std::string shader_name;
150  std::string header_file_name;
151  };
152 
153  Reflector(Options options,
154  const std::shared_ptr<const spirv_cross::ParsedIR>& ir,
155  const std::shared_ptr<fml::Mapping>& shader_data,
156  const CompilerBackend& compiler);
157 
159 
160  bool IsValid() const;
161 
162  std::shared_ptr<fml::Mapping> GetReflectionJSON() const;
163 
164  std::shared_ptr<fml::Mapping> GetReflectionHeader() const;
165 
166  std::shared_ptr<fml::Mapping> GetReflectionCC() const;
167 
168  std::shared_ptr<RuntimeStageData::Shader> GetRuntimeStageShaderData() const;
169 
170  std::shared_ptr<ShaderBundleData> GetShaderBundleData() const;
171 
172  private:
173  struct StructDefinition {
174  std::string name;
175  size_t byte_length = 0u;
176  std::vector<StructMember> members;
177  };
178 
179  struct BindPrototypeArgument {
180  std::string type_name;
181  std::string argument_name;
182  };
183 
184  struct BindPrototype {
185  std::string name;
186  std::string return_type;
187  std::string docstring;
188  std::string descriptor_type = "";
189  std::vector<BindPrototypeArgument> args;
190  };
191 
192  const Options options_;
193  const std::shared_ptr<const spirv_cross::ParsedIR> ir_;
194  const std::shared_ptr<fml::Mapping> shader_data_;
195  const CompilerBackend compiler_;
196  std::unique_ptr<const nlohmann::json> template_arguments_;
197  std::shared_ptr<fml::Mapping> reflection_header_;
198  std::shared_ptr<fml::Mapping> reflection_cc_;
199  std::shared_ptr<RuntimeStageData::Shader> runtime_stage_shader_;
200  std::shared_ptr<ShaderBundleData> shader_bundle_data_;
201  bool is_valid_ = false;
202 
203  std::optional<nlohmann::json> GenerateTemplateArguments() const;
204 
205  std::shared_ptr<fml::Mapping> GenerateReflectionHeader() const;
206 
207  std::shared_ptr<fml::Mapping> GenerateReflectionCC() const;
208 
209  std::shared_ptr<RuntimeStageData::Shader> GenerateRuntimeStageData() const;
210 
211  std::shared_ptr<ShaderBundleData> GenerateShaderBundleData() const;
212 
213  std::shared_ptr<fml::Mapping> InflateTemplate(std::string_view tmpl) const;
214 
215  std::optional<nlohmann::json::object_t> ReflectResource(
216  const spirv_cross::Resource& resource,
217  std::optional<size_t> offset) const;
218 
219  std::optional<nlohmann::json::array_t> ReflectResources(
220  const spirv_cross::SmallVector<spirv_cross::Resource>& resources,
221  bool compute_offsets = false) const;
222 
223  std::vector<size_t> ComputeOffsets(
224  const spirv_cross::SmallVector<spirv_cross::Resource>& resources) const;
225 
226  std::optional<size_t> GetOffset(spirv_cross::ID id,
227  const std::vector<size_t>& offsets) const;
228 
229  std::optional<nlohmann::json::object_t> ReflectType(
230  const spirv_cross::TypeID& type_id) const;
231 
232  nlohmann::json::object_t EmitStructDefinition(
233  std::optional<Reflector::StructDefinition> struc) const;
234 
235  std::optional<StructDefinition> ReflectStructDefinition(
236  const spirv_cross::TypeID& type_id) const;
237 
238  std::vector<BindPrototype> ReflectBindPrototypes(
239  const spirv_cross::ShaderResources& resources,
240  spv::ExecutionModel execution_model) const;
241 
242  nlohmann::json::array_t EmitBindPrototypes(
243  const spirv_cross::ShaderResources& resources,
244  spv::ExecutionModel execution_model) const;
245 
246  std::optional<StructDefinition> ReflectPerVertexStructDefinition(
247  const spirv_cross::SmallVector<spirv_cross::Resource>& stage_inputs)
248  const;
249 
250  std::optional<std::string> GetMemberNameAtIndexIfExists(
251  const spirv_cross::SPIRType& parent_type,
252  size_t index) const;
253 
254  std::string GetMemberNameAtIndex(const spirv_cross::SPIRType& parent_type,
255  size_t index,
256  std::string suffix = "") const;
257 
258  std::vector<StructMember> ReadStructMembers(
259  const spirv_cross::TypeID& type_id) const;
260 
261  std::optional<uint32_t> GetArrayElements(
262  const spirv_cross::SPIRType& type) const;
263 
264  template <uint32_t Size>
265  uint32_t GetArrayStride(const spirv_cross::SPIRType& struct_type,
266  const spirv_cross::SPIRType& member_type,
267  uint32_t index) const {
268  auto element_count = GetArrayElements(member_type).value_or(1);
269  if (element_count <= 1) {
270  return Size;
271  }
272  return compiler_->type_struct_member_array_stride(struct_type, index);
273  };
274 
275  Reflector(const Reflector&) = delete;
276 
277  Reflector& operator=(const Reflector&) = delete;
278 };
279 
280 } // namespace compiler
281 } // namespace impeller
282 
283 #endif // FLUTTER_IMPELLER_COMPILER_REFLECTOR_H_
GLenum type
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
std::shared_ptr< fml::Mapping > GetReflectionJSON() const
Definition: reflector.cc:108
std::shared_ptr< fml::Mapping > GetReflectionCC() const
Definition: reflector.cc:125
std::shared_ptr< RuntimeStageData::Shader > GetRuntimeStageShaderData() const
Definition: reflector.cc:129
std::shared_ptr< ShaderBundleData > GetShaderBundleData() const
Definition: reflector.cc:134
std::shared_ptr< fml::Mapping > GetReflectionHeader() const
Definition: reflector.cc:121
TSize< Scalar > Size
Definition: size.h:159
Definition: comparable.h:95
UnderlyingType underlying_type
Definition: reflector.h:42
static std::string BaseTypeToString(spirv_cross::SPIRType::BaseType type)
Definition: reflector.h:44
std::optional< size_t > array_elements
Definition: reflector.h:40
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:124
static UnderlyingType DetermineUnderlyingType(spirv_cross::SPIRType::BaseType type)
Definition: reflector.h:89
spirv_cross::SPIRType::BaseType base_type
Definition: reflector.h:35