Flutter Impeller
runtime_stage.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 <array>
8 #include <memory>
9 
10 #include "fml/mapping.h"
14 #include "impeller/runtime_stage/runtime_stage_flatbuffers.h"
15 #include "runtime_stage_types_flatbuffers.h"
16 
17 namespace impeller {
18 
19 static RuntimeUniformType ToType(fb::UniformDataType type) {
20  switch (type) {
27  }
28  FML_UNREACHABLE();
29 }
30 
31 static RuntimeShaderStage ToShaderStage(fb::Stage stage) {
32  switch (stage) {
33  case fb::Stage::kVertex:
35  case fb::Stage::kFragment:
37  case fb::Stage::kCompute:
39  }
40  FML_UNREACHABLE();
41 }
42 
43 /// The generated name from GLSLang/shaderc for the UBO containing non-opaque
44 /// uniforms specified in the user-written runtime effect shader.
45 ///
46 /// Vulkan does not allow non-opaque uniforms outside of a UBO.
47 const char* RuntimeStage::kVulkanUBOName =
48  "_RESERVED_IDENTIFIER_FIXUP_gl_DefaultUniformBlock";
49 
50 std::unique_ptr<RuntimeStage> RuntimeStage::RuntimeStageIfPresent(
51  const fb::RuntimeStage* runtime_stage,
52  const std::shared_ptr<fml::Mapping>& payload) {
53  if (!runtime_stage) {
54  return nullptr;
55  }
56 
57  return std::unique_ptr<RuntimeStage>(
58  new RuntimeStage(runtime_stage, payload));
59 }
60 
62  const std::shared_ptr<fml::Mapping>& payload) {
63  if (payload == nullptr || !payload->GetMapping()) {
64  return {};
65  }
66  if (!fb::RuntimeStagesBufferHasIdentifier(payload->GetMapping())) {
67  return {};
68  }
69 
70  auto raw_stages = fb::GetRuntimeStages(payload->GetMapping());
71  return {
73  RuntimeStageIfPresent(raw_stages->sksl(), payload)},
75  RuntimeStageIfPresent(raw_stages->metal(), payload)},
77  RuntimeStageIfPresent(raw_stages->opengles(), payload)},
79  RuntimeStageIfPresent(raw_stages->vulkan(), payload)},
80  };
81 }
82 
83 RuntimeStage::RuntimeStage(const fb::RuntimeStage* runtime_stage,
84  const std::shared_ptr<fml::Mapping>& payload)
85  : payload_(payload) {
86  FML_DCHECK(runtime_stage);
87 
88  stage_ = ToShaderStage(runtime_stage->stage());
89  entrypoint_ = runtime_stage->entrypoint()->str();
90 
91  auto* uniforms = runtime_stage->uniforms();
92 
93  // Note: image bindings are screwy and will always have the same offset.
94  // track the binding of the UBO to determine where the image bindings go.
95  // This is only guaranteed to give us the correct bindings if there is a
96  // single sampler2D.
97  std::optional<size_t> ubo_id;
98  if (uniforms) {
99  for (auto i = uniforms->begin(), end = uniforms->end(); i != end; i++) {
101  desc.name = i->name()->str();
102  desc.location = i->location();
103  desc.binding = i->binding();
104  desc.type = ToType(i->type());
105  if (desc.type == kStruct) {
106  ubo_id = desc.location;
107  desc.binding = desc.location;
108  }
110  static_cast<size_t>(i->rows()), static_cast<size_t>(i->columns())};
111  desc.bit_width = i->bit_width();
112  desc.array_elements = i->array_elements();
113  if (i->struct_layout()) {
114  for (const auto& byte_type : *i->struct_layout()) {
115  desc.struct_layout.push_back(static_cast<uint8_t>(byte_type));
116  }
117  }
118  desc.struct_float_count = i->struct_float_count();
119  uniforms_.push_back(std::move(desc));
120  }
121  }
122 
123  code_mapping_ = std::make_shared<fml::NonOwnedMapping>(
124  runtime_stage->shader()->data(), //
125  runtime_stage->shader()->size(), //
126  [payload = payload_](auto, auto) {} //
127  );
128 
129  size_t binding = 64;
130  if (ubo_id.has_value() && ubo_id.value() == binding) {
131  binding++;
132  }
133  for (auto& uniform : uniforms_) {
134  if (uniform.type == kSampledImage) {
135  uniform.binding = binding;
136  binding++;
137  if (ubo_id.has_value() && ubo_id.value() == binding) {
138  binding++;
139  }
140  }
141  }
142 
143  for (const auto& uniform : GetUniforms()) {
144  if (uniform.type == kStruct) {
145  descriptor_set_layouts_.push_back(DescriptorSetLayout{
146  static_cast<uint32_t>(uniform.location),
149  });
150  } else if (uniform.type == kSampledImage) {
151  descriptor_set_layouts_.push_back(DescriptorSetLayout{
152  static_cast<uint32_t>(uniform.binding),
155  });
156  }
157  }
158  is_valid_ = true;
159 }
160 
161 RuntimeStage::~RuntimeStage() = default;
164 
165 bool RuntimeStage::IsValid() const {
166  return is_valid_;
167 }
168 
169 const std::shared_ptr<fml::Mapping>& RuntimeStage::GetCodeMapping() const {
170  return code_mapping_;
171 }
172 
173 const std::vector<RuntimeUniformDescription>& RuntimeStage::GetUniforms()
174  const {
175  return uniforms_;
176 }
177 
179  const std::string& name) const {
180  for (const auto& uniform : uniforms_) {
181  if (uniform.name == name) {
182  return &uniform;
183  }
184  }
185  return nullptr;
186 }
187 
188 const std::string& RuntimeStage::GetEntrypoint() const {
189  return entrypoint_;
190 }
191 
193  return stage_;
194 }
195 
196 bool RuntimeStage::IsDirty() const {
197  return is_dirty_;
198 }
199 
201  is_dirty_ = false;
202 }
203 
204 const std::vector<DescriptorSetLayout>& RuntimeStage::GetDescriptorSetLayouts()
205  const {
206  return descriptor_set_layouts_;
207 }
208 
209 } // namespace impeller
impeller::RuntimeStage::~RuntimeStage
~RuntimeStage()
impeller::RuntimeUniformDescription
Definition: runtime_types.h:39
impeller::kFloat
@ kFloat
Definition: runtime_types.h:23
impeller::RuntimeStage::GetShaderStage
RuntimeShaderStage GetShaderStage() const
Definition: runtime_stage.cc:192
impeller::DescriptorSetLayout
Definition: shader_types.h:162
impeller::ToType
static RuntimeUniformType ToType(fb::UniformDataType type)
Definition: runtime_stage.cc:19
impeller::RuntimeShaderStage
RuntimeShaderStage
Definition: runtime_types.h:28
impeller::RuntimeStageBackend::kVulkan
@ kVulkan
impeller::RuntimeUniformDescription::binding
size_t binding
Location, but for Vulkan.
Definition: runtime_types.h:43
impeller::RuntimeStage::RuntimeStage
RuntimeStage(const fb::RuntimeStage *runtime_stage, const std::shared_ptr< fml::Mapping > &payload)
Definition: runtime_stage.cc:83
impeller::RuntimeUniformDescription::dimensions
RuntimeUniformDimensions dimensions
Definition: runtime_types.h:45
impeller::RuntimeStage::DecodeRuntimeStages
static Map DecodeRuntimeStages(const std::shared_ptr< fml::Mapping > &payload)
Definition: runtime_stage.cc:61
impeller::RuntimeStage::kVulkanUBOName
static const char * kVulkanUBOName
Definition: runtime_stage.h:22
impeller::kSampledImage
@ kSampledImage
Definition: runtime_types.h:24
validation.h
impeller::RuntimeStage
Definition: runtime_stage.h:20
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
runtime_types.h
impeller::RuntimeStageBackend::kOpenGLES
@ kOpenGLES
impeller::RuntimeUniformDimensions
Definition: runtime_types.h:34
impeller::RuntimeStage::GetUniforms
const std::vector< RuntimeUniformDescription > & GetUniforms() const
Definition: runtime_stage.cc:173
impeller::RuntimeShaderStage::kVertex
@ kVertex
impeller::RuntimeStage::operator=
RuntimeStage & operator=(RuntimeStage &&)
impeller::RuntimeStage::GetUniform
const RuntimeUniformDescription * GetUniform(const std::string &name) const
Definition: runtime_stage.cc:178
impeller::RuntimeShaderStage::kFragment
@ kFragment
runtime_stage.h
impeller::RuntimeStage::GetDescriptorSetLayouts
const std::vector< DescriptorSetLayout > & GetDescriptorSetLayouts() const
Definition: runtime_stage.cc:204
impeller::RuntimeUniformType
RuntimeUniformType
Definition: runtime_types.h:22
impeller::RuntimeUniformDescription::name
std::string name
Definition: runtime_types.h:40
impeller::RuntimeStage::SetClean
void SetClean()
Definition: runtime_stage.cc:200
type
GLenum type
Definition: blit_command_gles.cc:126
impeller::RuntimeUniformDescription::struct_float_count
size_t struct_float_count
Definition: runtime_types.h:49
impeller::ShaderStage::kFragment
@ kFragment
impeller::RuntimeUniformDescription::struct_layout
std::vector< uint8_t > struct_layout
Definition: runtime_types.h:48
impeller::RuntimeUniformDescription::type
RuntimeUniformType type
Definition: runtime_types.h:44
impeller::kStruct
@ kStruct
Definition: runtime_types.h:25
impeller::DescriptorType::kSampledImage
@ kSampledImage
impeller::RuntimeUniformDescription::location
size_t location
Definition: runtime_types.h:41
impeller::DescriptorType::kUniformBuffer
@ kUniformBuffer
impeller::RuntimeUniformDescription::bit_width
size_t bit_width
Definition: runtime_types.h:46
impeller::RuntimeStageBackend::kSkSL
@ kSkSL
impeller::RuntimeStage::IsValid
bool IsValid() const
Definition: runtime_stage.cc:165
impeller::RuntimeShaderStage::kCompute
@ kCompute
impeller::RuntimeStage::IsDirty
bool IsDirty() const
Definition: runtime_stage.cc:196
impeller::RuntimeUniformDescription::array_elements
std::optional< size_t > array_elements
Definition: runtime_types.h:47
impeller::RuntimeStage::GetEntrypoint
const std::string & GetEntrypoint() const
Definition: runtime_stage.cc:188
shader_types.h
impeller::RuntimeStageBackend::kMetal
@ kMetal
impeller
Definition: aiks_blend_unittests.cc:18
impeller::RuntimeStage::Map
std::map< RuntimeStageBackend, std::shared_ptr< RuntimeStage > > Map
Definition: runtime_stage.h:24
impeller::RuntimeStage::GetCodeMapping
const std::shared_ptr< fml::Mapping > & GetCodeMapping() const
Definition: runtime_stage.cc:169