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

Commit ed0b701

Browse files
committed
[Impeller] Implement framebuffer-fetch via subpasses in Vulkan without extensions.
* Subpasses are not exposed in the HAL and the need for subpasses in Vulkan can be determined based on the presence and use of input-attachments in the shaders. This information is already reflected by the compiler. Because of this, all references to subpasses have been removed from APIs above the HAL. * `RenderPassBuilderVK` is a lightweight object used to generate render passes to use either with the pipelines (compat, base, or per-subpass) or during rendering along with the framebuffer. Using the builder also sets up the right subpass dependencies. As long as the builder contains compatible attachments and subpass counts, different subpasses stamped by the builder (via the `Build` method) are guaranteed to be compatible per the rules in the spec. * Pass attachments are now in the `eGeneral` layout. There was no observable difference in performance when manually inserting the right transitions. Except, a lot of transitions needed to be inserted. If we need it, we can add it back in short order. I wouldn't be averse to adding it if reviewers insist. * Depending on where the subpass cursor is for each command, a different pipeline variant is necessary. For instance, if a command uses a pipeline at subpass 1 of 10 and that same pipeline is reused later in say subpass 6, the variant for subpass 1 is not suitable for subpass 6 (`VkGraphicsPipelineCreateInfo::subpass(uint32_t)` is part of the compat rules). Creation of these subpass variants from the lone-pass (subpass index 0 of count 1) prototype is done via a preload operation with jobs submitted to a concurrent worker. The preload can only happen once the number of passes needed can be determined. On mobile and desktop devices at hand, the observation was that the variants obtained from the prototype already in a `PipelineCacheVK` was extremely fast. Even so, once the variant is obtained, it is cached in `PipelineVK`. Notably, this is not present in `PipelineCacheVK`. That top-level cache only contains prototypes for the lone-pass pipeline configuration. The allows for purging of subpass variants of which there can theoretically be an unbounded number, and also a single point where subpass prototype creation can be elided completely if the `rasterization_order_attachment_access` extension is present. * Speaking of the `rasterization_order_attachment_access` extension, its use has been removed in this patch. I am prototyping adding it back to measure the overhead introduced by manual subpass management. If the overhead is measurable, we can use the extension on devices that have it as an added optimization. * The complexity of command encoding remains linear (to the number of commands) per pass. * This patch only works on a single color attachment being used as an input attachment. While this is sufficient for current use cases, the Metal implementation is significantly more capable since the multiple attachments and attachment types (depth) are already supported. Rounding out support for this is in progress. * This patch contains some test harness updates for MoltenVK that will be backed out and submitted separately.
1 parent e212085 commit ed0b701

35 files changed

+1221
-921
lines changed

