Flutter Engine Uber Docs
Docs for the entire Flutter Engine repo.
 
Loading...
Searching...
No Matches
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#include <sstream>
10
11#include "fml/mapping.h"
15#include "impeller/runtime_stage/runtime_stage_flatbuffers.h"
16#include "runtime_stage_types_flatbuffers.h"
17
18namespace impeller {
19
20static RuntimeUniformType ToType(fb::UniformDataType type) {
21 switch (type) {
22 case fb::UniformDataType::kFloat:
24 case fb::UniformDataType::kSampledImage:
26 case fb::UniformDataType::kStruct:
28 }
30}
31
32static RuntimeShaderStage ToShaderStage(fb::Stage stage) {
33 switch (stage) {
34 case fb::Stage::kVertex:
36 case fb::Stage::kFragment:
38 case fb::Stage::kCompute:
40 }
42}
43
44/// The generated name from GLSLang/shaderc for the UBO containing non-opaque
45/// uniforms specified in the user-written runtime effect shader.
46///
47/// Vulkan does not allow non-opaque uniforms outside of a UBO.
49 "_RESERVED_IDENTIFIER_FIXUP_gl_DefaultUniformBlock";
50
51absl::StatusOr<RuntimeStage> RuntimeStage::Create(
52 const fb::RuntimeStage* runtime_stage,
53 const std::shared_ptr<fml::Mapping>& payload) {
54 if (!runtime_stage) {
55 return absl::InvalidArgumentError("Runtime stage is null.");
56 }
57
58 RuntimeStage stage(payload);
59 stage.stage_ = ToShaderStage(runtime_stage->stage());
60 stage.entrypoint_ = runtime_stage->entrypoint()->str();
61
62 auto* uniforms = runtime_stage->uniforms();
63
64 // Note: image bindings are screwy and will always have the same offset.
65 // track the binding of the UBO to determine where the image bindings go.
66 // This is only guaranteed to give us the correct bindings if there is a
67 // single sampler2D.
68 std::optional<size_t> ubo_id;
69 if (uniforms) {
70 for (auto i = uniforms->begin(), end = uniforms->end(); i != end; i++) {
72 desc.name = i->name()->str();
73 desc.location = i->location();
74 desc.binding = i->binding();
75 desc.type = ToType(i->type());
76 if (desc.type == kStruct) {
77 ubo_id = desc.location;
78 desc.binding = desc.location;
79 }
81 static_cast<size_t>(i->rows()), static_cast<size_t>(i->columns())};
82 desc.bit_width = i->bit_width();
83 desc.array_elements = i->array_elements();
84 if (i->struct_layout()) {
85 for (const auto& byte_type : *i->struct_layout()) {
86 desc.struct_layout.push_back(static_cast<uint8_t>(byte_type));
87 }
88 }
89 desc.struct_float_count = i->struct_float_count();
90 stage.uniforms_.push_back(std::move(desc));
91 }
92 }
93
94 stage.code_mapping_ = std::make_shared<fml::NonOwnedMapping>(
95 runtime_stage->shader()->data(), //
96 runtime_stage->shader()->size(), //
97 [payload = stage.payload_](auto, auto) {} //
98 );
99
100 size_t binding = 64;
101 if (ubo_id.has_value() && ubo_id.value() == binding) {
102 binding++;
103 }
104 for (auto& uniform : stage.uniforms_) {
105 if (uniform.type == kSampledImage) {
106 uniform.binding = binding;
107 binding++;
108 if (ubo_id.has_value() && ubo_id.value() == binding) {
109 binding++;
110 }
111 }
112 }
113
114 for (const auto& uniform : stage.GetUniforms()) {
115 if (uniform.type == kStruct) {
116 stage.descriptor_set_layouts_.push_back(DescriptorSetLayout{
117 static_cast<uint32_t>(uniform.location),
120 });
121 } else if (uniform.type == kSampledImage) {
122 stage.descriptor_set_layouts_.push_back(DescriptorSetLayout{
123 static_cast<uint32_t>(uniform.binding),
126 });
127 }
128 }
129
130 return stage;
131}
132
133std::unique_ptr<RuntimeStage> RuntimeStage::RuntimeStageIfPresent(
134 const fb::RuntimeStage* runtime_stage,
135 const std::shared_ptr<fml::Mapping>& payload) {
136 auto stage = Create(runtime_stage, payload);
137 if (!stage.ok()) {
138 return nullptr;
139 }
140 return std::make_unique<RuntimeStage>(std::move(*stage));
141}
142
143absl::StatusOr<RuntimeStage::Map> RuntimeStage::DecodeRuntimeStages(
144 const std::shared_ptr<fml::Mapping>& payload) {
145 if (payload == nullptr || !payload->GetMapping()) {
146 return absl::InvalidArgumentError("Payload is null or empty.");
147 }
148 if (!fb::RuntimeStagesBufferHasIdentifier(payload->GetMapping())) {
149 return absl::InvalidArgumentError(
150 "Payload does not have valid identifier.");
151 }
152
153 auto raw_stages = fb::GetRuntimeStages(payload->GetMapping());
154 if (!raw_stages) {
155 return absl::InvalidArgumentError("Failed to get runtime stages.");
156 }
157
158 const uint32_t version = raw_stages->format_version();
159 const auto expected =
160 static_cast<uint32_t>(fb::RuntimeStagesFormatVersion::kVersion);
161 if (version != expected) {
162 std::stringstream stream;
163 stream << "Unsupported runtime stages format version. Expected " << expected
164 << ", got " << version << ".";
165 return absl::InvalidArgumentError(stream.str());
166 }
167
168 return Map{
170 RuntimeStageIfPresent(raw_stages->sksl(), payload)},
172 RuntimeStageIfPresent(raw_stages->metal(), payload)},
174 RuntimeStageIfPresent(raw_stages->opengles(), payload)},
176 RuntimeStageIfPresent(raw_stages->opengles3(), payload)},
178 RuntimeStageIfPresent(raw_stages->vulkan(), payload)},
179 };
180}
181
182RuntimeStage::RuntimeStage(std::shared_ptr<fml::Mapping> payload)
183 : payload_(std::move(payload)) {}
184
186RuntimeStage::RuntimeStage(RuntimeStage&&) = default;
187RuntimeStage& RuntimeStage::operator=(RuntimeStage&&) = default;
188
189const std::shared_ptr<fml::Mapping>& RuntimeStage::GetCodeMapping() const {
190 return code_mapping_;
191}
192
193const std::vector<RuntimeUniformDescription>& RuntimeStage::GetUniforms()
194 const {
195 return uniforms_;
196}
197
199 const std::string& name) const {
200 for (const auto& uniform : uniforms_) {
201 if (uniform.name == name) {
202 return &uniform;
203 }
204 }
205 return nullptr;
206}
207
208const std::string& RuntimeStage::GetEntrypoint() const {
209 return entrypoint_;
210}
211
213 return stage_;
214}
215
217 return is_dirty_;
218}
219
221 is_dirty_ = false;
222}
223
224const std::vector<DescriptorSetLayout>& RuntimeStage::GetDescriptorSetLayouts()
225 const {
226 return descriptor_set_layouts_;
227}
228
229} // namespace impeller
GLenum type
RuntimeStage(RuntimeStage &&)
const std::string & GetEntrypoint() const
RuntimeStage & operator=(RuntimeStage &&)
static absl::StatusOr< RuntimeStage > Create(const fb::RuntimeStage *runtime_stage, const std::shared_ptr< fml::Mapping > &payload)
const std::vector< RuntimeUniformDescription > & GetUniforms() const
const RuntimeUniformDescription * GetUniform(const std::string &name) const
std::map< RuntimeStageBackend, std::shared_ptr< RuntimeStage > > Map
static const char * kVulkanUBOName
const std::shared_ptr< fml::Mapping > & GetCodeMapping() const
const std::vector< DescriptorSetLayout > & GetDescriptorSetLayouts() const
static absl::StatusOr< Map > DecodeRuntimeStages(const std::shared_ptr< fml::Mapping > &payload)
RuntimeShaderStage GetShaderStage() const
#define FML_UNREACHABLE()
Definition logging.h:128
const char * name
Definition fuchsia.cc:49
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
static RuntimeUniformType ToType(fb::UniformDataType type)
Definition ref_ptr.h:261
RuntimeUniformDimensions dimensions
std::vector< uint8_t > struct_layout
std::optional< size_t > array_elements
size_t binding
Location, but for Vulkan.
const size_t end