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  // NOLINTNEXTLINE(clang-analyzer-cplusplus.NewDeleteLeaks)
58  return std::unique_ptr<RuntimeStage>(
59  new RuntimeStage(runtime_stage, payload));
60 }
61 
63  const std::shared_ptr<fml::Mapping>& payload) {
64  if (payload == nullptr || !payload->GetMapping()) {
65  return {};
66  }
67  if (!fb::RuntimeStagesBufferHasIdentifier(payload->GetMapping())) {
68  return {};
69  }
70 
71  auto raw_stages = fb::GetRuntimeStages(payload->GetMapping());
72  return {
74  RuntimeStageIfPresent(raw_stages->sksl(), payload)},
76  RuntimeStageIfPresent(raw_stages->metal(), payload)},
78  RuntimeStageIfPresent(raw_stages->opengles(), payload)},
80  RuntimeStageIfPresent(raw_stages->opengles3(), payload)},
82  RuntimeStageIfPresent(raw_stages->vulkan(), payload)},
83  };
84 }
85 
86 RuntimeStage::RuntimeStage(const fb::RuntimeStage* runtime_stage,
87  const std::shared_ptr<fml::Mapping>& payload)
88  : payload_(payload) {
89  FML_DCHECK(runtime_stage);
90 
91  stage_ = ToShaderStage(runtime_stage->stage());
92  entrypoint_ = runtime_stage->entrypoint()->str();
93 
94  auto* uniforms = runtime_stage->uniforms();
95 
96  // Note: image bindings are screwy and will always have the same offset.
97  // track the binding of the UBO to determine where the image bindings go.
98  // This is only guaranteed to give us the correct bindings if there is a
99  // single sampler2D.
100  std::optional<size_t> ubo_id;
101  if (uniforms) {
102  for (auto i = uniforms->begin(), end = uniforms->end(); i != end; i++) {
104  desc.name = i->name()->str();
105  desc.location = i->location();
106  desc.binding = i->binding();
107  desc.type = ToType(i->type());
108  if (desc.type == kStruct) {
109  ubo_id = desc.location;
110  desc.binding = desc.location;
111  }
113  static_cast<size_t>(i->rows()), static_cast<size_t>(i->columns())};
114  desc.bit_width = i->bit_width();
115  desc.array_elements = i->array_elements();
116  if (i->struct_layout()) {
117  for (const auto& byte_type : *i->struct_layout()) {
118  desc.struct_layout.push_back(static_cast<uint8_t>(byte_type));
119  }
120  }
121  desc.struct_float_count = i->struct_float_count();
122  uniforms_.push_back(std::move(desc));
123  }
124  }
125 
126  code_mapping_ = std::make_shared<fml::NonOwnedMapping>(
127  runtime_stage->shader()->data(), //
128  runtime_stage->shader()->size(), //
129  [payload = payload_](auto, auto) {} //
130  );
131 
132  size_t binding = 64;
133  if (ubo_id.has_value() && ubo_id.value() == binding) {
134  binding++;
135  }
136  for (auto& uniform : uniforms_) {
137  if (uniform.type == kSampledImage) {
138  uniform.binding = binding;
139  binding++;
140  if (ubo_id.has_value() && ubo_id.value() == binding) {
141  binding++;
142  }
143  }
144  }
145 
146  for (const auto& uniform : GetUniforms()) {
147  if (uniform.type == kStruct) {
148  descriptor_set_layouts_.push_back(DescriptorSetLayout{
149  static_cast<uint32_t>(uniform.location),
152  });
153  } else if (uniform.type == kSampledImage) {
154  descriptor_set_layouts_.push_back(DescriptorSetLayout{
155  static_cast<uint32_t>(uniform.binding),
158  });
159  }
160  }
161  is_valid_ = true;
162 }
163 
164 RuntimeStage::~RuntimeStage() = default;
167 
168 bool RuntimeStage::IsValid() const {
169  return is_valid_;
170 }
171 
172 const std::shared_ptr<fml::Mapping>& RuntimeStage::GetCodeMapping() const {
173  return code_mapping_;
174 }
175 
176 const std::vector<RuntimeUniformDescription>& RuntimeStage::GetUniforms()
177  const {
178  return uniforms_;
179 }
180 
182  const std::string& name) const {
183  for (const auto& uniform : uniforms_) {
184  if (uniform.name == name) {
185  return &uniform;
186  }
187  }
188  return nullptr;
189 }
190 
191 const std::string& RuntimeStage::GetEntrypoint() const {
192  return entrypoint_;
193 }
194 
196  return stage_;
197 }
198 
199 bool RuntimeStage::IsDirty() const {
200  return is_dirty_;
201 }
202 
204  is_dirty_ = false;
205 }
206 
207 const std::vector<DescriptorSetLayout>& RuntimeStage::GetDescriptorSetLayouts()
208  const {
209  return descriptor_set_layouts_;
210 }
211 
212 } // namespace impeller
GLenum type
const std::string & GetEntrypoint() const
RuntimeStage & operator=(RuntimeStage &&)
const std::vector< RuntimeUniformDescription > & GetUniforms() const
const RuntimeUniformDescription * GetUniform(const std::string &name) const
std::map< RuntimeStageBackend, std::shared_ptr< RuntimeStage > > Map
Definition: runtime_stage.h:24
static const char * kVulkanUBOName
Definition: runtime_stage.h:22
static Map DecodeRuntimeStages(const std::shared_ptr< fml::Mapping > &payload)
const std::shared_ptr< fml::Mapping > & GetCodeMapping() const
const std::vector< DescriptorSetLayout > & GetDescriptorSetLayouts() const
RuntimeShaderStage GetShaderStage() const
RuntimeStage(const fb::RuntimeStage *runtime_stage, const std::shared_ptr< fml::Mapping > &payload)
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
static RuntimeUniformType ToType(fb::UniformDataType type)
RuntimeUniformDimensions dimensions
Definition: runtime_types.h:47
std::vector< uint8_t > struct_layout
Definition: runtime_types.h:50
std::optional< size_t > array_elements
Definition: runtime_types.h:49
size_t binding
Location, but for Vulkan.
Definition: runtime_types.h:45
const size_t end