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

Commit d079196

Browse files
authored
[Impeller] Implement RuntimeEffectContents (#36866)
1 parent 7d18d70 commit d079196

File tree

16 files changed

+348
-13
lines changed

16 files changed

+348
-13
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,8 @@ FILE: ../../../flutter/impeller/entity/contents/radial_gradient_contents.cc
12141214
FILE: ../../../flutter/impeller/entity/contents/radial_gradient_contents.h
12151215
FILE: ../../../flutter/impeller/entity/contents/rrect_shadow_contents.cc
12161216
FILE: ../../../flutter/impeller/entity/contents/rrect_shadow_contents.h
1217+
FILE: ../../../flutter/impeller/entity/contents/runtime_effect_contents.cc
1218+
FILE: ../../../flutter/impeller/entity/contents/runtime_effect_contents.h
12171219
FILE: ../../../flutter/impeller/entity/contents/solid_color_contents.cc
12181220
FILE: ../../../flutter/impeller/entity/contents/solid_color_contents.h
12191221
FILE: ../../../flutter/impeller/entity/contents/solid_stroke_contents.cc
@@ -1280,6 +1282,7 @@ FILE: ../../../flutter/impeller/entity/shaders/morphology_filter.frag
12801282
FILE: ../../../flutter/impeller/entity/shaders/morphology_filter.vert
12811283
FILE: ../../../flutter/impeller/entity/shaders/position.vert
12821284
FILE: ../../../flutter/impeller/entity/shaders/position_color.vert
1285+
FILE: ../../../flutter/impeller/entity/shaders/position_no_color.vert
12831286
FILE: ../../../flutter/impeller/entity/shaders/position_uv.vert
12841287
FILE: ../../../flutter/impeller/entity/shaders/radial_gradient_fill.frag
12851288
FILE: ../../../flutter/impeller/entity/shaders/rrect_blur.frag
@@ -1555,6 +1558,7 @@ FILE: ../../../flutter/impeller/runtime_stage/runtime_stage.h
15551558
FILE: ../../../flutter/impeller/runtime_stage/runtime_stage_playground.cc
15561559
FILE: ../../../flutter/impeller/runtime_stage/runtime_stage_playground.h
15571560
FILE: ../../../flutter/impeller/runtime_stage/runtime_stage_unittests.cc
1561+
FILE: ../../../flutter/impeller/runtime_stage/runtime_types.cc
15581562
FILE: ../../../flutter/impeller/runtime_stage/runtime_types.h
15591563
FILE: ../../../flutter/impeller/tessellator/c/tessellator.cc
15601564
FILE: ../../../flutter/impeller/tessellator/c/tessellator.h

impeller/display_list/display_list_dispatcher.cc

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,14 @@
55
#include "impeller/display_list/display_list_dispatcher.h"
66

77
#include <algorithm>
8+
#include <cstring>
9+
#include <memory>
810
#include <optional>
911
#include <unordered_map>
1012

1113
#include "display_list/display_list_blend_mode.h"
1214
#include "display_list/display_list_color_filter.h"
15+
#include "display_list/display_list_color_source.h"
1316
#include "display_list/display_list_path_effect.h"
1417
#include "display_list/display_list_tile_mode.h"
1518
#include "flutter/fml/logging.h"
@@ -21,6 +24,7 @@
2124
#include "impeller/entity/contents/filters/inputs/filter_input.h"
2225
#include "impeller/entity/contents/linear_gradient_contents.h"
2326
#include "impeller/entity/contents/radial_gradient_contents.h"
27+
#include "impeller/entity/contents/runtime_effect_contents.h"
2428
#include "impeller/entity/contents/solid_stroke_contents.h"
2529
#include "impeller/entity/contents/sweep_gradient_contents.h"
2630
#include "impeller/entity/contents/tiled_texture_contents.h"
@@ -425,8 +429,28 @@ void DisplayListDispatcher::setColorSource(
425429
};
426430
return;
427431
}
432+
case flutter::DlColorSourceType::kRuntimeEffect: {
433+
const flutter::DlRuntimeEffectColorSource* runtime_effect_color_source =
434+
source->asRuntimeEffect();
435+
auto runtime_stage =
436+
runtime_effect_color_source->runtime_effect()->runtime_stage();
437+
auto uniform_data_sk = runtime_effect_color_source->uniform_data();
438+
439+
paint_.color_source = [runtime_stage, uniform_data_sk]() {
440+
// TODO(113714): Get rid of the allocation + copy for uniform data.
441+
std::vector<uint8_t> uniform_data;
442+
uniform_data.resize(uniform_data_sk->size());
443+
memcpy(uniform_data.data(), uniform_data_sk->bytes(),
444+
uniform_data.size());
445+
446+
auto contents = std::make_shared<RuntimeEffectContents>();
447+
contents->SetRuntimeStage(runtime_stage);
448+
contents->SetUniformData(std::move(uniform_data));
449+
return contents;
450+
};
451+
return;
452+
}
428453
case flutter::DlColorSourceType::kConicalGradient:
429-
case flutter::DlColorSourceType::kRuntimeEffect:
430454
case flutter::DlColorSourceType::kUnknown:
431455
UNIMPLEMENTED;
432456
break;

