Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 00ff332

Browse files
authored
[Flutter GPU] Shader bundle improvements: Uniform structs & member offset reflection, GLES metadata, separate from runtime stage. (#49485)
* Switch from legacy uniform semantics to uniform structs. * Completely separate shader bundle from runtime stage. * Packing multiple backends per shader. * Pack struct and member fields into the shader bundle flatbuffer. * Bind uniforms with correct metadata for GLES. * Add uniform struct size and member offset reflection.
1 parent 5199f56 commit 00ff332

34 files changed

+1240
-417
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5016,6 +5016,8 @@ ORIGIN: ../../../flutter/impeller/compiler/runtime_stage_data.cc + ../../../flut
50165016
ORIGIN: ../../../flutter/impeller/compiler/runtime_stage_data.h + ../../../flutter/LICENSE
50175017
ORIGIN: ../../../flutter/impeller/compiler/shader_bundle.cc + ../../../flutter/LICENSE
50185018
ORIGIN: ../../../flutter/impeller/compiler/shader_bundle.h + ../../../flutter/LICENSE
5019+
ORIGIN: ../../../flutter/impeller/compiler/shader_bundle_data.cc + ../../../flutter/LICENSE
5020+
ORIGIN: ../../../flutter/impeller/compiler/shader_bundle_data.h + ../../../flutter/LICENSE
50195021
ORIGIN: ../../../flutter/impeller/compiler/shader_lib/flutter/runtime_effect.glsl + ../../../flutter/LICENSE
50205022
ORIGIN: ../../../flutter/impeller/compiler/shader_lib/impeller/blending.glsl + ../../../flutter/LICENSE
50215023
ORIGIN: ../../../flutter/impeller/compiler/shader_lib/impeller/branching.glsl + ../../../flutter/LICENSE
@@ -7831,6 +7833,8 @@ FILE: ../../../flutter/impeller/compiler/runtime_stage_data.cc
78317833
FILE: ../../../flutter/impeller/compiler/runtime_stage_data.h
78327834
FILE: ../../../flutter/impeller/compiler/shader_bundle.cc
78337835
FILE: ../../../flutter/impeller/compiler/shader_bundle.h
7836+
FILE: ../../../flutter/impeller/compiler/shader_bundle_data.cc
7837+
FILE: ../../../flutter/impeller/compiler/shader_bundle_data.h
78347838
FILE: ../../../flutter/impeller/compiler/shader_lib/flutter/runtime_effect.glsl
78357839
FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/blending.glsl
78367840
FILE: ../../../flutter/impeller/compiler/shader_lib/impeller/branching.glsl

impeller/compiler/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ impeller_component("compiler_lib") {
4848
"runtime_stage_data.h",
4949
"shader_bundle.cc",
5050
"shader_bundle.h",
51+
"shader_bundle_data.cc",
52+
"shader_bundle_data.h",
5153
"source_options.cc",
5254
"source_options.h",
5355
"spirv_compiler.cc",

impeller/compiler/reflector.cc

Lines changed: 141 additions & 35 deletions
Large diffs are not rendered by default.

impeller/compiler/reflector.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include "flutter/fml/mapping.h"
1414
#include "impeller/compiler/compiler_backend.h"
1515
#include "impeller/compiler/runtime_stage_data.h"
16+
#include "impeller/compiler/shader_bundle_data.h"
1617
#include "inja/inja.hpp"
1718
#include "spirv_msl.hpp"
1819
#include "spirv_parser.hpp"
@@ -22,7 +23,7 @@ namespace compiler {
2223

2324
struct StructMember {
2425
std::string type;
25-
std::string base_type;
26+
spirv_cross::SPIRType::BaseType base_type;
2627
std::string name;
2728
size_t offset = 0u;
2829
size_t size = 0u;
@@ -31,15 +32,15 @@ struct StructMember {
3132
size_t element_padding = 0u;
3233

3334
StructMember(std::string p_type,
34-
std::string p_base_type,
35+
spirv_cross::SPIRType::BaseType p_base_type,
3536
std::string p_name,
3637
size_t p_offset,
3738
size_t p_size,
3839
size_t p_byte_length,
3940
std::optional<size_t> p_array_elements,
4041
size_t p_element_padding)
4142
: type(std::move(p_type)),
42-
base_type(std::move(p_base_type)),
43+
base_type(p_base_type),
4344
name(std::move(p_name)),
4445
offset(p_offset),
4546
size(p_size),
@@ -74,6 +75,8 @@ class Reflector {
7475

7576
std::shared_ptr<RuntimeStageData::Shader> GetRuntimeStageShaderData() const;
7677

78+
std::shared_ptr<ShaderBundleData> GetShaderBundleData() const;
79+
7780
private:
7881
struct StructDefinition {
7982
std::string name;
@@ -101,6 +104,7 @@ class Reflector {
101104
std::shared_ptr<fml::Mapping> reflection_header_;
102105
std::shared_ptr<fml::Mapping> reflection_cc_;
103106
std::shared_ptr<RuntimeStageData::Shader> runtime_stage_shader_;
107+
std::shared_ptr<ShaderBundleData> shader_bundle_data_;
104108
bool is_valid_ = false;
105109

106110
std::optional<nlohmann::json> GenerateTemplateArguments() const;
@@ -111,6 +115,8 @@ class Reflector {
111115

112116
std::shared_ptr<RuntimeStageData::Shader> GenerateRuntimeStageData() const;
113117

118+
std::shared_ptr<ShaderBundleData> GenerateShaderBundleData() const;
119+
114120
std::shared_ptr<fml::Mapping> InflateTemplate(std::string_view tmpl) const;
115121

116122
std::optional<nlohmann::json::object_t> ReflectResource(

impeller/compiler/runtime_stage_data.cc

Lines changed: 74 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -293,79 +293,92 @@ std::shared_ptr<fml::Mapping> RuntimeStageData::CreateJsonMapping() const {
293293
json_string->size(), [json_string](auto, auto) {});
294294
}
295295

296-
std::unique_ptr<fb::RuntimeStagesT> RuntimeStageData::CreateFlatbuffer() const {
297-
// The high level object API is used here for writing to the buffer. This is
298-
// just a convenience.
299-
auto runtime_stages = std::make_unique<fb::RuntimeStagesT>();
296+
std::unique_ptr<fb::RuntimeStageT> RuntimeStageData::CreateStageFlatbuffer(
297+
impeller::RuntimeStageBackend backend) const {
298+
auto kvp = data_.find(backend);
299+
if (kvp == data_.end()) {
300+
return nullptr;
301+
}
300302

301-
for (const auto& kvp : data_) {
302-
auto runtime_stage = std::make_unique<fb::RuntimeStageT>();
303-
runtime_stage->entrypoint = kvp.second->entrypoint;
304-
const auto stage = ToStage(kvp.second->stage);
305-
if (!stage.has_value()) {
306-
VALIDATION_LOG << "Invalid runtime stage.";
303+
auto runtime_stage = std::make_unique<fb::RuntimeStageT>();
304+
runtime_stage->entrypoint = kvp->second->entrypoint;
305+
const auto stage = ToStage(kvp->second->stage);
306+
if (!stage.has_value()) {
307+
VALIDATION_LOG << "Invalid runtime stage.";
308+
return nullptr;
309+
}
310+
runtime_stage->stage = stage.value();
311+
if (!kvp->second->shader) {
312+
VALIDATION_LOG << "No shader specified for runtime stage.";
313+
return nullptr;
314+
}
315+
if (kvp->second->shader->GetSize() > 0u) {
316+
runtime_stage->shader = {
317+
kvp->second->shader->GetMapping(),
318+
kvp->second->shader->GetMapping() + kvp->second->shader->GetSize()};
319+
}
320+
for (const auto& uniform : kvp->second->uniforms) {
321+
auto desc = std::make_unique<fb::UniformDescriptionT>();
322+
323+
desc->name = uniform.name;
324+
if (desc->name.empty()) {
325+
VALIDATION_LOG << "Uniform name cannot be empty.";
307326
return nullptr;
308327
}
309-
runtime_stage->stage = stage.value();
310-
if (!kvp.second->shader) {
311-
VALIDATION_LOG << "No shader specified for runtime stage.";
328+
desc->location = uniform.location;
329+
desc->rows = uniform.rows;
330+
desc->columns = uniform.columns;
331+
auto uniform_type = ToUniformType(uniform.type);
332+
if (!uniform_type.has_value()) {
333+
VALIDATION_LOG << "Invalid uniform type for runtime stage.";
312334
return nullptr;
313335
}
314-
if (kvp.second->shader->GetSize() > 0u) {
315-
runtime_stage->shader = {
316-
kvp.second->shader->GetMapping(),
317-
kvp.second->shader->GetMapping() + kvp.second->shader->GetSize()};
336+
desc->type = uniform_type.value();
337+
desc->bit_width = uniform.bit_width;
338+
if (uniform.array_elements.has_value()) {
339+
desc->array_elements = uniform.array_elements.value();
318340
}
319-
for (const auto& uniform : kvp.second->uniforms) {
320-
auto desc = std::make_unique<fb::UniformDescriptionT>();
321341

322-
desc->name = uniform.name;
323-
if (desc->name.empty()) {
324-
VALIDATION_LOG << "Uniform name cannot be empty.";
325-
return nullptr;
326-
}
327-
desc->location = uniform.location;
328-
desc->rows = uniform.rows;
329-
desc->columns = uniform.columns;
330-
auto uniform_type = ToUniformType(uniform.type);
331-
if (!uniform_type.has_value()) {
332-
VALIDATION_LOG << "Invalid uniform type for runtime stage.";
333-
return nullptr;
334-
}
335-
desc->type = uniform_type.value();
336-
desc->bit_width = uniform.bit_width;
337-
if (uniform.array_elements.has_value()) {
338-
desc->array_elements = uniform.array_elements.value();
339-
}
342+
runtime_stage->uniforms.emplace_back(std::move(desc));
343+
}
344+
345+
for (const auto& input : kvp->second->inputs) {
346+
auto desc = std::make_unique<fb::StageInputT>();
347+
348+
desc->name = input.name;
340349

341-
runtime_stage->uniforms.emplace_back(std::move(desc));
350+
if (desc->name.empty()) {
351+
VALIDATION_LOG << "Stage input name cannot be empty.";
352+
return nullptr;
353+
}
354+
desc->location = input.location;
355+
desc->set = input.set;
356+
desc->binding = input.binding;
357+
auto input_type = ToInputType(input.type);
358+
if (!input_type.has_value()) {
359+
VALIDATION_LOG << "Invalid uniform type for runtime stage.";
360+
return nullptr;
342361
}
362+
desc->type = input_type.value();
363+
desc->bit_width = input.bit_width;
364+
desc->vec_size = input.vec_size;
365+
desc->columns = input.columns;
366+
desc->offset = input.offset;
343367

344-
for (const auto& input : kvp.second->inputs) {
345-
auto desc = std::make_unique<fb::StageInputT>();
368+
runtime_stage->inputs.emplace_back(std::move(desc));
369+
}
346370

347-
desc->name = input.name;
371+
return runtime_stage;
372+
}
348373

349-
if (desc->name.empty()) {
350-
VALIDATION_LOG << "Stage input name cannot be empty.";
351-
return nullptr;
352-
}
353-
desc->location = input.location;
354-
desc->set = input.set;
355-
desc->binding = input.binding;
356-
auto input_type = ToInputType(input.type);
357-
if (!input_type.has_value()) {
358-
VALIDATION_LOG << "Invalid uniform type for runtime stage.";
359-
return nullptr;
360-
}
361-
desc->type = input_type.value();
362-
desc->bit_width = input.bit_width;
363-
desc->vec_size = input.vec_size;
364-
desc->columns = input.columns;
365-
desc->offset = input.offset;
374+
std::unique_ptr<fb::RuntimeStagesT>
375+
RuntimeStageData::CreateMultiStageFlatbuffer() const {
376+
// The high level object API is used here for writing to the buffer. This is
377+
// just a convenience.
378+
auto runtime_stages = std::make_unique<fb::RuntimeStagesT>();
366379

367-
runtime_stage->inputs.emplace_back(std::move(desc));
368-
}
380+
for (const auto& kvp : data_) {
381+
auto runtime_stage = CreateStageFlatbuffer(kvp.first);
369382
switch (kvp.first) {
370383
case RuntimeStageBackend::kSkSL:
371384
runtime_stages->sksl = std::move(runtime_stage);
@@ -385,7 +398,7 @@ std::unique_ptr<fb::RuntimeStagesT> RuntimeStageData::CreateFlatbuffer() const {
385398
}
386399

387400
std::shared_ptr<fml::Mapping> RuntimeStageData::CreateMapping() const {
388-
auto runtime_stages = CreateFlatbuffer();
401+
auto runtime_stages = CreateMultiStageFlatbuffer();
389402
if (!runtime_stages) {
390403
return nullptr;
391404
}

impeller/compiler/runtime_stage_data.h

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,6 @@
1818
namespace impeller {
1919
namespace compiler {
2020

21-
struct UniformDescription {
22-
std::string name;
23-
size_t location = 0u;
24-
spirv_cross::SPIRType::BaseType type = spirv_cross::SPIRType::BaseType::Float;
25-
size_t rows = 0u;
26-
size_t columns = 0u;
27-
size_t bit_width = 0u;
28-
std::optional<size_t> array_elements = std::nullopt;
29-
};
30-
31-
struct InputDescription {
32-
std::string name;
33-
size_t location;
34-
size_t set;
35-
size_t binding;
36-
spirv_cross::SPIRType::BaseType type =
37-
spirv_cross::SPIRType::BaseType::Unknown;
38-
size_t bit_width;
39-
size_t vec_size;
40-
size_t columns;
41-
size_t offset;
42-
};
43-
4421
class RuntimeStageData {
4522
public:
4623
struct Shader {
@@ -63,7 +40,10 @@ class RuntimeStageData {
6340

6441
void AddShader(const std::shared_ptr<Shader>& data);
6542

66-
std::unique_ptr<fb::RuntimeStagesT> CreateFlatbuffer() const;
43+
std::unique_ptr<fb::RuntimeStageT> CreateStageFlatbuffer(
44+
impeller::RuntimeStageBackend backend) const;
45+
46+
std::unique_ptr<fb::RuntimeStagesT> CreateMultiStageFlatbuffer() const;
6747

6848
std::shared_ptr<fml::Mapping> CreateJsonMapping() const;
6949

0 commit comments

Comments
 (0)