impeller/entity/contents/content_context.cc

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -238,64 +238,49 @@ ContentContext::ContentContext(
238238
if (context_->GetCapabilities()->SupportsFramebufferFetch()) {
239239
framebuffer_blend_color_pipelines_.CreateDefault(
240240
*context_, options_trianglestrip,
241-
{static_cast<Scalar>(BlendSelectValues::kColor), supports_decal},
242-
UseSubpassInput::kYes);
241+
{static_cast<Scalar>(BlendSelectValues::kColor), supports_decal});
243242
framebuffer_blend_colorburn_pipelines_.CreateDefault(
244243
*context_, options_trianglestrip,
245-
{static_cast<Scalar>(BlendSelectValues::kColorBurn), supports_decal},
246-
UseSubpassInput::kYes);
244+
{static_cast<Scalar>(BlendSelectValues::kColorBurn), supports_decal});
247245
framebuffer_blend_colordodge_pipelines_.CreateDefault(
248246
*context_, options_trianglestrip,
249-
{static_cast<Scalar>(BlendSelectValues::kColorDodge), supports_decal},
250-
UseSubpassInput::kYes);
247+
{static_cast<Scalar>(BlendSelectValues::kColorDodge), supports_decal});
251248
framebuffer_blend_darken_pipelines_.CreateDefault(
252249
*context_, options_trianglestrip,
253-
{static_cast<Scalar>(BlendSelectValues::kDarken), supports_decal},
254-
UseSubpassInput::kYes);
250+
{static_cast<Scalar>(BlendSelectValues::kDarken), supports_decal});
255251
framebuffer_blend_difference_pipelines_.CreateDefault(
256252
*context_, options_trianglestrip,
257-
{static_cast<Scalar>(BlendSelectValues::kDifference), supports_decal},
258-
UseSubpassInput::kYes);
253+
{static_cast<Scalar>(BlendSelectValues::kDifference), supports_decal});
259254
framebuffer_blend_exclusion_pipelines_.CreateDefault(
260255
*context_, options_trianglestrip,
261-
{static_cast<Scalar>(BlendSelectValues::kExclusion), supports_decal},
262-
UseSubpassInput::kYes);
256+
{static_cast<Scalar>(BlendSelectValues::kExclusion), supports_decal});
263257
framebuffer_blend_hardlight_pipelines_.CreateDefault(
264258
*context_, options_trianglestrip,
265-
{static_cast<Scalar>(BlendSelectValues::kHardLight), supports_decal},
266-
UseSubpassInput::kYes);
259+
{static_cast<Scalar>(BlendSelectValues::kHardLight), supports_decal});
267260
framebuffer_blend_hue_pipelines_.CreateDefault(
268261
*context_, options_trianglestrip,
269-
{static_cast<Scalar>(BlendSelectValues::kHue), supports_decal},
270-
UseSubpassInput::kYes);
262+
{static_cast<Scalar>(BlendSelectValues::kHue), supports_decal});
271263
framebuffer_blend_lighten_pipelines_.CreateDefault(
272264
*context_, options_trianglestrip,
273-
{static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal},
274-
UseSubpassInput::kYes);
265+
{static_cast<Scalar>(BlendSelectValues::kLighten), supports_decal});
275266
framebuffer_blend_luminosity_pipelines_.CreateDefault(
276267
*context_, options_trianglestrip,
277-
{static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal},
278-
UseSubpassInput::kYes);
268+
{static_cast<Scalar>(BlendSelectValues::kLuminosity), supports_decal});
279269
framebuffer_blend_multiply_pipelines_.CreateDefault(
280270
*context_, options_trianglestrip,
281-
{static_cast<Scalar>(BlendSelectValues::kMultiply), supports_decal},
282-
UseSubpassInput::kYes);
271+
{static_cast<Scalar>(BlendSelectValues::kMultiply), supports_decal});
283272
framebuffer_blend_overlay_pipelines_.CreateDefault(
284273
*context_, options_trianglestrip,
285-
{static_cast<Scalar>(BlendSelectValues::kOverlay), supports_decal},
286-
UseSubpassInput::kYes);
274+
{static_cast<Scalar>(BlendSelectValues::kOverlay), supports_decal});
287275
framebuffer_blend_saturation_pipelines_.CreateDefault(
288276
*context_, options_trianglestrip,
289-
{static_cast<Scalar>(BlendSelectValues::kSaturation), supports_decal},
290-
UseSubpassInput::kYes);
277+
{static_cast<Scalar>(BlendSelectValues::kSaturation), supports_decal});
291278
framebuffer_blend_screen_pipelines_.CreateDefault(
292279
*context_, options_trianglestrip,
293-
{static_cast<Scalar>(BlendSelectValues::kScreen), supports_decal},
294-
UseSubpassInput::kYes);
280+
{static_cast<Scalar>(BlendSelectValues::kScreen), supports_decal});
295281
framebuffer_blend_softlight_pipelines_.CreateDefault(
296282
*context_, options_trianglestrip,
297-
{static_cast<Scalar>(BlendSelectValues::kSoftLight), supports_decal},
298-
UseSubpassInput::kYes);
283+
{static_cast<Scalar>(BlendSelectValues::kSoftLight), supports_decal});
299284
}
300285