impeller/entity/BUILD.gn

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ impeller_shaders("entity_shaders") {
4444
"shaders/linear_gradient_fill.frag",
4545
"shaders/morphology_filter.frag",
4646
"shaders/morphology_filter.vert",
47+
"shaders/position_color.vert",
48+
"shaders/position_no_color.vert",
49+
"shaders/position_uv.vert",
50+
"shaders/position.vert",
4751
"shaders/radial_gradient_fill.frag",
4852
"shaders/rrect_blur.vert",
4953
"shaders/rrect_blur.frag",
@@ -57,9 +61,6 @@ impeller_shaders("entity_shaders") {
5761
"shaders/tiled_texture_fill.frag",
5862
"shaders/tiled_texture_fill.vert",
5963
"shaders/vertices.frag",
60-
"shaders/position_color.vert",
61-
"shaders/position.vert",
62-
"shaders/position_uv.vert",
6364
]
6465
}
6566

@@ -113,6 +114,8 @@ impeller_component("entity") {
113114
"contents/radial_gradient_contents.h",
114115
"contents/rrect_shadow_contents.cc",
115116
"contents/rrect_shadow_contents.h",
117+
"contents/runtime_effect_contents.cc",
118+
"contents/runtime_effect_contents.h",
116119
"contents/solid_color_contents.cc",
117120
"contents/solid_color_contents.h",
118121
"contents/solid_stroke_contents.cc",
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
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/entity/contents/runtime_effect_contents.h"
6+
7+
#include <future>
8+
#include <memory>
9+
10+
#include "flutter/fml/logging.h"
11+
#include "flutter/fml/make_copyable.h"
12+
#include "impeller/base/validation.h"
13+
#include "impeller/entity/contents/clip_contents.h"
14+
#include "impeller/entity/contents/content_context.h"
15+
#include "impeller/entity/position_no_color.vert.h"
16+
#include "impeller/renderer/formats.h"
17+
#include "impeller/renderer/pipeline_library.h"
18+
#include "impeller/renderer/render_pass.h"
19+
#include "impeller/renderer/shader_function.h"
20+
#include "impeller/renderer/shader_types.h"
21+
22+
namespace impeller {
23+
24+
void RuntimeEffectContents::SetRuntimeStage(
25+
std::shared_ptr<RuntimeStage> runtime_stage) {
26+
runtime_stage_ = std::move(runtime_stage);
27+
}
28+
29+
void RuntimeEffectContents::SetUniformData(std::vector<uint8_t> uniform_data) {
30+
uniform_data_ = std::move(uniform_data);
31+
}
32+
33+
bool RuntimeEffectContents::Render(const ContentContext& renderer,
34+
const Entity& entity,
35+
RenderPass& pass) const {
36+
auto context = renderer.GetContext();
37+
auto library = context->GetShaderLibrary();
38+
39+
//--------------------------------------------------------------------------
40+
/// Get or register shader.
41+
///
42+
43+
// TODO(113719): Register the shader function earlier.
44+
45+
std::shared_ptr<const ShaderFunction> function = library->GetFunction(
46+
runtime_stage_->GetEntrypoint(), ShaderStage::kFragment);
47+
48+
if (!function) {
49+
std::promise<bool> promise;
50+
auto future = promise.get_future();
51+
52+
library->RegisterFunction(
53+
runtime_stage_->GetEntrypoint(),
54+
ToShaderStage(runtime_stage_->GetShaderStage()),
55+
runtime_stage_->GetCodeMapping(),
56+
fml::MakeCopyable([promise = std::move(promise)](bool result) mutable {
57+
promise.set_value(result);
58+
}));
59+
60+
if (!future.get()) {
61+
VALIDATION_LOG << "Failed to build runtime effect (entry point: "
62+
<< runtime_stage_->GetEntrypoint() << ")";
63+
return false;
64+
}
65+
66+
function = library->GetFunction(runtime_stage_->GetEntrypoint(),
67+
ShaderStage::kFragment);
68+
if (!function) {
69+
VALIDATION_LOG
70+
<< "Failed to fetch runtime effect function immediately after "
71+
"registering it (entry point: "
72+
<< runtime_stage_->GetEntrypoint() << ")";
73+
return false;
74+
}
75+
}
76+
77+
//--------------------------------------------------------------------------
78+
/// Resolve geometry.
79+
///
80+
81+
auto geometry_result = GetGeometry()->GetPositionBuffer(
82+
context->GetResourceAllocator(), pass.GetTransientsBuffer(),
83+
renderer.GetTessellator(), pass.GetRenderTargetSize());
84+
85+
//--------------------------------------------------------------------------
86+
/// Get or create runtime stage pipeline.
87+
///
88+
89+
using VS = PositionNoColorVertexShader;
90+
PipelineDescriptor desc;
91+
desc.SetLabel("Runtime Stage");
92+
desc.AddStageEntrypoint(
93+
library->GetFunction(VS::kEntrypointName, ShaderStage::kVertex));
94+
desc.AddStageEntrypoint(library->GetFunction(runtime_stage_->GetEntrypoint(),
95+
ShaderStage::kFragment));
96+
auto vertex_descriptor = std::make_shared<VertexDescriptor>();
97+
if (!vertex_descriptor->SetStageInputs(VS::kAllShaderStageInputs)) {
98+
VALIDATION_LOG << "Failed to set stage inputs for runtime effect pipeline.";
99+
}
100+
desc.SetVertexDescriptor(std::move(vertex_descriptor));
101+
desc.SetColorAttachmentDescriptor(0u, {.format = PixelFormat::kDefaultColor});
102+
desc.SetStencilAttachmentDescriptors({});
103+
desc.SetStencilPixelFormat(PixelFormat::kDefaultStencil);
104+
105+
auto options = OptionsFromPassAndEntity(pass, entity);
106+
if (geometry_result.prevent_overdraw) {
107+
options.stencil_compare = CompareFunction::kEqual;
108+
options.stencil_operation = StencilOperation::kIncrementClamp;
109+
}
110+
options.ApplyToPipelineDescriptor(desc);
111+
112+
auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).get();
113+
if (!pipeline) {
114+
VALIDATION_LOG << "Failed to get or create runtime effect pipeline.";
115+
return false;
116+
}
117+
118+
Command cmd;
119+
cmd.label = "RuntimeEffectContents";
120+
cmd.pipeline = pipeline;
121+
cmd.stencil_reference = entity.GetStencilDepth();
122+
cmd.BindVertices(geometry_result.vertex_buffer);
123+
cmd.primitive_type = geometry_result.type;
124+
125+
//--------------------------------------------------------------------------
126+
/// Vertex stage uniforms.
127+
///
128+
129+
VS::VertInfo frame_info;
130+
frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) *
131+
entity.GetTransformation();
132+
VS::BindVertInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info));
133+
134+
//--------------------------------------------------------------------------
135+
/// Fragment stage uniforms.
136+
///
137+
138+
size_t buffer_index = 0;
139+
for (auto uniform : runtime_stage_->GetUniforms()) {
140+
// TODO(113715): Populate this metadata once GLES is able to handle
141+
// non-struct uniform names.
142+
ShaderMetadata metadata;
143+
144+
size_t alignment =
145+
std::max(uniform.bit_width / 8, DefaultUniformAlignment());
146+
auto buffer_view = pass.GetTransientsBuffer().Emplace(
147+
&uniform_data_[uniform.location * sizeof(float)], uniform.GetSize(),
148+
alignment);
149+
150+
ShaderUniformSlot slot;
151+
slot.name = uniform.name.c_str();
152+
slot.ext_res_0 = buffer_index;
153+
cmd.BindResource(ShaderStage::kFragment, slot, metadata, buffer_view);
154+
155+
buffer_index++;
156+
}
157+
158+
pass.AddCommand(std::move(cmd));
159+
160+
if (geometry_result.prevent_overdraw) {
161+
return ClipRestoreContents().Render(renderer, entity, pass);
162+
}
163+
return true;
164+
}
165+
166+
} // namespace impeller
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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 <functional>
6+
#include <memory>
7+
8+
#include "impeller/entity/contents/color_source_contents.h"
9+
#include "impeller/runtime_stage/runtime_stage.h"
10+
11+
namespace impeller {
12+
13+
class RuntimeEffectContents final : public ColorSourceContents {
14+
public:
15+
void SetRuntimeStage(std::shared_ptr<RuntimeStage> runtime_stage);
16+
17+
void SetUniformData(std::vector<uint8_t> uniform_data);
18+
19+
// |Contents|
20+
bool Render(const ContentContext& renderer,
21+
const Entity& entity,
22+
RenderPass& pass) const override;
23+
24+
private:
25+
std::shared_ptr<RuntimeStage> runtime_stage_;
26+
std::vector<uint8_t> uniform_data_;
27+
};
28+
29+
} // namespace impeller

