| 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
5 #include "impeller/runtime_stage/runtime_stage.h"
6
7 #include <array>
8 #include <memory>
9 #include <sstream>
10
11 #include "fml/mapping.h"
12 #include "impeller/base/validation.h"
13 #include "impeller/core/runtime_types.h"
14 #include "impeller/core/shader_types.h"
15 #include "impeller/runtime_stage/runtime_stage_flatbuffers.h"
16 #include "runtime_stage_types_flatbuffers.h"
17
18 namespace impeller {
19
20 static RuntimeUniformType ToType(fb::UniformDataType type) {
21 switch (type) {
22 case fb::UniformDataType::kFloat:
23 return RuntimeUniformType::kFloat;
24 case fb::UniformDataType::kSampledImage:
25 return RuntimeUniformType::kSampledImage;
26 case fb::UniformDataType::kStruct:
27 return RuntimeUniformType::kStruct;
28 }
29 FML_UNREACHABLE();
30 }
31
32 static RuntimeShaderStage ToShaderStage(fb::Stage stage) {
33 switch (stage) {
34 case fb::Stage::kVertex:
35 return RuntimeShaderStage::kVertex;
36 case fb::Stage::kFragment:
37 return RuntimeShaderStage::kFragment;
38 case fb::Stage::kCompute:
39 return RuntimeShaderStage::kCompute;
40 }
41 FML_UNREACHABLE();
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.
48 const char* RuntimeStage::kVulkanUBOName =
49 "_RESERVED_IDENTIFIER_FIXUP_gl_DefaultUniformBlock";
50
51 absl::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++) {
71 RuntimeUniformDescription desc;
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 }
80 desc.dimensions = RuntimeUniformDimensions{
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->padding_layout()) {
85 for (const auto& byte_type : *i->padding_layout()) {
86 impeller::RuntimePaddingType type;
87 switch (byte_type) {
88 case fb::PaddingType::kPadding:
89 type = impeller::RuntimePaddingType::kPadding;
90 break;
91 case fb::PaddingType::kFloat:
92 type = impeller::RuntimePaddingType::kFloat;
93 break;
94 }
95 desc.padding_layout.push_back(type);
96 }
97 }
98 if (i->struct_fields()) {
99 for (const auto& elem : *i->struct_fields()) {
100 desc.struct_fields.emplace_back(
101 StructField{.name = elem->name()->str(),
102 .byte_size = static_cast<size_t>(elem->byte_size())});
103 }
104 }
105 desc.struct_float_count = i->struct_float_count();
106 stage.uniforms_.push_back(std::move(desc));
107 }
108 }
109
110 stage.code_mapping_ = std::make_shared<fml::NonOwnedMapping>(
111 runtime_stage->shader()->data(), //
112 runtime_stage->shader()->size(), //
113 [payload = stage.payload_](auto, auto) {} //
114 );
115
116 size_t binding = 64;
117 if (ubo_id.has_value() && ubo_id.value() == binding) {
118 binding++;
119 }
120 for (auto& uniform : stage.uniforms_) {
121 if (uniform.type == kSampledImage) {
122 uniform.binding = binding;
123 binding++;
124 if (ubo_id.has_value() && ubo_id.value() == binding) {
125 binding++;
126 }
127 }
128 }
129
130 for (const auto& uniform : stage.GetUniforms()) {
131 if (uniform.type == kStruct) {
132 stage.descriptor_set_layouts_.push_back(DescriptorSetLayout{
133 static_cast<uint32_t>(uniform.location),
134 DescriptorType::kUniformBuffer,
135 ShaderStage::kFragment,
136 });
137 } else if (uniform.type == kSampledImage) {
138 stage.descriptor_set_layouts_.push_back(DescriptorSetLayout{
139 static_cast<uint32_t>(uniform.binding),
140 DescriptorType::kSampledImage,
141 ShaderStage::kFragment,
142 });
143 }
144 }
145
146 return stage;
147 }
148
149 std::unique_ptr<RuntimeStage> RuntimeStage::RuntimeStageIfPresent(
150 const fb::RuntimeStage* runtime_stage,
151 const std::shared_ptr<fml::Mapping>& payload) {
152 auto stage = Create(runtime_stage, payload);
153 if (!stage.ok()) {
154 return nullptr;
155 }
156 return std::make_unique<RuntimeStage>(std::move(*stage));
157 }
158
159 absl::StatusOr<RuntimeStage::Map> RuntimeStage::DecodeRuntimeStages(
160 const std::shared_ptr<fml::Mapping>& payload) {
161 if (payload == nullptr || !payload->GetMapping()) {
162 return absl::InvalidArgumentError("Payload is null or empty.");
163 }
164 if (!fb::RuntimeStagesBufferHasIdentifier(payload->GetMapping())) {
165 return absl::InvalidArgumentError(
166 "Payload does not have valid identifier.");
167 }
168
169 auto raw_stages = fb::GetRuntimeStages(payload->GetMapping());
170 if (!raw_stages) {
171 return absl::InvalidArgumentError("Failed to get runtime stages.");
172 }
173
174 const uint32_t version = raw_stages->format_version();
175 const auto expected =
176 static_cast<uint32_t>(fb::RuntimeStagesFormatVersion::kVersion);
177 if (version != expected) {
178 std::stringstream stream;
179 stream << "Unsupported runtime stages format version. Expected " << expected
180 << ", got " << version << ".";
181 return absl::InvalidArgumentError(stream.str());
182 }
183
184 return Map{
185 {RuntimeStageBackend::kSkSL,
186 RuntimeStageIfPresent(raw_stages->sksl(), payload)},
187 {RuntimeStageBackend::kMetal,
188 RuntimeStageIfPresent(raw_stages->metal(), payload)},
189 {RuntimeStageBackend::kOpenGLES,
190 RuntimeStageIfPresent(raw_stages->opengles(), payload)},
191 {RuntimeStageBackend::kOpenGLES3,
192 RuntimeStageIfPresent(raw_stages->opengles3(), payload)},
193 {RuntimeStageBackend::kVulkan,
194 RuntimeStageIfPresent(raw_stages->vulkan(), payload)},
195 };
196 }
197
198 RuntimeStage::RuntimeStage(std::shared_ptr<fml::Mapping> payload)
199 : payload_(std::move(payload)) {}
200
201 RuntimeStage::~RuntimeStage() = default;
202 RuntimeStage::RuntimeStage(RuntimeStage&&) = default;
203 RuntimeStage& RuntimeStage::operator=(RuntimeStage&&) = default;
204
205 const std::shared_ptr<fml::Mapping>& RuntimeStage::GetCodeMapping() const {
206 return code_mapping_;
207 }
208
209 const std::vector<RuntimeUniformDescription>& RuntimeStage::GetUniforms()
210 const {
211 return uniforms_;
212 }
213
214 const RuntimeUniformDescription* RuntimeStage::GetUniform(
215 const std::string& name) const {
216 for (const auto& uniform : uniforms_) {
217 if (uniform.name == name) {
218 return &uniform;
219 }
220 }
221 return nullptr;
222 }
223
224 const std::string& RuntimeStage::GetEntrypoint() const {
225 return entrypoint_;
226 }
227
228 RuntimeShaderStage RuntimeStage::GetShaderStage() const {
229 return stage_;
230 }
231
232 bool RuntimeStage::IsDirty() const {
233 return is_dirty_;
234 }
235
236 void RuntimeStage::SetClean() {
237 is_dirty_ = false;
238 }
239
240 const std::vector<DescriptorSetLayout>& RuntimeStage::GetDescriptorSetLayouts()
241 const {
242 return descriptor_set_layouts_;
243 }
244
245 } // namespace impeller
type
GLenum type
Definition: blit_command_gles.cc:153
impeller::RuntimeStage
Definition: runtime_stage.h:21
impeller::RuntimeStage::~RuntimeStage
~RuntimeStage()
impeller::RuntimeStage::RuntimeStage
RuntimeStage(RuntimeStage &&)
impeller::RuntimeStage::GetEntrypoint
const std::string & GetEntrypoint() const
Definition: runtime_stage.cc:224
impeller::RuntimeStage::operator=
RuntimeStage & operator=(RuntimeStage &&)
impeller::RuntimeStage::Create
static absl::StatusOr< RuntimeStage > Create(const fb::RuntimeStage *runtime_stage, const std::shared_ptr< fml::Mapping > &payload)
Definition: runtime_stage.cc:51
impeller::RuntimeStage::GetUniforms
const std::vector< RuntimeUniformDescription > & GetUniforms() const
Definition: runtime_stage.cc:209
impeller::RuntimeStage::SetClean
void SetClean()
Definition: runtime_stage.cc:236
impeller::RuntimeStage::GetUniform
const RuntimeUniformDescription * GetUniform(const std::string &name) const
Definition: runtime_stage.cc:214
impeller::RuntimeStage::Map
std::map< RuntimeStageBackend, std::shared_ptr< RuntimeStage > > Map
Definition: runtime_stage.h:25
impeller::RuntimeStage::kVulkanUBOName
static const char * kVulkanUBOName
Definition: runtime_stage.h:23
impeller::RuntimeStage::GetCodeMapping
const std::shared_ptr< fml::Mapping > & GetCodeMapping() const
Definition: runtime_stage.cc:205
impeller::RuntimeStage::IsDirty
bool IsDirty() const
Definition: runtime_stage.cc:232
impeller::RuntimeStage::GetDescriptorSetLayouts
const std::vector< DescriptorSetLayout > & GetDescriptorSetLayouts() const
Definition: runtime_stage.cc:240
impeller::RuntimeStage::DecodeRuntimeStages
static absl::StatusOr< Map > DecodeRuntimeStages(const std::shared_ptr< fml::Mapping > &payload)
Definition: runtime_stage.cc:159
impeller::RuntimeStage::GetShaderStage
RuntimeShaderStage GetShaderStage() const
Definition: runtime_stage.cc:228
impeller
Definition: allocation.cc:12
impeller::RuntimeShaderStage
RuntimeShaderStage
Definition: runtime_types.h:30
impeller::RuntimeShaderStage::kCompute
@ kCompute
impeller::RuntimeShaderStage::kFragment
@ kFragment
impeller::RuntimeShaderStage::kVertex
@ kVertex
impeller::RuntimePaddingType
RuntimePaddingType
Definition: runtime_types.h:41
impeller::RuntimePaddingType::kPadding
@ kPadding
impeller::RuntimePaddingType::kFloat
@ kFloat
impeller::RuntimeStageBackend::kOpenGLES
@ kOpenGLES
impeller::RuntimeStageBackend::kMetal
@ kMetal
impeller::RuntimeStageBackend::kVulkan
@ kVulkan
impeller::RuntimeStageBackend::kSkSL
@ kSkSL
impeller::RuntimeStageBackend::kOpenGLES3
@ kOpenGLES3
impeller::ToShaderStage
constexpr ShaderStage ToShaderStage(RuntimeShaderStage stage)
Definition: shader_types.h:29
impeller::ShaderStage::kFragment
@ kFragment
impeller::ToType
static RuntimeUniformType ToType(fb::UniformDataType type)
Definition: runtime_stage.cc:20
impeller::DescriptorType::kUniformBuffer
@ kUniformBuffer
impeller::DescriptorType::kSampledImage
@ kSampledImage
impeller::kPadding
constexpr auto kPadding
Definition: typographer_context_skia.cc:48
impeller::RuntimeUniformType
RuntimeUniformType
Definition: runtime_types.h:24
impeller::kSampledImage
@ kSampledImage
Definition: runtime_types.h:26
impeller::kFloat
@ kFloat
Definition: runtime_types.h:25
impeller::kStruct
@ kStruct
Definition: runtime_types.h:27
std
Definition: comparable.h:95
runtime_stage.h
runtime_types.h
shader_types.h
impeller::DescriptorSetLayout
Definition: shader_types.h:167
impeller::RuntimeUniformDescription
Definition: runtime_types.h:52
impeller::RuntimeUniformDescription::dimensions
RuntimeUniformDimensions dimensions
Definition: runtime_types.h:58
impeller::RuntimeUniformDescription::location
size_t location
Definition: runtime_types.h:54
impeller::RuntimeUniformDescription::struct_fields
std::vector< StructField > struct_fields
Definition: runtime_types.h:64
impeller::RuntimeUniformDescription::padding_layout
std::vector< RuntimePaddingType > padding_layout
Definition: runtime_types.h:61
impeller::RuntimeUniformDescription::name
std::string name
Definition: runtime_types.h:53
impeller::RuntimeUniformDescription::type
RuntimeUniformType type
Definition: runtime_types.h:57
impeller::RuntimeUniformDescription::struct_float_count
size_t struct_float_count
Definition: runtime_types.h:65
impeller::RuntimeUniformDescription::array_elements
std::optional< size_t > array_elements
Definition: runtime_types.h:60
impeller::RuntimeUniformDescription::bit_width
size_t bit_width
Definition: runtime_types.h:59
impeller::RuntimeUniformDescription::binding
size_t binding
Location, but for Vulkan.
Definition: runtime_types.h:56
impeller::RuntimeUniformDimensions
Definition: runtime_types.h:36
impeller::StructField
Definition: runtime_types.h:46
impeller::StructField::name
std::string name
Definition: runtime_types.h:47
end
const size_t end
Definition: tessellator_libtess.cc:63
validation.h