Flutter Impeller
shader_types.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_CORE_SHADER_TYPES_H_
6 #define FLUTTER_IMPELLER_CORE_SHADER_TYPES_H_
7 
8 #include <cstddef>
9 #include <cstdint>
10 #include <optional>
11 #include <string_view>
12 #include <vector>
13 
14 #include "flutter/fml/hash_combine.h"
15 #include "flutter/fml/logging.h"
17 #include "impeller/geometry/half.h"
19 
20 namespace impeller {
21 
22 enum class ShaderStage {
23  kUnknown,
24  kVertex,
25  kFragment,
26  kCompute,
27 };
28 
30  switch (stage) {
32  return ShaderStage::kVertex;
36  return ShaderStage::kCompute;
37  }
38  FML_UNREACHABLE();
39 }
40 
41 enum class ShaderType {
42  kUnknown,
43  kVoid,
44  kBoolean,
49  kSignedInt,
54  kHalfFloat,
55  kFloat,
56  kDouble,
57  kStruct,
58  kImage,
60  kSampler,
61 };
62 
63 // This is a separate type from ShaderType because ShaderType is used for
64 // OpenGLES's attrib type which doesn't map to things like vec4.
65 enum class ShaderFloatType {
66  kFloat,
67  kVec2,
68  kVec3,
69  kVec4,
70  kMat2,
71  kMat3,
72  kMat4,
73 };
74 
77  std::string name;
78  size_t offset;
79  size_t size;
80  size_t byte_length;
81  std::optional<size_t> array_elements;
82  std::optional<ShaderFloatType> float_type;
83 };
84 
85 /// @brief Derive the `ShaderFloatType` from the base `ShaderType` and
86 /// the (vec_size, columns) dimensions reported by SPIR-V Cross.
87 ///
88 /// `vec_size` is the component count of a single column (the vector length
89 /// for non-matrix types, the row count for matrices). `columns` is 1 for
90 /// vectors and N for an NxN matrix. Returns `std::nullopt` for non-float
91 /// types and for shapes that don't map to a `ShaderFloatType`.
92 constexpr std::optional<ShaderFloatType> DeriveShaderFloatType(ShaderType type,
93  size_t vec_size,
94  size_t columns) {
95  if (type != ShaderType::kFloat) {
96  return std::nullopt;
97  }
98  if (columns == 1) {
99  switch (vec_size) {
100  case 1:
102  case 2:
103  return ShaderFloatType::kVec2;
104  case 3:
105  return ShaderFloatType::kVec3;
106  case 4:
107  return ShaderFloatType::kVec4;
108  default:
109  return std::nullopt;
110  }
111  }
112  if (vec_size == columns) {
113  switch (vec_size) {
114  case 2:
115  return ShaderFloatType::kMat2;
116  case 3:
117  return ShaderFloatType::kMat3;
118  case 4:
119  return ShaderFloatType::kMat4;
120  default:
121  return std::nullopt;
122  }
123  }
124  return std::nullopt;
125 }
126 
128  // This must match the uniform name in the shader program.
129  std::string name;
130  std::vector<ShaderStructMemberMetadata> members;
131 };
132 
133 /// @brief Metadata required to bind a buffer.
134 ///
135 /// OpenGL binding requires the usage of the separate shader metadata struct.
137  /// @brief The name of the uniform slot.
138  const char* name;
139 
140  /// @brief `ext_res_0` is the Metal binding value.
141  size_t ext_res_0;
142 
143  /// @brief The Vulkan descriptor set index.
144  size_t set;
145 
146  /// @brief The Vulkan binding value.
147  size_t binding;
148 };
149 
150 /// @brief Metadata required to bind a combined texture and sampler.
151 ///
152 /// OpenGL binding requires the usage of the separate shader metadata struct.
154  /// @brief The name of the uniform slot.
155  const char* name;
156 
157  /// @brief `ext_res_0` is the Metal binding value.
159 
160  /// @brief The Vulkan descriptor set index.
161  size_t set;
162 
163  /// @brief The Vulkan binding value.
164  size_t binding;
165 };
166 
167 /// @brief The format of a single vertex attribute, combining its scalar kind,
168 /// bit width, and component count.
169 ///
170 /// Each backend maps these values to its own native vertex format, so
171 /// this is the shared vocabulary for vertex inputs. The values are
172 /// currently derived from a reflected `ShaderStageIOSlot` (see
173 /// `ShaderStageIOSlot::GetVertexAttributeFormat`), so only the kinds
174 /// that reflection produces are reachable.
176  /// Not a valid vertex attribute (a matrix input, an unsupported scalar kind,
177  /// or a component count outside 1 to 4).
178  kInvalid,
179 
180  kFloat32,
181  kFloat32x2,
182  kFloat32x3,
183  kFloat32x4,
184 
185  kFloat16,
186  kFloat16x2,
187  kFloat16x3,
188  kFloat16x4,
189 
190  kSInt8,
191  kSInt8x2,
192  kSInt8x3,
193  kSInt8x4,
194 
195  kUInt8,
196  kUInt8x2,
197  kUInt8x3,
198  kUInt8x4,
199 
200  kSInt16,
201  kSInt16x2,
202  kSInt16x3,
203  kSInt16x4,
204 
205  kUInt16,
206  kUInt16x2,
207  kUInt16x3,
208  kUInt16x4,
209 
210  kSInt32,
211  kSInt32x2,
212  kSInt32x3,
213  kSInt32x4,
214 
215  kUInt32,
216  kUInt32x2,
217  kUInt32x3,
218  kUInt32x4,
219 };
220 
222  const char* name;
223  size_t location;
224  size_t set;
225  size_t binding;
227  size_t bit_width;
228  size_t vec_size;
229  size_t columns;
230  size_t offset;
232 
233  constexpr size_t GetHash() const {
234  return fml::HashCombine(name, location, set, binding, type, bit_width,
236  }
237 
238  constexpr bool operator==(const ShaderStageIOSlot& other) const {
239  return name == other.name && //
240  location == other.location && //
241  set == other.set && //
242  binding == other.binding && //
243  type == other.type && //
244  bit_width == other.bit_width && //
245  vec_size == other.vec_size && //
246  columns == other.columns && //
247  offset == other.offset && //
249  ;
250  }
251 
252  /// @brief Derives the flat vertex attribute format from this slot's scalar
253  /// type, bit width, and component count.
254  ///
255  /// Returns `kInvalid` for matrices, component counts outside 1 to 4,
256  /// mismatched bit widths, and scalar kinds that are not valid vertex
257  /// inputs (boolean, 64-bit integers, and doubles).
259  if (columns != 1u || vec_size < 1u || vec_size > 4u) {
261  }
262  auto pick = [vec_size = vec_size](
265  switch (vec_size) {
266  case 1:
267  return x1;
268  case 2:
269  return x2;
270  case 3:
271  return x3;
272  case 4:
273  return x4;
274  default:
276  }
277  };
278  switch (type) {
279  case ShaderType::kFloat:
280  return bit_width == 32u ? pick(VertexAttributeFormat::kFloat32,
286  return bit_width == 16u ? pick(VertexAttributeFormat::kFloat16,
292  return bit_width == 8u ? pick(VertexAttributeFormat::kSInt8,
298  return bit_width == 8u ? pick(VertexAttributeFormat::kUInt8,
304  return bit_width == 16u ? pick(VertexAttributeFormat::kSInt16,
310  return bit_width == 16u ? pick(VertexAttributeFormat::kUInt16,
316  return bit_width == 32u ? pick(VertexAttributeFormat::kSInt32,
322  return bit_width == 32u ? pick(VertexAttributeFormat::kUInt32,
328  case ShaderType::kVoid:
333  case ShaderType::kDouble:
334  case ShaderType::kStruct:
335  case ShaderType::kImage:
339  }
340  FML_UNREACHABLE();
341  }
342 };
343 
344 /// @brief Whether a vertex buffer binding advances its read position once
345 /// per vertex or once per instance.
346 ///
347 /// An instance-rate binding supplies per-instance data (such as a
348 /// per-instance model transform) to an instanced draw. It maps to
349 /// `MTLVertexStepFunctionPerInstance`, `VK_VERTEX_INPUT_RATE_INSTANCE`,
350 /// and a `glVertexAttribDivisor` of 1.
351 enum class VertexInputRate {
352  /// The binding is read once per vertex. This is the default.
353  kVertex,
354  /// The binding is read once per instance.
355  kInstance,
356 };
357 
359  size_t stride;
360  size_t binding;
361  /// The rate at which this binding advances during a draw. Defaults to
362  /// per-vertex; an instanced draw reads per-instance bindings once per
363  /// instance.
365 
366  constexpr size_t GetHash() const {
367  return fml::HashCombine(stride, binding, input_rate);
368  }
369 
370  constexpr bool operator==(const ShaderStageBufferLayout& other) const {
371  return stride == other.stride && //
372  binding == other.binding && //
373  input_rate == other.input_rate;
374  }
375 };
376 
377 // These enum values were chosen to match the same values
378 // in the VK Descriptor Type enum.
379 enum class DescriptorType {
380  kSampler = 0,
381  kSampledImage = 1,
382  kImage = 2,
383  kUniformBuffer = 6,
384  kStorageBuffer = 7,
385  kInputAttachment = 10,
386 };
387 
389  uint32_t binding;
392 };
393 
394 template <size_t Size>
395 struct Padding {
396  private:
397  uint8_t pad_[Size];
398 };
399 
400 /// @brief Struct used for padding uniform buffer array elements.
401 template <typename T,
402  size_t Size,
403  class = std::enable_if_t<std::is_standard_layout_v<T>>>
404 struct Padded {
405  T value;
407 
408  Padded(T p_value) : value(p_value) {}; // NOLINT(google-explicit-constructor)
409 };
410 
411 inline constexpr Vector4 ToVector(Color color) {
412  return {color.red, color.green, color.blue, color.alpha};
413 }
414 
415 } // namespace impeller
416 
417 #endif // FLUTTER_IMPELLER_CORE_SHADER_TYPES_H_
uint32_t vec_size
uint32_t columns
VertexInputRate
Whether a vertex buffer binding advances its read position once per vertex or once per instance.
Definition: shader_types.h:351
@ kInstance
The binding is read once per instance.
@ kVertex
The binding is read once per vertex. This is the default.
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
constexpr std::optional< ShaderFloatType > DeriveShaderFloatType(ShaderType type, size_t vec_size, size_t columns)
Derive the ShaderFloatType from the base ShaderType and the (vec_size, columns) dimensions reported b...
Definition: shader_types.h:92
VertexAttributeFormat
The format of a single vertex attribute, combining its scalar kind, bit width, and component count.
Definition: shader_types.h:175
constexpr Vector4 ToVector(Color color)
Definition: shader_types.h:411
TSize< Scalar > Size
Definition: size.h:159
Scalar blue
Definition: color.h:138
Scalar alpha
Definition: color.h:143
Scalar red
Definition: color.h:128
Scalar green
Definition: color.h:133
Struct used for padding uniform buffer array elements.
Definition: shader_types.h:404
Padded(T p_value)
Definition: shader_types.h:408
Padding< Size > _PADDING_
Definition: shader_types.h:406
Metadata required to bind a combined texture and sampler.
Definition: shader_types.h:153
size_t texture_index
ext_res_0 is the Metal binding value.
Definition: shader_types.h:158
size_t set
The Vulkan descriptor set index.
Definition: shader_types.h:161
const char * name
The name of the uniform slot.
Definition: shader_types.h:155
size_t binding
The Vulkan binding value.
Definition: shader_types.h:164
std::vector< ShaderStructMemberMetadata > members
Definition: shader_types.h:130
constexpr size_t GetHash() const
Definition: shader_types.h:366
constexpr bool operator==(const ShaderStageBufferLayout &other) const
Definition: shader_types.h:370
constexpr bool operator==(const ShaderStageIOSlot &other) const
Definition: shader_types.h:238
constexpr size_t GetHash() const
Definition: shader_types.h:233
constexpr VertexAttributeFormat GetVertexAttributeFormat() const
Derives the flat vertex attribute format from this slot's scalar type, bit width, and component count...
Definition: shader_types.h:258
std::optional< ShaderFloatType > float_type
Definition: shader_types.h:82
std::optional< size_t > array_elements
Definition: shader_types.h:81
Metadata required to bind a buffer.
Definition: shader_types.h:136
size_t binding
The Vulkan binding value.
Definition: shader_types.h:147
size_t ext_res_0
ext_res_0 is the Metal binding value.
Definition: shader_types.h:141
size_t set
The Vulkan descriptor set index.
Definition: shader_types.h:144
const char * name
The name of the uniform slot.
Definition: shader_types.h:138