impeller/entity/entity_unittests.cc

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
// found in the LICENSE file.
44

55
#include <algorithm>
6+
#include <cstring>
67
#include <memory>
78
#include <optional>
89
#include <unordered_map>
910
#include <vector>
1011

1112
#include "flutter/testing/testing.h"
1213
#include "fml/logging.h"
14+
#include "fml/time/time_point.h"
1315
#include "gtest/gtest.h"
1416
#include "impeller/entity/contents/atlas_contents.h"
1517
#include "impeller/entity/contents/clip_contents.h"
@@ -19,6 +21,7 @@
1921
#include "impeller/entity/contents/filters/filter_contents.h"
2022
#include "impeller/entity/contents/filters/inputs/filter_input.h"
2123
#include "impeller/entity/contents/rrect_shadow_contents.h"
24+
#include "impeller/entity/contents/runtime_effect_contents.h"
2225
#include "impeller/entity/contents/solid_color_contents.h"
2326
#include "impeller/entity/contents/solid_stroke_contents.h"
2427
#include "impeller/entity/contents/text_contents.h"
@@ -37,6 +40,7 @@
3740
#include "impeller/playground/widgets.h"
3841
#include "impeller/renderer/render_pass.h"
3942
#include "impeller/renderer/vertex_buffer_builder.h"
43+
#include "impeller/runtime_stage/runtime_stage.h"
4044
#include "impeller/tessellator/tessellator.h"
4145
#include "impeller/typographer/backends/skia/text_frame_skia.h"
4246
#include "impeller/typographer/backends/skia/text_render_context_skia.h"
@@ -2026,5 +2030,38 @@ TEST_P(EntityTest, SdfText) {
20262030
ASSERT_TRUE(OpenPlaygroundHere(callback));
20272031
}
20282032

