| Flutter Impeller |

runtime_stage_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
5 #include "impeller/compiler/runtime_stage_data.h"
6
7 #include <array>
8 #include <optional>
9
10 #include "inja/inja.hpp"
11
12 #include "impeller/base/validation.h"
13 #include "impeller/runtime_stage/runtime_stage_flatbuffers.h"
14
15 namespace impeller {
16 namespace compiler {
17
18 RuntimeStageData::RuntimeStageData(std::string entrypoint,
19 spv::ExecutionModel stage,
20 TargetPlatform target_platform)
21 : entrypoint_(std::move(entrypoint)),
22 stage_(stage),
23 target_platform_(target_platform) {}
24
25 RuntimeStageData::~RuntimeStageData() = default;
26
27 void RuntimeStageData::AddUniformDescription(UniformDescription uniform) {
28 uniforms_.emplace_back(std::move(uniform));
29 }
30
31 void RuntimeStageData::SetShaderData(std::shared_ptr<fml::Mapping> shader) {
32 shader_ = std::move(shader);
33 }
34
35 void RuntimeStageData::SetSkSLData(std::shared_ptr<fml::Mapping> sksl) {
36 sksl_ = std::move(sksl);
37 }
38
39 static std::optional<fb::Stage> ToStage(spv::ExecutionModel stage) {
40 switch (stage) {
41 case spv::ExecutionModel::ExecutionModelVertex:
42 return fb::Stage::kVertex;
43 case spv::ExecutionModel::ExecutionModelFragment:
44 return fb::Stage::kFragment;
45 case spv::ExecutionModel::ExecutionModelGLCompute:
46 return fb::Stage::kCompute;
47 case spv::ExecutionModel::ExecutionModelTessellationControl:
48 return fb::Stage::kTessellationControl;
49 case spv::ExecutionModel::ExecutionModelTessellationEvaluation:
50 return fb::Stage::kTessellationEvaluation;
51 default:
52 return std::nullopt;
53 }
54 FML_UNREACHABLE();
55 }
56
57 static std::optional<uint32_t> ToJsonStage(spv::ExecutionModel stage) {
58 switch (stage) {
59 case spv::ExecutionModel::ExecutionModelVertex:
60 return 0; // fb::Stage::kVertex;
61 case spv::ExecutionModel::ExecutionModelFragment:
62 return 1; // fb::Stage::kFragment;
63 case spv::ExecutionModel::ExecutionModelGLCompute:
64 return 2; // fb::Stage::kCompute;
65 case spv::ExecutionModel::ExecutionModelTessellationControl:
66 return 3; // fb::Stage::kTessellationControl;
67 case spv::ExecutionModel::ExecutionModelTessellationEvaluation:
68 return 4; // fb::Stage::kTessellationEvaluation;
69 default:
70 return std::nullopt;
71 }
72 FML_UNREACHABLE();
73 }
74
75 static std::optional<fb::TargetPlatform> ToTargetPlatform(
76 TargetPlatform platform) {
77 switch (platform) {
78 case TargetPlatform::kUnknown:
79 case TargetPlatform::kMetalDesktop:
80 case TargetPlatform::kMetalIOS:
81 case TargetPlatform::kOpenGLES:
82 case TargetPlatform::kOpenGLDesktop:
83 case TargetPlatform::kVulkan:
84 return std::nullopt;
85 case TargetPlatform::kSkSL:
86 return fb::TargetPlatform::kSkSL;
87 case TargetPlatform::kRuntimeStageMetal:
88 return fb::TargetPlatform::kMetal;
89 case TargetPlatform::kRuntimeStageGLES:
90 return fb::TargetPlatform::kOpenGLES;
91 case TargetPlatform::kRuntimeStageVulkan:
92 return fb::TargetPlatform::kVulkan;
93 }
94 FML_UNREACHABLE();
95 }
96
97 static std::optional<uint32_t> ToJsonTargetPlatform(TargetPlatform platform) {
98 switch (platform) {
99 case TargetPlatform::kUnknown:
100 case TargetPlatform::kMetalDesktop:
101 case TargetPlatform::kMetalIOS:
102 case TargetPlatform::kOpenGLES:
103 case TargetPlatform::kOpenGLDesktop:
104 case TargetPlatform::kVulkan:
105 return std::nullopt;
106 case TargetPlatform::kSkSL:
107 return static_cast<uint32_t>(fb::TargetPlatform::kSkSL);
108 case TargetPlatform::kRuntimeStageMetal:
109 return static_cast<uint32_t>(fb::TargetPlatform::kMetal);
110 case TargetPlatform::kRuntimeStageGLES:
111 return static_cast<uint32_t>(fb::TargetPlatform::kOpenGLES);
112 case TargetPlatform::kRuntimeStageVulkan:
113 return static_cast<uint32_t>(fb::TargetPlatform::kVulkan);
114 }
115 FML_UNREACHABLE();
116 }
117
118 static std::optional<fb::UniformDataType> ToType(
119 spirv_cross::SPIRType::BaseType type) {
120 switch (type) {
121 case spirv_cross::SPIRType::Boolean:
122 return fb::UniformDataType::kBoolean;
123 case spirv_cross::SPIRType::SByte:
124 return fb::UniformDataType::kSignedByte;
125 case spirv_cross::SPIRType::UByte:
126 return fb::UniformDataType::kUnsignedByte;
127 case spirv_cross::SPIRType::Short:
128 return fb::UniformDataType::kSignedShort;
129 case spirv_cross::SPIRType::UShort:
130 return fb::UniformDataType::kUnsignedShort;
131 case spirv_cross::SPIRType::Int:
132 return fb::UniformDataType::kSignedInt;
133 case spirv_cross::SPIRType::UInt:
134 return fb::UniformDataType::kUnsignedInt;
135 case spirv_cross::SPIRType::Int64:
136 return fb::UniformDataType::kSignedInt64;
137 case spirv_cross::SPIRType::UInt64:
138 return fb::UniformDataType::kUnsignedInt64;
139 case spirv_cross::SPIRType::Half:
140 return fb::UniformDataType::kHalfFloat;
141 case spirv_cross::SPIRType::Float:
142 return fb::UniformDataType::kFloat;
143 case spirv_cross::SPIRType::Double:
144 return fb::UniformDataType::kDouble;
145 case spirv_cross::SPIRType::SampledImage:
146 return fb::UniformDataType::kSampledImage;
147 case spirv_cross::SPIRType::AccelerationStructure:
148 case spirv_cross::SPIRType::AtomicCounter:
149 case spirv_cross::SPIRType::Char:
150 case spirv_cross::SPIRType::ControlPointArray:
151 case spirv_cross::SPIRType::Image:
152 case spirv_cross::SPIRType::Interpolant:
153 case spirv_cross::SPIRType::RayQuery:
154 case spirv_cross::SPIRType::Sampler:
155 case spirv_cross::SPIRType::Struct:
156 case spirv_cross::SPIRType::Unknown:
157 case spirv_cross::SPIRType::Void:
158 return std::nullopt;
159 }
160 FML_UNREACHABLE();
161 }
162
163 static std::optional<uint32_t> ToJsonType(
164 spirv_cross::SPIRType::BaseType type) {
165 switch (type) {
166 case spirv_cross::SPIRType::Boolean:
167 return 0; // fb::UniformDataType::kBoolean;
168 case spirv_cross::SPIRType::SByte:
169 return 1; // fb::UniformDataType::kSignedByte;
170 case spirv_cross::SPIRType::UByte:
171 return 2; // fb::UniformDataType::kUnsignedByte;
172 case spirv_cross::SPIRType::Short:
173 return 3; // fb::UniformDataType::kSignedShort;
174 case spirv_cross::SPIRType::UShort:
175 return 4; // fb::UniformDataType::kUnsignedShort;
176 case spirv_cross::SPIRType::Int:
177 return 5; // fb::UniformDataType::kSignedInt;
178 case spirv_cross::SPIRType::UInt:
179 return 6; // fb::UniformDataType::kUnsignedInt;
180 case spirv_cross::SPIRType::Int64:
181 return 7; // fb::UniformDataType::kSignedInt64;
182 case spirv_cross::SPIRType::UInt64:
183 return 8; // fb::UniformDataType::kUnsignedInt64;
184 case spirv_cross::SPIRType::Half:
185 return 9; // b::UniformDataType::kHalfFloat;
186 case spirv_cross::SPIRType::Float:
187 return 10; // fb::UniformDataType::kFloat;
188 case spirv_cross::SPIRType::Double:
189 return 11; // fb::UniformDataType::kDouble;
190 case spirv_cross::SPIRType::SampledImage:
191 return 12; // fb::UniformDataType::kSampledImage;
192 case spirv_cross::SPIRType::AccelerationStructure:
193 case spirv_cross::SPIRType::AtomicCounter:
194 case spirv_cross::SPIRType::Char:
195 case spirv_cross::SPIRType::ControlPointArray:
196 case spirv_cross::SPIRType::Image:
197 case spirv_cross::SPIRType::Interpolant:
198 case spirv_cross::SPIRType::RayQuery:
199 case spirv_cross::SPIRType::Sampler:
200 case spirv_cross::SPIRType::Struct:
201 case spirv_cross::SPIRType::Unknown:
202 case spirv_cross::SPIRType::Void:
203 return std::nullopt;
204 }
205 FML_UNREACHABLE();
206 }
207
208 static const char* kStageKey = "stage";
209 static const char* kTargetPlatformKey = "target_platform";
210 static const char* kEntrypointKey = "entrypoint";
211 static const char* kUniformsKey = "uniforms";
212 static const char* kShaderKey = "sksl";
213 static const char* kUniformNameKey = "name";
214 static const char* kUniformLocationKey = "location";
215 static const char* kUniformTypeKey = "type";
216 static const char* kUniformRowsKey = "rows";
217 static const char* kUniformColumnsKey = "columns";
218 static const char* kUniformBitWidthKey = "bit_width";
219 static const char* kUniformArrayElementsKey = "array_elements";
220
221 std::shared_ptr<fml::Mapping> RuntimeStageData::CreateJsonMapping() const {
222 // Runtime Stage Data JSON format
223 // {
224 // "stage": 0,
225 // "target_platform": "",
226 // "entrypoint": "",
227 // "shader": "",
228 // "sksl": "",
229 // "uniforms": [
230 // {
231 // "name": "..",
232 // "location": 0,
233 // "type": 0,
234 // "rows": 0,
235 // "columns": 0,
236 // "bit_width": 0,
237 // "array_elements": 0,
238 // }
239 // ]
240 // },
241 nlohmann::json root;
242
243 const auto stage = ToJsonStage(stage_);
244 if (!stage.has_value()) {
245 VALIDATION_LOG << "Invalid runtime stage.";
246 return nullptr;
247 }
248 root[kStageKey] = stage.value();
249
250 const auto target_platform = ToJsonTargetPlatform(target_platform_);
251 if (!target_platform.has_value()) {
252 VALIDATION_LOG << "Invalid target platform for runtime stage.";
253 return nullptr;
254 }
255 root[kTargetPlatformKey] = target_platform.value();
256
257 if (shader_->GetSize() > 0u) {
258 std::string shader(reinterpret_cast<const char*>(shader_->GetMapping()),
259 shader_->GetSize());
260 root[kShaderKey] = shader.c_str();
261 }
262
263 auto& uniforms = root[kUniformsKey] = nlohmann::json::array_t{};
264 for (const auto& uniform : uniforms_) {
265 nlohmann::json uniform_object;
266 uniform_object[kUniformNameKey] = uniform.name.c_str();
267 uniform_object[kUniformLocationKey] = uniform.location;
268 uniform_object[kUniformRowsKey] = uniform.rows;
269 uniform_object[kUniformColumnsKey] = uniform.columns;
270
271 auto uniform_type = ToJsonType(uniform.type);
272 if (!uniform_type.has_value()) {
273 VALIDATION_LOG << "Invalid uniform type for runtime stage.";
274 return nullptr;
275 }
276
277 uniform_object[kUniformTypeKey] = uniform_type.value();
278 uniform_object[kUniformBitWidthKey] = uniform.bit_width;
279
280 if (uniform.array_elements.has_value()) {
281 uniform_object[kUniformArrayElementsKey] = uniform.array_elements.value();
282 } else {
283 uniform_object[kUniformArrayElementsKey] = 0;
284 }
285 uniforms.push_back(uniform_object);
286 }
287
288 auto json_string = std::make_shared<std::string>(root.dump(2u));
289
290 return std::make_shared<fml::NonOwnedMapping>(
291 reinterpret_cast<const uint8_t*>(json_string->data()),
292 json_string->size(), [json_string](auto, auto) {});
293 }
294
295 std::shared_ptr<fml::Mapping> RuntimeStageData::CreateMapping() const {
296 // The high level object API is used here for writing to the buffer. This is
297 // just a convenience.
298 fb::RuntimeStageT runtime_stage;
299 runtime_stage.entrypoint = entrypoint_;
300 const auto stage = ToStage(stage_);
301 if (!stage.has_value()) {
302 VALIDATION_LOG << "Invalid runtime stage.";
303 return nullptr;
304 }
305 runtime_stage.stage = stage.value();
306 const auto target_platform = ToTargetPlatform(target_platform_);
307 if (!target_platform.has_value()) {
308 VALIDATION_LOG << "Invalid target platform for runtime stage.";
309 return nullptr;
310 }
311 runtime_stage.target_platform = target_platform.value();
312 if (!shader_) {
313 VALIDATION_LOG << "No shader specified for runtime stage.";
314 return nullptr;
315 }
316 if (shader_->GetSize() > 0u) {
317 runtime_stage.shader = {shader_->GetMapping(),
318 shader_->GetMapping() + shader_->GetSize()};
319 }
320 // It is not an error for the SkSL to be ommitted.
321 if (sksl_->GetSize() > 0u) {
322 runtime_stage.sksl = {sksl_->GetMapping(),
323 sksl_->GetMapping() + sksl_->GetSize()};
324 }
325 for (const auto& uniform : uniforms_) {
326 auto desc = std::make_unique<fb::UniformDescriptionT>();
327
328 desc->name = uniform.name;
329 if (desc->name.empty()) {
330 VALIDATION_LOG << "Uniform name cannot be empty.";
331 return nullptr;
332 }
333 desc->location = uniform.location;
334 desc->rows = uniform.rows;
335 desc->columns = uniform.columns;
336 auto uniform_type = ToType(uniform.type);
337 if (!uniform_type.has_value()) {
338 VALIDATION_LOG << "Invalid uniform type for runtime stage.";
339 return nullptr;
340 }
341 desc->type = uniform_type.value();
342 desc->bit_width = uniform.bit_width;
343 if (uniform.array_elements.has_value()) {
344 desc->array_elements = uniform.array_elements.value();
345 }
346
347 runtime_stage.uniforms.emplace_back(std::move(desc));
348 }
349 auto builder = std::make_shared<flatbuffers::FlatBufferBuilder>();
350 builder->Finish(fb::RuntimeStage::Pack(*builder.get(), &runtime_stage),
351 fb::RuntimeStageIdentifier());
352 return std::make_shared<fml::NonOwnedMapping>(builder->GetBufferPointer(),
353 builder->GetSize(),
354 [builder](auto, auto) {});
355 }
356
357 } // namespace compiler
358 } // namespace impeller
impeller::kBoolean
@ kBoolean
Definition: runtime_types.h:14
impeller::kFloat
@ kFloat
Definition: runtime_types.h:24
runtime_stage_data.h
impeller::compiler::RuntimeStageData::~RuntimeStageData
~RuntimeStageData()
impeller::compiler::RuntimeStageData::CreateJsonMapping
std::shared_ptr< fml::Mapping > CreateJsonMapping() const
Definition: runtime_stage_data.cc:221
impeller::kUnsignedShort
@ kUnsignedShort
Definition: runtime_types.h:18
impeller::compiler::RuntimeStageData::SetSkSLData
void SetSkSLData(std::shared_ptr< fml::Mapping > sksl)
Definition: runtime_stage_data.cc:35
impeller::compiler::RuntimeStageData::SetShaderData
void SetShaderData(std::shared_ptr< fml::Mapping > shader)
Definition: runtime_stage_data.cc:31
impeller::compiler::kUniformBitWidthKey
static const char * kUniformBitWidthKey
Definition: runtime_stage_data.cc:218
impeller::compiler::TargetPlatform::kMetalDesktop
@ kMetalDesktop
impeller::kSignedByte
@ kSignedByte
Definition: runtime_types.h:15
impeller::compiler::RuntimeStageData::RuntimeStageData
RuntimeStageData(std::string entrypoint, spv::ExecutionModel stage, TargetPlatform target_platform)
Definition: runtime_stage_data.cc:18
impeller::kSampledImage
@ kSampledImage
Definition: runtime_types.h:26
impeller::compiler::kEntrypointKey
static const char * kEntrypointKey
Definition: runtime_stage_data.cc:210
impeller::compiler::kTargetPlatformKey
static const char * kTargetPlatformKey
Definition: runtime_stage_data.cc:209
impeller::compiler::TargetPlatform::kMetalIOS
@ kMetalIOS
validation.h
impeller::compiler::TargetPlatform
TargetPlatform
Definition: types.h:28
impeller::compiler::RuntimeStageData::CreateMapping
std::shared_ptr< fml::Mapping > CreateMapping() const
Definition: runtime_stage_data.cc:295
impeller::compiler::ToTargetPlatform
static std::optional< fb::TargetPlatform > ToTargetPlatform(TargetPlatform platform)
Definition: runtime_stage_data.cc:75
impeller::compiler::kUniformNameKey
static const char * kUniformNameKey
Definition: runtime_stage_data.cc:213
impeller::kSignedInt
@ kSignedInt
Definition: runtime_types.h:19
impeller::compiler::kUniformColumnsKey
static const char * kUniformColumnsKey
Definition: runtime_stage_data.cc:217
impeller::compiler::kShaderKey
static const char * kShaderKey
Definition: runtime_stage_data.cc:212
impeller::compiler::TargetPlatform::kVulkan
@ kVulkan
impeller::compiler::kUniformTypeKey
static const char * kUniformTypeKey
Definition: runtime_stage_data.cc:215
impeller::compiler::TargetPlatform::kRuntimeStageVulkan
@ kRuntimeStageVulkan
impeller::compiler::kStageKey
static const char * kStageKey
Definition: runtime_stage_data.cc:208
impeller::compiler::ToStage
static std::optional< fb::Stage > ToStage(spv::ExecutionModel stage)
Definition: runtime_stage_data.cc:39
impeller::kUnsignedByte
@ kUnsignedByte
Definition: runtime_types.h:16
impeller::kUnsignedInt64
@ kUnsignedInt64
Definition: runtime_types.h:22
impeller::compiler::kUniformArrayElementsKey
static const char * kUniformArrayElementsKey
Definition: runtime_stage_data.cc:219
impeller::compiler::ToType
static std::optional< fb::UniformDataType > ToType(spirv_cross::SPIRType::BaseType type)
Definition: runtime_stage_data.cc:118
impeller::kHalfFloat
@ kHalfFloat
Definition: runtime_types.h:23
impeller::kUnsignedInt
@ kUnsignedInt
Definition: runtime_types.h:20
impeller::compiler::RuntimeStageData::AddUniformDescription
void AddUniformDescription(UniformDescription uniform)
Definition: runtime_stage_data.cc:27
impeller::kSignedShort
@ kSignedShort
Definition: runtime_types.h:17
impeller::compiler::UniformDescription
Definition: runtime_stage_data.h:18
impeller::compiler::ToJsonType
static std::optional< uint32_t > ToJsonType(spirv_cross::SPIRType::BaseType type)
Definition: runtime_stage_data.cc:163
VALIDATION_LOG
#define VALIDATION_LOG
Definition: validation.h:60
impeller::compiler::kUniformLocationKey
static const char * kUniformLocationKey
Definition: runtime_stage_data.cc:214
impeller::kDouble
@ kDouble
Definition: runtime_types.h:25
std
Definition: comparable.h:98
impeller::compiler::TargetPlatform::kOpenGLDesktop
@ kOpenGLDesktop
impeller::kSignedInt64
@ kSignedInt64
Definition: runtime_types.h:21
impeller::compiler::TargetPlatform::kUnknown
@ kUnknown
impeller::compiler::ToJsonStage
static std::optional< uint32_t > ToJsonStage(spv::ExecutionModel stage)
Definition: runtime_stage_data.cc:57
impeller::compiler::TargetPlatform::kOpenGLES
@ kOpenGLES
impeller::compiler::kUniformsKey
static const char * kUniformsKey
Definition: runtime_stage_data.cc:211
impeller::compiler::kUniformRowsKey
static const char * kUniformRowsKey
Definition: runtime_stage_data.cc:216
impeller::compiler::TargetPlatform::kRuntimeStageMetal
@ kRuntimeStageMetal
impeller
Definition: aiks_context.cc:10
impeller::compiler::TargetPlatform::kSkSL
@ kSkSL
impeller::compiler::TargetPlatform::kRuntimeStageGLES
@ kRuntimeStageGLES
impeller::compiler::ToJsonTargetPlatform
static std::optional< uint32_t > ToJsonTargetPlatform(TargetPlatform platform)
Definition: runtime_stage_data.cc:97