[Impeller] Support blit passes on Vulkan. (#39438)
fixes: https://github.com/flutter/flutter/issues/112649
diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter
index 9339938..5df8365 100644
--- a/ci/licenses_golden/licenses_flutter
+++ b/ci/licenses_golden/licenses_flutter
@@ -1506,6 +1506,8 @@
ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc + ../../../flutter/LICENSE
@@ -1514,6 +1516,8 @@
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.cc + ../../../flutter/LICENSE
+ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h + ../../../flutter/LICENSE
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.mm
FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc
FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h
+FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc
+FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.h
FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.cc
FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_pass_vk.h
FILE: ../../../flutter/impeller/renderer/backend/vulkan/capabilities_vk.cc
@@ -3995,6 +4001,8 @@
FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.h
FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.cc
FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_pool_vk.h
+FILE: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.cc
+FILE: ../../../flutter/impeller/renderer/backend/vulkan/commands_vk.h
FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.cc
FILE: ../../../flutter/impeller/renderer/backend/vulkan/context_vk.h
FILE: ../../../flutter/impeller/renderer/backend/vulkan/deletion_queue_vk.cc
diff --git a/impeller/renderer/backend/vulkan/BUILD.gn b/impeller/renderer/backend/vulkan/BUILD.gn
index 3ba6c17..dd1514a 100644
--- a/impeller/renderer/backend/vulkan/BUILD.gn
+++ b/impeller/renderer/backend/vulkan/BUILD.gn
@@ -8,6 +8,8 @@
sources = [
"allocator_vk.cc",
"allocator_vk.h",
+ "blit_command_vk.cc",
+ "blit_command_vk.h",
"blit_pass_vk.cc",
"blit_pass_vk.h",
"capabilities_vk.cc",
@@ -16,6 +18,8 @@
"command_buffer_vk.h",
"command_pool_vk.cc",
"command_pool_vk.h",
+ "commands_vk.cc",
+ "commands_vk.h",
"context_vk.cc",
"context_vk.h",
"deletion_queue_vk.cc",
diff --git a/impeller/renderer/backend/vulkan/blit_command_vk.cc b/impeller/renderer/backend/vulkan/blit_command_vk.cc
new file mode 100644
index 0000000..8a9dd4c
--- /dev/null
+++ b/impeller/renderer/backend/vulkan/blit_command_vk.cc
@@ -0,0 +1,182 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "impeller/renderer/backend/vulkan/blit_command_vk.h"
+
+#include "impeller/renderer/backend/vulkan/commands_vk.h"
+#include "impeller/renderer/backend/vulkan/texture_vk.h"
+
+namespace impeller {
+
+BlitEncodeVK::~BlitEncodeVK() = default;
+
+//------------------------------------------------------------------------------
+/// BlitCopyTextureToTextureCommandVK
+///
+
+BlitCopyTextureToTextureCommandVK::~BlitCopyTextureToTextureCommandVK() =
+ default;
+
+std::string BlitCopyTextureToTextureCommandVK::GetLabel() const {
+ return label;
+}
+
+[[nodiscard]] bool BlitCopyTextureToTextureCommandVK::Encode(
+ FencedCommandBufferVK* fenced_command_buffer) const {
+ // cast source and destination to TextureVK
+ const auto& source_tex_vk = TextureVK::Cast(*source);
+ const auto& dest_tex_vk = TextureVK::Cast(*destination);
+
+ // get the vulkan image and image view
+ const auto source_image = source_tex_vk.GetImage();
+ const auto dest_image = dest_tex_vk.GetImage();
+
+ // copy the source image to the destination image, from source_region to
+ // destination_origin.
+ vk::ImageCopy image_copy;
+ image_copy.setSrcSubresource(
+ vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
+ image_copy.setDstSubresource(
+ vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
+
+ image_copy.srcOffset =
+ vk::Offset3D(source_region.origin.x, source_region.origin.y, 0);
+ image_copy.dstOffset =
+ vk::Offset3D(destination_origin.x, destination_origin.y, 0);
+ image_copy.extent =
+ vk::Extent3D(source_region.size.width, source_region.size.height, 1);
+
+ // get single use command buffer
+ auto copy_cmd = fenced_command_buffer->GetSingleUseChild();
+
+ vk::CommandBufferBeginInfo begin_info;
+ begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
+ auto res = copy_cmd.begin(begin_info);
+
+ if (res != vk::Result::eSuccess) {
+ VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res);
+ return false;
+ }
+
+ // transition the source image to transfer source optimal
+ TransitionImageLayoutCommandVK transition_source_cmd =
+ TransitionImageLayoutCommandVK(source_image, vk::ImageLayout::eUndefined,
+ vk::ImageLayout::eTransferSrcOptimal);
+ bool success = transition_source_cmd.Submit(fenced_command_buffer);
+ if (!success) {
+ VALIDATION_LOG << "Failed to transition source image layout";
+ return false;
+ }
+
+ // transition the destination image to transfer destination optimal
+ TransitionImageLayoutCommandVK transition_dest_cmd =
+ TransitionImageLayoutCommandVK(dest_image, vk::ImageLayout::eUndefined,
+ vk::ImageLayout::eTransferDstOptimal);
+ success = transition_dest_cmd.Submit(fenced_command_buffer);
+ if (!success) {
+ VALIDATION_LOG << "Failed to transition destination image layout";
+ return false;
+ }
+
+ // issue the copy command
+ copy_cmd.copyImage(source_image, vk::ImageLayout::eTransferSrcOptimal,
+ dest_image, vk::ImageLayout::eTransferDstOptimal,
+ image_copy);
+ res = copy_cmd.end();
+ if (res != vk::Result::eSuccess) {
+ VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res);
+ return false;
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+/// BlitCopyTextureToBufferCommandVK
+///
+
+BlitCopyTextureToBufferCommandVK::~BlitCopyTextureToBufferCommandVK() = default;
+
+std::string BlitCopyTextureToBufferCommandVK::GetLabel() const {
+ return label;
+}
+
+[[nodiscard]] bool BlitCopyTextureToBufferCommandVK::Encode(
+ FencedCommandBufferVK* fenced_command_buffer) const {
+ // cast source and destination to TextureVK
+ const auto& source_tex_vk = TextureVK::Cast(*source);
+ const auto& dest_buf_vk = DeviceBufferVK::Cast(*destination);
+
+ // get the vulkan image and image view
+ const auto source_image = source_tex_vk.GetImage();
+
+ // get buffer image handle
+ const auto dest_buffer = dest_buf_vk.GetVKBufferHandle();
+
+ // copy the source image to the destination buffer, from source_region to
+ // destination_origin.
+ vk::BufferImageCopy image_copy{};
+ image_copy.setBufferOffset(destination_offset);
+ image_copy.setBufferRowLength(0);
+ image_copy.setBufferImageHeight(0);
+ image_copy.setImageSubresource(
+ vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1));
+ image_copy.setImageOffset(
+ vk::Offset3D(source_region.origin.x, source_region.origin.y, 0));
+ image_copy.setImageExtent(
+ vk::Extent3D(source_region.size.width, source_region.size.height, 1));
+
+ // transition the source image to transfer source optimal
+ TransitionImageLayoutCommandVK transition_source_cmd =
+ TransitionImageLayoutCommandVK(source_image, vk::ImageLayout::eUndefined,
+ vk::ImageLayout::eTransferSrcOptimal);
+ bool success = transition_source_cmd.Submit(fenced_command_buffer);
+ if (!success) {
+ return false;
+ }
+
+ // get single use command buffer
+ auto copy_cmd = fenced_command_buffer->GetSingleUseChild();
+
+ vk::CommandBufferBeginInfo begin_info;
+ begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
+ auto res = copy_cmd.begin(begin_info);
+
+ if (res != vk::Result::eSuccess) {
+ VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res);
+ return false;
+ }
+
+ // issue the copy command
+ copy_cmd.copyImageToBuffer(source_image, vk::ImageLayout::eTransferSrcOptimal,
+ dest_buffer, image_copy);
+ res = copy_cmd.end();
+ if (res != vk::Result::eSuccess) {
+ VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res);
+ }
+
+ return true;
+}
+
+//------------------------------------------------------------------------------
+/// BlitGenerateMipmapCommandVK
+///
+
+BlitGenerateMipmapCommandVK::~BlitGenerateMipmapCommandVK() = default;
+
+std::string BlitGenerateMipmapCommandVK::GetLabel() const {
+ return label;
+}
+
+[[nodiscard]] bool BlitGenerateMipmapCommandVK::Encode(
+ FencedCommandBufferVK* fenced_command_buffer) const {
+ // TODO(https://github.com/flutter/flutter/issues/120134): Support generating
+ // mipmaps on Vulkan.
+ IMPELLER_UNIMPLEMENTED;
+ return true;
+}
+
+// END: BlitGenerateMipmapCommandVK
+
+} // namespace impeller
diff --git a/impeller/renderer/backend/vulkan/blit_command_vk.h b/impeller/renderer/backend/vulkan/blit_command_vk.h
new file mode 100644
index 0000000..dda7f42
--- /dev/null
+++ b/impeller/renderer/backend/vulkan/blit_command_vk.h
@@ -0,0 +1,57 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include <memory>
+#include "impeller/base/backend_cast.h"
+#include "impeller/renderer/backend/vulkan/context_vk.h"
+#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h"
+#include "impeller/renderer/blit_command.h"
+#include "impeller/renderer/context.h"
+
+namespace impeller {
+
+/// Mixin for dispatching Vulkan commands.
+struct BlitEncodeVK : BackendCast<BlitEncodeVK, BlitCommand> {
+ virtual ~BlitEncodeVK();
+
+ virtual std::string GetLabel() const = 0;
+
+ [[nodiscard]] virtual bool Encode(
+ FencedCommandBufferVK* fenced_command_buffer) const = 0;
+};
+
+struct BlitCopyTextureToTextureCommandVK
+ : public BlitCopyTextureToTextureCommand,
+ public BlitEncodeVK {
+ ~BlitCopyTextureToTextureCommandVK() override;
+
+ std::string GetLabel() const override;
+
+ [[nodiscard]] bool Encode(
+ FencedCommandBufferVK* fenced_command_buffer) const override;
+};
+
+struct BlitCopyTextureToBufferCommandVK : public BlitCopyTextureToBufferCommand,
+ public BlitEncodeVK {
+ ~BlitCopyTextureToBufferCommandVK() override;
+
+ std::string GetLabel() const override;
+
+ [[nodiscard]] bool Encode(
+ FencedCommandBufferVK* fenced_command_buffer) const override;
+};
+
+struct BlitGenerateMipmapCommandVK : public BlitGenerateMipmapCommand,
+ public BlitEncodeVK {
+ ~BlitGenerateMipmapCommandVK() override;
+
+ std::string GetLabel() const override;
+
+ [[nodiscard]] bool Encode(
+ FencedCommandBufferVK* fenced_command_buffer) const override;
+};
+
+} // namespace impeller
diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.cc b/impeller/renderer/backend/vulkan/blit_pass_vk.cc
index 03f0510..bdbd591 100644
--- a/impeller/renderer/backend/vulkan/blit_pass_vk.cc
+++ b/impeller/renderer/backend/vulkan/blit_pass_vk.cc
@@ -4,8 +4,92 @@
#include "impeller/renderer/backend/vulkan/blit_pass_vk.h"
+#include "flutter/fml/logging.h"
+#include "flutter/fml/trace_event.h"
+
namespace impeller {
-//
+BlitPassVK::BlitPassVK(std::shared_ptr<FencedCommandBufferVK> command_buffer)
+ : command_buffer_(std::move(command_buffer)) {}
+
+BlitPassVK::~BlitPassVK() = default;
+
+void BlitPassVK::OnSetLabel(std::string label) {
+ if (label.empty()) {
+ return;
+ }
+ label_ = std::move(label);
+}
+
+// |BlitPass|
+bool BlitPassVK::IsValid() const {
+ return command_buffer_ != nullptr;
+}
+
+// |BlitPass|
+bool BlitPassVK::EncodeCommands(
+ const std::shared_ptr<Allocator>& transients_allocator) const {
+ TRACE_EVENT0("impeller", "BlitPassVK::EncodeCommands");
+
+ if (!IsValid()) {
+ return false;
+ }
+
+ for (auto& command : commands_) {
+ bool encode_res = command->Encode(command_buffer_.get());
+ if (!encode_res) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// |BlitPass|
+bool BlitPassVK::OnCopyTextureToTextureCommand(
+ std::shared_ptr<Texture> source,
+ std::shared_ptr<Texture> destination,
+ IRect source_region,
+ IPoint destination_origin,
+ std::string label) {
+ auto command = std::make_unique<BlitCopyTextureToTextureCommandVK>();
+ command->source = std::move(source);
+ command->destination = std::move(destination);
+ command->source_region = source_region;
+ command->destination_origin = destination_origin;
+ command->label = std::move(label);
+
+ commands_.push_back(std::move(command));
+ return true;
+}
+
+// |BlitPass|
+bool BlitPassVK::OnCopyTextureToBufferCommand(
+ std::shared_ptr<Texture> source,
+ std::shared_ptr<DeviceBuffer> destination,
+ IRect source_region,
+ size_t destination_offset,
+ std::string label) {
+ auto command = std::make_unique<BlitCopyTextureToBufferCommandVK>();
+ command->source = std::move(source);
+ command->destination = std::move(destination);
+ command->source_region = source_region;
+ command->destination_offset = destination_offset;
+ command->label = std::move(label);
+
+ commands_.push_back(std::move(command));
+ return true;
+}
+
+// |BlitPass|
+bool BlitPassVK::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
+ std::string label) {
+ auto command = std::make_unique<BlitGenerateMipmapCommandVK>();
+ command->texture = std::move(texture);
+ command->label = std::move(label);
+
+ commands_.push_back(std::move(command));
+ return true;
+}
} // namespace impeller
diff --git a/impeller/renderer/backend/vulkan/blit_pass_vk.h b/impeller/renderer/backend/vulkan/blit_pass_vk.h
index a76e5a7..aa8a391 100644
--- a/impeller/renderer/backend/vulkan/blit_pass_vk.h
+++ b/impeller/renderer/backend/vulkan/blit_pass_vk.h
@@ -5,19 +5,25 @@
#pragma once
#include "flutter/fml/macros.h"
+#include "impeller/renderer/backend/vulkan/blit_command_vk.h"
+#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h"
#include "impeller/renderer/blit_pass.h"
namespace impeller {
class BlitPassVK final : public BlitPass {
public:
+ explicit BlitPassVK(std::shared_ptr<FencedCommandBufferVK> command_buffer);
+
// |BlitPass|
~BlitPassVK() override;
private:
friend class CommandBufferVK;
- BlitPassVK();
+ std::shared_ptr<FencedCommandBufferVK> command_buffer_;
+ std::vector<std::unique_ptr<BlitEncodeVK>> commands_;
+ std::string label_;
// |BlitPass|
bool IsValid() const override;
diff --git a/impeller/renderer/backend/vulkan/command_buffer_vk.cc b/impeller/renderer/backend/vulkan/command_buffer_vk.cc
index 98f1e86..01fc6f3 100644
--- a/impeller/renderer/backend/vulkan/command_buffer_vk.cc
+++ b/impeller/renderer/backend/vulkan/command_buffer_vk.cc
@@ -9,6 +9,7 @@
#include "flutter/fml/logging.h"
#include "impeller/base/validation.h"
+#include "impeller/renderer/backend/vulkan/blit_pass_vk.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
@@ -120,7 +121,16 @@
std::shared_ptr<BlitPass> CommandBufferVK::OnCreateBlitPass() const {
// TODO(kaushikiska): https://github.com/flutter/flutter/issues/112649
- return nullptr;
+ if (!IsValid()) {
+ return nullptr;
+ }
+
+ auto pass = std::make_shared<BlitPassVK>(fenced_command_buffer_);
+ if (!pass->IsValid()) {
+ return nullptr;
+ }
+
+ return pass;
}
std::shared_ptr<ComputePass> CommandBufferVK::OnCreateComputePass() const {
diff --git a/impeller/renderer/backend/vulkan/commands_vk.cc b/impeller/renderer/backend/vulkan/commands_vk.cc
new file mode 100644
index 0000000..6eab778
--- /dev/null
+++ b/impeller/renderer/backend/vulkan/commands_vk.cc
@@ -0,0 +1,67 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "impeller/renderer/backend/vulkan/commands_vk.h"
+
+namespace impeller {
+
+TransitionImageLayoutCommandVK::TransitionImageLayoutCommandVK(
+ vk::Image image,
+ vk::ImageLayout old_layout,
+ vk::ImageLayout new_layout)
+ : image_(image), old_layout_(old_layout), new_layout_(new_layout) {}
+
+TransitionImageLayoutCommandVK::~TransitionImageLayoutCommandVK() = default;
+
+bool TransitionImageLayoutCommandVK::Submit(
+ FencedCommandBufferVK* command_buffer) {
+ if (!command_buffer) {
+ return false;
+ }
+
+ vk::ImageMemoryBarrier barrier =
+ vk::ImageMemoryBarrier()
+ .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentWrite |
+ vk::AccessFlagBits::eTransferWrite)
+ .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead |
+ vk::AccessFlagBits::eShaderRead)
+ .setOldLayout(old_layout_)
+ .setNewLayout(new_layout_)
+ .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
+ .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
+ .setImage(image_)
+ .setSubresourceRange(
+ vk::ImageSubresourceRange()
+ .setAspectMask(vk::ImageAspectFlagBits::eColor)
+ .setBaseMipLevel(0)
+ .setLevelCount(1)
+ .setBaseArrayLayer(0)
+ .setLayerCount(1));
+
+ vk::PipelineStageFlags src_stage = vk::PipelineStageFlagBits::eAllGraphics;
+ vk::PipelineStageFlags dst_stage = vk::PipelineStageFlagBits::eAllGraphics;
+
+ auto transition_cmd = command_buffer->GetSingleUseChild();
+
+ vk::CommandBufferBeginInfo begin_info;
+ begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
+ auto res = transition_cmd.begin(begin_info);
+
+ if (res != vk::Result::eSuccess) {
+ FML_LOG(ERROR) << "Failed to begin command buffer: " << vk::to_string(res);
+ return false;
+ }
+
+ transition_cmd.pipelineBarrier(src_stage, dst_stage, {}, nullptr, nullptr,
+ barrier);
+ res = transition_cmd.end();
+ if (res != vk::Result::eSuccess) {
+ FML_LOG(ERROR) << "Failed to end command buffer: " << vk::to_string(res);
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace impeller
diff --git a/impeller/renderer/backend/vulkan/commands_vk.h b/impeller/renderer/backend/vulkan/commands_vk.h
new file mode 100644
index 0000000..31c1c12
--- /dev/null
+++ b/impeller/renderer/backend/vulkan/commands_vk.h
@@ -0,0 +1,31 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#pragma once
+
+#include "impeller/renderer/backend/vulkan/context_vk.h"
+#include "impeller/renderer/backend/vulkan/fenced_command_buffer_vk.h"
+
+// Set of common utility commands for Vulkan.
+namespace impeller {
+
+class TransitionImageLayoutCommandVK {
+ public:
+ TransitionImageLayoutCommandVK(vk::Image image,
+ vk::ImageLayout old_layout,
+ vk::ImageLayout new_layout);
+
+ ~TransitionImageLayoutCommandVK();
+
+ bool Submit(FencedCommandBufferVK* command_buffer);
+
+ private:
+ vk::Image image_;
+ vk::ImageLayout old_layout_;
+ vk::ImageLayout new_layout_;
+
+ FML_DISALLOW_COPY_AND_ASSIGN(TransitionImageLayoutCommandVK);
+};
+
+} // namespace impeller
diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc
index 5c3e398..720ecf9 100644
--- a/impeller/renderer/backend/vulkan/render_pass_vk.cc
+++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc
@@ -9,6 +9,7 @@
#include "fml/logging.h"
#include "impeller/base/validation.h"
+#include "impeller/renderer/backend/vulkan/commands_vk.h"
#include "impeller/renderer/backend/vulkan/context_vk.h"
#include "impeller/renderer/backend/vulkan/device_buffer_vk.h"
#include "impeller/renderer/backend/vulkan/formats_vk.h"
@@ -394,46 +395,9 @@
bool RenderPassVK::TransitionImageLayout(vk::Image image,
vk::ImageLayout layout_old,
vk::ImageLayout layout_new) const {
- auto transition_cmd = command_buffer_->GetSingleUseChild();
-
- vk::CommandBufferBeginInfo begin_info;
- begin_info.setFlags(vk::CommandBufferUsageFlagBits::eOneTimeSubmit);
- auto res = transition_cmd.begin(begin_info);
-
- if (res != vk::Result::eSuccess) {
- VALIDATION_LOG << "Failed to begin command buffer: " << vk::to_string(res);
- return false;
- }
-
- vk::ImageMemoryBarrier barrier =
- vk::ImageMemoryBarrier()
- .setSrcAccessMask(vk::AccessFlagBits::eColorAttachmentWrite |
- vk::AccessFlagBits::eTransferWrite)
- .setDstAccessMask(vk::AccessFlagBits::eColorAttachmentRead |
- vk::AccessFlagBits::eShaderRead)
- .setOldLayout(layout_old)
- .setNewLayout(layout_new)
- .setSrcQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
- .setDstQueueFamilyIndex(VK_QUEUE_FAMILY_IGNORED)
- .setImage(image)
- .setSubresourceRange(
- vk::ImageSubresourceRange()
- .setAspectMask(vk::ImageAspectFlagBits::eColor)
- .setBaseMipLevel(0)
- .setLevelCount(1)
- .setBaseArrayLayer(0)
- .setLayerCount(1));
- transition_cmd.pipelineBarrier(vk::PipelineStageFlagBits::eAllGraphics,
- vk::PipelineStageFlagBits::eAllGraphics, {},
- nullptr, nullptr, barrier);
-
- res = transition_cmd.end();
- if (res != vk::Result::eSuccess) {
- VALIDATION_LOG << "Failed to end command buffer: " << vk::to_string(res);
- return false;
- }
-
- return true;
+ auto transition_cmd =
+ TransitionImageLayoutCommandVK(image, layout_old, layout_new);
+ return transition_cmd.Submit(command_buffer_.get());
}
bool RenderPassVK::CopyBufferToImage(const TextureVK& texture_vk) const {