Skip to content

Commit

Permalink
[Impeller] Support blit passes on Vulkan. (flutter#39438)
Browse files Browse the repository at this point in the history
  • Loading branch information
iskakaushik authored Feb 9, 2023
1 parent e50569b commit 9a40a38
Show file tree
Hide file tree
Showing 10 changed files with 456 additions and 43 deletions.
8 changes: 8 additions & 0 deletions ci/licenses_golden/licenses_flutter
Original file line number Diff line number Diff line change
Expand Up @@ -1506,6 +1506,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h
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
Expand All @@ -1514,6 +1516,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc +
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
Expand Down Expand Up @@ -3987,6 +3991,8 @@ FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h
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
Expand All @@ -3995,6 +4001,8 @@ FILE: ../../../flutter/impeller/renderer/backend/vulkan/command_buffer_vk.cc
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
Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/backend/vulkan/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ impeller_component("vulkan") {
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",
Expand All @@ -16,6 +18,8 @@ impeller_component("vulkan") {
"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",
Expand Down
182 changes: 182 additions & 0 deletions impeller/renderer/backend/vulkan/blit_command_vk.cc
Original file line number Diff line number Diff line change
@@ -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
57 changes: 57 additions & 0 deletions impeller/renderer/backend/vulkan/blit_command_vk.h
Original file line number Diff line number Diff line change
@@ -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
86 changes: 85 additions & 1 deletion impeller/renderer/backend/vulkan/blit_pass_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Loading

0 comments on commit 9a40a38

Please sign in to comment.