301286
blend_color_pipelines_.CreateDefault(

impeller/entity/contents/content_context.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -814,15 +814,13 @@ class ContentContext {
814814

815815
void CreateDefault(const Context& context,
816816
const ContentContextOptions& options,
817-
const std::initializer_list<Scalar>& constants = {},
818-
UseSubpassInput subpass_input = UseSubpassInput::kNo) {
817+
const std::initializer_list<Scalar>& constants = {}) {
819818
auto desc =
820819
PipelineT::Builder::MakeDefaultPipelineDescriptor(context, constants);
821820
if (!desc.has_value()) {
822821
VALIDATION_LOG << "Failed to create default pipeline.";
823822
return;
824823
}
825-
desc->SetUseSubpassInput(subpass_input);
826824
options.ApplyToPipelineDescriptor(*desc);
827825
SetDefault(options, std::make_unique<PipelineT>(context, desc));
828826
}

impeller/entity/entity_unittests.cc

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2689,39 +2689,6 @@ TEST_P(EntityTest, DecalSpecializationAppliedToMorphologyFilter) {
26892689
expected_constants);
26902690
}
26912691

2692-
TEST_P(EntityTest, FramebufferFetchPipelinesDeclareUsage) {
2693-
auto content_context =
2694-
ContentContext(GetContext(), TypographerContextSkia::Make());
2695-
if (!content_context.GetDeviceCapabilities().SupportsFramebufferFetch()) {
2696-
GTEST_SKIP() << "Framebuffer fetch not supported.";
2697-
}
2698-
2699-
ContentContextOptions options;
2700-
options.color_attachment_pixel_format = PixelFormat::kR8G8B8A8UNormInt;
2701-
auto color_burn =
2702-
content_context.GetFramebufferBlendColorBurnPipeline(options);
2703-
2704-
EXPECT_TRUE(color_burn->GetDescriptor().UsesSubpassInput());
2705-
}
2706-
2707-
TEST_P(EntityTest, PipelineDescriptorEqAndHash) {
2708-
auto desc_1 = std::make_shared<PipelineDescriptor>();
2709-
auto desc_2 = std::make_shared<PipelineDescriptor>();
2710-
2711-
EXPECT_TRUE(desc_1->IsEqual(*desc_2));
2712-
EXPECT_EQ(desc_1->GetHash(), desc_2->GetHash());
2713-
2714-
desc_1->SetUseSubpassInput(UseSubpassInput::kYes);
2715-
2716-
EXPECT_FALSE(desc_1->IsEqual(*desc_2));
2717-
EXPECT_NE(desc_1->GetHash(), desc_2->GetHash());
2718-
2719-
desc_2->SetUseSubpassInput(UseSubpassInput::kYes);
2720-
2721-
EXPECT_TRUE(desc_1->IsEqual(*desc_2));
2722-
EXPECT_EQ(desc_1->GetHash(), desc_2->GetHash());
2723-
}
2724-
27252692
// This doesn't really tell you if the hashes will have frequent
27262693
// collisions, but since this type is only used to hash a bounded
27272694
// set of options, we can just compare benchmarks.

impeller/fixtures/BUILD.gn

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import("//flutter/testing/testing.gni")
88
impeller_shaders("shader_fixtures") {
99
name = "fixtures"
1010

11+
# 2.3 adds support for framebuffer fetch in Metal.
12+
metal_version = "2.3"
13+
1114
# Not analyzing because they are not performance critical, and mipmap uses
1215
# textureLod, which uses an extension that malioc does not support.
1316
analyze = false
@@ -16,8 +19,9 @@ impeller_shaders("shader_fixtures") {
1619
"array.vert",
1720
"box_fade.frag",
1821
"box_fade.vert",
19-
"colors.vert",
2022
"colors.frag",
23+
"colors.vert",
24+
"half.frag",
2125
"impeller.frag",
2226
"impeller.vert",
2327
"inactive_uniforms.frag",
@@ -27,12 +31,16 @@ impeller_shaders("shader_fixtures") {
2731
"mipmaps.frag",
2832
"mipmaps.vert",
2933
"sample.comp",
34+
"sepia.frag",
35+
"sepia.vert",
36+
"simple.vert",
3037
"stage1.comp",
3138
"stage2.comp",
32-
"simple.vert",
39+
"swizzle.frag",
3340
"test_texture.frag",
3441
"test_texture.vert",
35-
"half.frag",
42+
"texture.frag",
43+
"texture.vert",
3644
]
3745

3846
if (impeller_enable_opengles) {

impeller/fixtures/sepia.frag

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+
out vec4 frag_color;
6+
7+
layout(input_attachment_index = 0) uniform subpassInputMS subpass_input;
8+
9+
void main() {
10+
// https://github.com/chinmaygarde/merle/blob/3eecb311ac8862c41f0c53a5d9b360be923142bb/src/texture.cc#L195
11+
const mat4 sepia_matrix = mat4(0.3588, 0.2990, 0.2392, 0.0000, //
12+
0.7044, 0.5870, 0.4696, 0.0000, //
13+
0.1368, 0.1140, 0.0912, 0.0000, //
14+
0.0000, 0.0000, 0.0000, 1.0000 //
15+
);
16+
frag_color = sepia_matrix * subpassLoad(subpass_input, 0);
17+
}

impeller/fixtures/sepia.vert

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
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+
uniform UniformBuffer {
6+
mat4 mvp;
7+
}
8+
uniform_buffer;
9+
10+
in vec3 vertex_position;
11+
12+
void main() {
13+
gl_Position = uniform_buffer.mvp * vec4(vertex_position, 1.0);
14+
}

impeller/fixtures/swizzle.frag

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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+
out vec4 frag_color;
6+
7+
layout(input_attachment_index = 0) uniform subpassInputMS subpass_input;
8+
9+
void main() {
10+
frag_color = subpassLoad(subpass_input, 0).gbra;
11+
}

impeller/fixtures/texture.frag

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
in vec2 interporlated_texture_coordinates;
6+
7+
out vec4 frag_color;
8+
9+
uniform sampler2D texture_contents;
10+
11+
void main() {
12+
frag_color = texture(texture_contents, interporlated_texture_coordinates);
13+
}

impeller/fixtures/texture.vert

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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+
uniform UniformBuffer {
6+
mat4 mvp;
7+
}
8+
uniform_buffer;
9+
10+
in vec3 vertex_position;
11+
in vec2 texture_coordinates;
12+
13+
out vec2 interpolated_texture_coordinates;
14+
15+
void main() {
16+
gl_Position = uniform_buffer.mvp * vec4(vertex_position, 1.0);
17+
interpolated_texture_coordinates = texture_coordinates;
18+
}

impeller/renderer/backend/vulkan/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ impeller_component("vulkan") {
7373
"pipeline_vk.h",
7474
"queue_vk.cc",
7575
"queue_vk.h",
76+
"render_pass_builder_vk.cc",
77+
"render_pass_builder_vk.h",
7678
"render_pass_vk.cc",
7779
"render_pass_vk.h",
7880
"resource_manager_vk.cc",

0 commit comments

Comments
 (0)