2033+
TEST_P(EntityTest, RuntimeEffect) {
2034+
if (GetParam() != PlaygroundBackend::kMetal) {
2035+
GTEST_SKIP_("This test only has a Metal fixture at the moment.");
2036+
}
2037+
2038+
auto callback = [&](ContentContext& context, RenderPass& pass) -> bool {
2039+
auto contents = std::make_shared<RuntimeEffectContents>();
2040+
contents->SetGeometry(Geometry::MakeCover());
2041+
2042+
auto runtime_stage =
2043+
LoadFixtureRuntimeStage("runtime_stage_example.frag.iplr");
2044+
contents->SetRuntimeStage(runtime_stage);
2045+
2046+
struct FragUniforms {
2047+
Scalar iTime;
2048+
Vector2 iResolution;
2049+
} frag_uniforms = {
2050+
.iTime = static_cast<Scalar>(
2051+
fml::TimePoint::Now().ToEpochDelta().ToSecondsF()),
2052+
.iResolution = Vector2(GetWindowSize().width, GetWindowSize().height),
2053+
};
2054+
std::vector<uint8_t> uniform_data;
2055+
uniform_data.resize(sizeof(FragUniforms));
2056+
memcpy(uniform_data.data(), &frag_uniforms, sizeof(FragUniforms));
2057+
contents->SetUniformData(uniform_data);
2058+
2059+
Entity entity;
2060+
entity.SetContents(contents);
2061+
return contents->Render(context, entity, pass);
2062+
};
2063+
ASSERT_TRUE(OpenPlaygroundHere(callback));
2064+
}
2065+
20292066
} // namespace testing
20302067
} // namespace impeller
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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/transform.glsl>
6+
7+
uniform VertInfo {
8+
mat4 mvp;
9+
} vert_info;
10+
11+
in vec2 position;
12+
out vec2 v_position;
13+
14+
void main() {
15+
gl_Position = vert_info.mvp * vec4(position, 0.0, 1.0);
16+
v_position = IPVec2TransformPosition(vert_info.mvp, position);
17+
}

0 commit comments

Comments
 (0)