Flutter Impeller
shader_bundle_data.cc
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 
6 
7 #include <optional>
8 
9 #include "impeller/shader_bundle/shader_bundle_flatbuffers.h"
10 
12 
13 namespace impeller {
14 namespace compiler {
15 
16 ShaderBundleData::ShaderBundleData(std::string entrypoint,
17  spv::ExecutionModel stage,
18  TargetPlatform target_platform)
19  : entrypoint_(std::move(entrypoint)),
20  stage_(stage),
21  target_platform_(target_platform) {}
22 
24 
26  uniform_structs_.emplace_back(std::move(uniform_struct));
27 }
28 
30  uniform_textures_.emplace_back(std::move(uniform_texture));
31 }
32 
34  inputs_.emplace_back(std::move(input));
35 }
36 
37 void ShaderBundleData::SetShaderData(std::shared_ptr<fml::Mapping> shader) {
38  shader_ = std::move(shader);
39 }
40 
41 static std::optional<fb::shaderbundle::ShaderStage> ToStage(
42  spv::ExecutionModel stage) {
43  switch (stage) {
44  case spv::ExecutionModel::ExecutionModelVertex:
45  return fb::shaderbundle::ShaderStage::kVertex;
46  case spv::ExecutionModel::ExecutionModelFragment:
47  return fb::shaderbundle::ShaderStage::kFragment;
48  case spv::ExecutionModel::ExecutionModelGLCompute:
49  return fb::shaderbundle::ShaderStage::kCompute;
50  default:
51  return std::nullopt;
52  }
53  FML_UNREACHABLE();
54 }
55 
56 static std::optional<fb::shaderbundle::UniformDataType> ToUniformType(
57  spirv_cross::SPIRType::BaseType type) {
58  switch (type) {
59  case spirv_cross::SPIRType::Boolean:
60  return fb::shaderbundle::UniformDataType::kBoolean;
61  case spirv_cross::SPIRType::SByte:
62  return fb::shaderbundle::UniformDataType::kSignedByte;
63  case spirv_cross::SPIRType::UByte:
64  return fb::shaderbundle::UniformDataType::kUnsignedByte;
65  case spirv_cross::SPIRType::Short:
66  return fb::shaderbundle::UniformDataType::kSignedShort;
67  case spirv_cross::SPIRType::UShort:
68  return fb::shaderbundle::UniformDataType::kUnsignedShort;
69  case spirv_cross::SPIRType::Int:
70  return fb::shaderbundle::UniformDataType::kSignedInt;
71  case spirv_cross::SPIRType::UInt:
72  return fb::shaderbundle::UniformDataType::kUnsignedInt;
73  case spirv_cross::SPIRType::Int64:
74  return fb::shaderbundle::UniformDataType::kSignedInt64;
75  case spirv_cross::SPIRType::UInt64:
76  return fb::shaderbundle::UniformDataType::kUnsignedInt64;
77  case spirv_cross::SPIRType::Half:
78  return fb::shaderbundle::UniformDataType::kHalfFloat;
79  case spirv_cross::SPIRType::Float:
81  case spirv_cross::SPIRType::Double:
82  return fb::shaderbundle::UniformDataType::kDouble;
83  case spirv_cross::SPIRType::SampledImage:
85  case spirv_cross::SPIRType::AccelerationStructure:
86  case spirv_cross::SPIRType::AtomicCounter:
87  case spirv_cross::SPIRType::Char:
88  case spirv_cross::SPIRType::ControlPointArray:
89  case spirv_cross::SPIRType::Image:
90  case spirv_cross::SPIRType::Interpolant:
91  case spirv_cross::SPIRType::RayQuery:
92  case spirv_cross::SPIRType::Sampler:
93  case spirv_cross::SPIRType::Struct:
94  case spirv_cross::SPIRType::Unknown:
95  case spirv_cross::SPIRType::Void:
96  return std::nullopt;
97  }
98  FML_UNREACHABLE();
99 }
100 static std::optional<fb::shaderbundle::InputDataType> ToInputType(
101  spirv_cross::SPIRType::BaseType type) {
102  switch (type) {
103  case spirv_cross::SPIRType::Boolean:
104  return fb::shaderbundle::InputDataType::kBoolean;
105  case spirv_cross::SPIRType::SByte:
106  return fb::shaderbundle::InputDataType::kSignedByte;
107  case spirv_cross::SPIRType::UByte:
108  return fb::shaderbundle::InputDataType::kUnsignedByte;
109  case spirv_cross::SPIRType::Short:
110  return fb::shaderbundle::InputDataType::kSignedShort;
111  case spirv_cross::SPIRType::UShort:
112  return fb::shaderbundle::InputDataType::kUnsignedShort;
113  case spirv_cross::SPIRType::Int:
114  return fb::shaderbundle::InputDataType::kSignedInt;
115  case spirv_cross::SPIRType::UInt:
116  return fb::shaderbundle::InputDataType::kUnsignedInt;
117  case spirv_cross::SPIRType::Int64:
118  return fb::shaderbundle::InputDataType::kSignedInt64;
119  case spirv_cross::SPIRType::UInt64:
120  return fb::shaderbundle::InputDataType::kUnsignedInt64;
121  case spirv_cross::SPIRType::Float:
123  case spirv_cross::SPIRType::Double:
124  return fb::shaderbundle::InputDataType::kDouble;
125  case spirv_cross::SPIRType::Unknown:
126  case spirv_cross::SPIRType::Void:
127  case spirv_cross::SPIRType::Half:
128  case spirv_cross::SPIRType::AtomicCounter:
129  case spirv_cross::SPIRType::Struct:
130  case spirv_cross::SPIRType::Image:
131  case spirv_cross::SPIRType::SampledImage:
132  case spirv_cross::SPIRType::Sampler:
133  case spirv_cross::SPIRType::AccelerationStructure:
134  case spirv_cross::SPIRType::RayQuery:
135  case spirv_cross::SPIRType::ControlPointArray:
136  case spirv_cross::SPIRType::Interpolant:
137  case spirv_cross::SPIRType::Char:
138  return std::nullopt;
139  }
140  FML_UNREACHABLE();
141 }
142 
143 std::unique_ptr<fb::shaderbundle::BackendShaderT>
145  auto shader_bundle = std::make_unique<fb::shaderbundle::BackendShaderT>();
146 
147  // The high level object API is used here for writing to the buffer. This is
148  // just a convenience.
149  shader_bundle->entrypoint = entrypoint_;
150  const auto stage = ToStage(stage_);
151  if (!stage.has_value()) {
152  VALIDATION_LOG << "Invalid shader bundle.";
153  return nullptr;
154  }
155  shader_bundle->stage = stage.value();
156  // This field is ignored, so just set it to anything.
157  if (!shader_) {
158  VALIDATION_LOG << "No shader specified for shader bundle.";
159  return nullptr;
160  }
161  if (shader_->GetSize() > 0u) {
162  shader_bundle->shader = {shader_->GetMapping(),
163  shader_->GetMapping() + shader_->GetSize()};
164  }
165  for (const auto& uniform : uniform_structs_) {
166  auto desc = std::make_unique<fb::shaderbundle::ShaderUniformStructT>();
167 
168  desc->name = uniform.name;
169  if (desc->name.empty()) {
170  VALIDATION_LOG << "Uniform name cannot be empty.";
171  return nullptr;
172  }
173  desc->ext_res_0 = uniform.ext_res_0;
174  desc->set = uniform.set;
175  desc->binding = uniform.binding;
176  desc->size_in_bytes = uniform.size_in_bytes;
177 
178  for (const auto& field : uniform.fields) {
179  auto field_desc =
180  std::make_unique<fb::shaderbundle::ShaderUniformStructFieldT>();
181  field_desc->name = field.name;
182  auto type = ToUniformType(field.type);
183  if (!type.has_value()) {
184  VALIDATION_LOG << " Invalid shader type " << field.type << ".";
185  return nullptr;
186  }
187  field_desc->type = type.value();
188  field_desc->offset_in_bytes = field.offset_in_bytes;
189  field_desc->element_size_in_bytes = field.element_size_in_bytes;
190  field_desc->total_size_in_bytes = field.total_size_in_bytes;
191  field_desc->array_elements = field.array_elements.value_or(0);
192  desc->fields.push_back(std::move(field_desc));
193  }
194 
195  shader_bundle->uniform_structs.emplace_back(std::move(desc));
196  }
197 
198  for (const auto& texture : uniform_textures_) {
199  auto desc = std::make_unique<fb::shaderbundle::ShaderUniformTextureT>();
200  desc->name = texture.name;
201  if (desc->name.empty()) {
202  VALIDATION_LOG << "Uniform name cannot be empty.";
203  return nullptr;
204  }
205  desc->ext_res_0 = texture.ext_res_0;
206  desc->set = texture.set;
207  desc->binding = texture.binding;
208  shader_bundle->uniform_textures.emplace_back(std::move(desc));
209  }
210 
211  for (const auto& input : inputs_) {
212  auto desc = std::make_unique<fb::shaderbundle::ShaderInputT>();
213 
214  desc->name = input.name;
215 
216  if (desc->name.empty()) {
217  VALIDATION_LOG << "Stage input name cannot be empty.";
218  return nullptr;
219  }
220  desc->location = input.location;
221  desc->set = input.set;
222  desc->binding = input.binding;
223  auto input_type = ToInputType(input.type);
224  if (!input_type.has_value()) {
225  VALIDATION_LOG << "Invalid uniform type for runtime stage.";
226  return nullptr;
227  }
228  desc->type = input_type.value();
229  desc->bit_width = input.bit_width;
230  desc->vec_size = input.vec_size;
231  desc->columns = input.columns;
232  desc->offset = input.offset;
233 
234  shader_bundle->inputs.emplace_back(std::move(desc));
235  }
236 
237  return shader_bundle;
238 }
239 
240 } // namespace compiler
241 } // namespace impeller
GLenum type
void AddInputDescription(InputDescription input)
ShaderBundleData(std::string entrypoint, spv::ExecutionModel stage, TargetPlatform target_platform)
std::unique_ptr< fb::shaderbundle::BackendShaderT > CreateFlatbuffer() const
void AddUniformStruct(ShaderUniformStruct uniform_struct)
void SetShaderData(std::shared_ptr< fml::Mapping > shader)
void AddUniformTexture(ShaderUniformTexture uniform_texture)
static std::optional< fb::Stage > ToStage(spv::ExecutionModel stage)
static std::optional< fb::UniformDataType > ToUniformType(spirv_cross::SPIRType::BaseType type)
static std::optional< fb::InputDataType > ToInputType(spirv_cross::SPIRType::BaseType type)
Definition: comparable.h:95
#define VALIDATION_LOG
Definition: validation.h:91