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

Commit 9a40a38

Browse files
authored
[Impeller] Support blit passes on Vulkan. (#39438)
fixes: flutter/flutter#112649
1 parent e50569b commit 9a40a38

File tree

10 files changed

+456
-43
lines changed

10 files changed

+456
-43
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1506,6 +1506,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h
15061506
ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm + ../../../flutter/LICENSE
15071507
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc + ../../../flutter/LICENSE
15081508
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h + ../../../flutter/LICENSE
1509+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc + ../../../flutter/LICENSE
1510+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.h + ../../../flutter/LICENSE
15091511
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.cc + ../../../flutter/LICENSE
15101512
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.h + ../../../flutter/LICENSE
15111513
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc + ../../../flutter/LICENSE
@@ -1514,6 +1516,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc +
15141516
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h + ../../../flutter/LICENSE
15151517
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc + ../../../flutter/LICENSE
15161518
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h + ../../../flutter/LICENSE
1519+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.cc + ../../../flutter/LICENSE
1520+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.h + ../../../flutter/LICENSE
15171521
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc + ../../../flutter/LICENSE
15181522
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h + ../../../flutter/LICENSE
15191523
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/deletion_queue_vk.cc + ../../../flutter/LICENSE
@@ -3987,6 +3991,8 @@ FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h
39873991
FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm
39883992
FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc
39893993
FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h
3994+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc
3995+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.h
39903996
FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.cc
39913997
FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.h
39923998
FILE: ../../../flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc
@@ -3995,6 +4001,8 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc
39954001
FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h
39964002
FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc
39974003
FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h
4004+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.cc
4005+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.h
39984006
FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc
39994007
FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h
40004008
FILE: ../../../flutter/impeller/renderer/backend/vulkan/deletion_queue_vk.cc

impeller/renderer/backend/vulkan/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ impeller_component("vulkan") {
88
sources = [
99
"allocator_vk.cc",
1010
"allocator_vk.h",
11+
"blit_command_vk.cc",
12+
"blit_command_vk.h",
1113
"blit_pass_vk.cc",
1214
"blit_pass_vk.h",
1315
"capabilities_vk.cc",
@@ -16,6 +18,8 @@ impeller_component("vulkan") {
1618
"command_buffer_vk.h",
1719
"command_pool_vk.cc",
1820
"command_pool_vk.h",
21+
"commands_vk.cc",
22+
"commands_vk.h",
1923
"context_vk.cc",
2024
"context_vk.h",
2125
"deletion_queue_vk.cc",
Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
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/renderer/backend/vulkan/blit_command_vk.h"
6+
7+
#include "impeller/renderer/backend/vulkan/commands_vk.h"
8+
#include "impeller/renderer/backend/vulkan/texture_vk.h"
9+
10+
namespace impeller {
11+
12+
BlitEncodeVK::~BlitEncodeVK() = default;
13+
14+
//------------------------------------------------------------------------------
15+
/// BlitCopyTextureToTextureCommandVK
16+
///
17+
18+
BlitCopyTextureToTextureCommandVK::~BlitCopyTextureToTextureCommandVK() =
19+
default;
20+
21+
std::string BlitCopyTextureToTextureCommandVK::GetLabel() const {
22+
return label;
23+
}
24+
25+
[[nodiscard]] bool BlitCopyTextureToTextureCommandVK::Encode(
26+
FencedCommandBufferVK* fenced_command_buffer) const {
27+
// cast source and destination to TextureVK
28+
const auto& source_tex_vk = TextureVK::Cast(*source);
29+
const auto& dest_tex_vk = TextureVK::Cast(*destination);
30+
31+
// get the vulkan image and image view
32+
const auto source_image = source_tex_vk.GetImage();
33+
const auto dest_image = dest_tex_vk.GetImage();
34+
35+
// copy the source image to the destination image, from source_region to
36+
// destination_origin.
37+
vk::ImageCopy image_copy;
38+
image_copy.setSrcSubresource(
39+
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
40+
image_copy.setDstSubresource(
41+
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
42+
43+
image_copy.srcOffset =
44+
vk::Offset3D(source_region.origin.x, source_region.origin.y, 0);
45+
image_copy.dstOffset =
46+
vk::Offset3D(destination_origin.x, destination_origin.y, 0);
47+
image_copy.extent =
48+
vk::Extent3D(source_region.size.width, source_region.size.height, 1);
49+
50+
// get single use command buffer
51+
auto copy_cmd = fenced_command_buffer->GetSingleUseChild();
52+
53+
vk::CommandBufferBeginInfo begin_info;
54+
begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
55+
auto res = copy_cmd.begin(begin_info);
56+
57+
if (res != vk::Result::eSuccess) {
58+
VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res);
59+
return false;
60+
}
61+
62+
// transition the source image to transfer source optimal
63+
TransitionImageLayoutCommandVK transition_source_cmd =
64+
TransitionImageLayoutCommandVK(source_image, vk::ImageLayout::eUndefined,
65+
vk::ImageLayout::eTransferSrcOptimal);
66+
bool success = transition_source_cmd.Submit(fenced_command_buffer);
67+
if (!success) {
68+
VALIDATION_LOG << "Failed to transition source image layout";
69+
return false;
70+
}
71+
72+
// transition the destination image to transfer destination optimal
73+
TransitionImageLayoutCommandVK transition_dest_cmd =
74+
TransitionImageLayoutCommandVK(dest_image, vk::ImageLayout::eUndefined,
75+
vk::ImageLayout::eTransferDstOptimal);
76+
success = transition_dest_cmd.Submit(fenced_command_buffer);
77+
if (!success) {
78+
VALIDATION_LOG << "Failed to transition destination image layout";
79+
return false;
80+
}
81+
82+
// issue the copy command
83+
copy_cmd.copyImage(source_image, vk::ImageLayout::eTransferSrcOptimal,
84+
dest_image, vk::ImageLayout::eTransferDstOptimal,
85+
image_copy);
86+
res = copy_cmd.end();
87+
if (res != vk::Result::eSuccess) {
88+
VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res);
89+
return false;
90+
}
91+
92+
return true;
93+
}
94+
95+
//------------------------------------------------------------------------------
96+
/// BlitCopyTextureToBufferCommandVK
97+
///
98+
99+
BlitCopyTextureToBufferCommandVK::~BlitCopyTextureToBufferCommandVK() = default;
100+
101+
std::string BlitCopyTextureToBufferCommandVK::GetLabel() const {
102+
return label;
103+
}
104+
105+
[[nodiscard]] bool BlitCopyTextureToBufferCommandVK::Encode(
106+
FencedCommandBufferVK* fenced_command_buffer) const {
107+
// cast source and destination to TextureVK
108+
const auto& source_tex_vk = TextureVK::Cast(*source);
109+
const auto& dest_buf_vk = DeviceBufferVK::Cast(*destination);
110+
111+
// get the vulkan image and image view
112+
const auto source_image = source_tex_vk.GetImage();
113+
114+
// get buffer image handle
115+
const auto dest_buffer = dest_buf_vk.GetVKBufferHandle();
116+
117+
// copy the source image to the destination buffer, from source_region to
118+
// destination_origin.
119+
vk::BufferImageCopy image_copy{};
120+
image_copy.setBufferOffset(destination_offset);
121+
image_copy.setBufferRowLength(0);
122+
image_copy.setBufferImageHeight(0);
123+
image_copy.setImageSubresource(
124+
vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
125+
image_copy.setImageOffset(
126+
vk::Offset3D(source_region.origin.x, source_region.origin.y, 0));
127+
image_copy.setImageExtent(
128+
vk::Extent3D(source_region.size.width, source_region.size.height, 1));
129+
130+
// transition the source image to transfer source optimal
131+
TransitionImageLayoutCommandVK transition_source_cmd =
132+
TransitionImageLayoutCommandVK(source_image, vk::ImageLayout::eUndefined,
133+
vk::ImageLayout::eTransferSrcOptimal);
134+
bool success = transition_source_cmd.Submit(fenced_command_buffer);
135+
if (!success) {
136+
return false;
137+
}
138+
139+
// get single use command buffer
140+
auto copy_cmd = fenced_command_buffer->GetSingleUseChild();
141+
142+
vk::CommandBufferBeginInfo begin_info;
143+
begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
144+
auto res = copy_cmd.begin(begin_info);
145+
146+
if (res != vk::Result::eSuccess) {
147+
VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res);
148+
return false;
149+
}
150+
151+
// issue the copy command
152+
copy_cmd.copyImageToBuffer(source_image, vk::ImageLayout::eTransferSrcOptimal,
153+
dest_buffer, image_copy);
154+
res = copy_cmd.end();
155+
if (res != vk::Result::eSuccess) {
156+
VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res);
157+
}
158+
159+
return true;
160+
}
161+
162+
//------------------------------------------------------------------------------
163+
/// BlitGenerateMipmapCommandVK
164+
///
165+
166+
BlitGenerateMipmapCommandVK::~BlitGenerateMipmapCommandVK() = default;
167+
168+
std::string BlitGenerateMipmapCommandVK::GetLabel() const {
169+
return label;
170+
}
171+
172+
[[nodiscard]] bool BlitGenerateMipmapCommandVK::Encode(
173+
FencedCommandBufferVK* fenced_command_buffer) const {
174+
// TODO(https://github.com/flutter/flutter/issues/120134): Support generating
175+
// mipmaps on Vulkan.
176+
IMPELLER_UNIMPLEMENTED;
177+
return true;
178+
}
179+
180+
// END: BlitGenerateMipmapCommandVK
181+
182+
} // namespace impeller
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
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+
#pragma once
6+
7+
#include <memory>
8+
#include "impeller/base/backend_cast.h"
9+
#include "impeller/renderer/backend/vulkan/context_vk.h"
10+
#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h"
11+
#include "impeller/renderer/blit_command.h"
12+
#include "impeller/renderer/context.h"
13+
14+
namespace impeller {
15+
16+
/// Mixin for dispatching Vulkan commands.
17+
struct BlitEncodeVK : BackendCast<BlitEncodeVK, BlitCommand> {
18+
virtual ~BlitEncodeVK();
19+
20+
virtual std::string GetLabel() const = 0;
21+
22+
[[nodiscard]] virtual bool Encode(
23+
FencedCommandBufferVK* fenced_command_buffer) const = 0;
24+
};
25+
26+
struct BlitCopyTextureToTextureCommandVK
27+
: public BlitCopyTextureToTextureCommand,
28+
public BlitEncodeVK {
29+
~BlitCopyTextureToTextureCommandVK() override;
30+
31+
std::string GetLabel() const override;
32+
33+
[[nodiscard]] bool Encode(
34+
FencedCommandBufferVK* fenced_command_buffer) const override;
35+
};
36+
37+
struct BlitCopyTextureToBufferCommandVK : public BlitCopyTextureToBufferCommand,
38+
public BlitEncodeVK {
39+
~BlitCopyTextureToBufferCommandVK() override;
40+
41+
std::string GetLabel() const override;
42+
43+
[[nodiscard]] bool Encode(
44+
FencedCommandBufferVK* fenced_command_buffer) const override;
45+
};
46+
47+
struct BlitGenerateMipmapCommandVK : public BlitGenerateMipmapCommand,
48+
public BlitEncodeVK {
49+
~BlitGenerateMipmapCommandVK() override;
50+
51+
std::string GetLabel() const override;
52+
53+
[[nodiscard]] bool Encode(
54+
FencedCommandBufferVK* fenced_command_buffer) const override;
55+
};
56+
57+
} // namespace impeller

impeller/renderer/backend/vulkan/blit_pass_vk.cc

Lines changed: 85 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,92 @@
44

55
#include "impeller/renderer/backend/vulkan/blit_pass_vk.h"
66

7+
#include "flutter/fml/logging.h"
8+
#include "flutter/fml/trace_event.h"
9+
710
namespace impeller {
811

9-
//
12+
BlitPassVK::BlitPassVK(std::shared_ptr<FencedCommandBufferVK> command_buffer)
13+
: command_buffer_(std::move(command_buffer)) {}
14+
15+
BlitPassVK::~BlitPassVK() = default;
16+
17+
void BlitPassVK::OnSetLabel(std::string label) {
18+
if (label.empty()) {
19+
return;
20+
}
21+
label_ = std::move(label);
22+
}
23+
24+
// |BlitPass|
25+
bool BlitPassVK::IsValid() const {
26+
return command_buffer_ != nullptr;
27+
}
28+
29+
// |BlitPass|
30+
bool BlitPassVK::EncodeCommands(
31+
const std::shared_ptr<Allocator>& transients_allocator) const {
32+
TRACE_EVENT0("impeller", "BlitPassVK::EncodeCommands");
33+
34+
if (!IsValid()) {
35+
return false;
36+
}
37+
38+
for (auto& command : commands_) {
39+
bool encode_res = command->Encode(command_buffer_.get());
40+
if (!encode_res) {
41+
return false;
42+
}
43+
}
44+
45+
return true;
46+
}
47+
48+
// |BlitPass|
49+
bool BlitPassVK::OnCopyTextureToTextureCommand(
50+
std::shared_ptr<Texture> source,
51+
std::shared_ptr<Texture> destination,
52+
IRect source_region,
53+
IPoint destination_origin,
54+
std::string label) {
55+
auto command = std::make_unique<BlitCopyTextureToTextureCommandVK>();
56+
command->source = std::move(source);
57+
command->destination = std::move(destination);
58+
command->source_region = source_region;
59+
command->destination_origin = destination_origin;
60+
command->label = std::move(label);
61+
62+
commands_.push_back(std::move(command));
63+
return true;
64+
}
65+
66+
// |BlitPass|
67+
bool BlitPassVK::OnCopyTextureToBufferCommand(
68+
std::shared_ptr<Texture> source,
69+
std::shared_ptr<DeviceBuffer> destination,
70+
IRect source_region,
71+
size_t destination_offset,
72+
std::string label) {
73+
auto command = std::make_unique<BlitCopyTextureToBufferCommandVK>();
74+
command->source = std::move(source);
75+
command->destination = std::move(destination);
76+
command->source_region = source_region;
77+
command->destination_offset = destination_offset;
78+
command->label = std::move(label);
79+
80+
commands_.push_back(std::move(command));
81+
return true;
82+
}
83+
84+
// |BlitPass|
85+
bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
86+
std::string label) {
87+
auto command = std::make_unique<BlitGenerateMipmapCommandVK>();
88+
command->texture = std::move(texture);
89+
command->label = std::move(label);
90+
91+
commands_.push_back(std::move(command));
92+
return true;
93+
}
1094

1195
} // namespace impeller

0 commit comments

Comments
 (0)