Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion impeller/playground/playground.cc
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ static std::shared_ptr<Texture> CreateTextureForDecompressedImage(
DecompressedImage& decompressed_image,
bool enable_mipmapping) {
// TODO(https://github.com/flutter/flutter/issues/123468): copying buffers to
// textures is not implemented for GLES/Vulkan.
// textures is not implemented for GLES.
if (context->GetCapabilities()->SupportsBufferToTextureBlits()) {
impeller::TextureDescriptor texture_descriptor;
texture_descriptor.storage_mode = impeller::StorageMode::kDevicePrivate;
Expand Down
59 changes: 59 additions & 0 deletions impeller/renderer/backend/vulkan/blit_command_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,65 @@ bool BlitCopyTextureToBufferCommandVK::Encode(CommandEncoderVK& encoder) const {
return true;
}

//------------------------------------------------------------------------------
/// BlitCopyBufferToTextureCommandVK
///

BlitCopyBufferToTextureCommandVK::~BlitCopyBufferToTextureCommandVK() = default;

std::string BlitCopyBufferToTextureCommandVK::GetLabel() const {
return label;
}

bool BlitCopyBufferToTextureCommandVK::Encode(CommandEncoderVK& encoder) const {
const auto& cmd_buffer = encoder.GetCommandBuffer();

// cast destination to TextureVK
const auto& dst = TextureVK::Cast(*destination);
const auto& src = DeviceBufferVK::Cast(*source.buffer);

if (!encoder.Track(source.buffer) || !encoder.Track(destination)) {
return false;
}

LayoutTransition transition;
transition.cmd_buffer = cmd_buffer;
transition.new_layout = vk::ImageLayout::eTransferSrcOptimal;
transition.src_access = vk::AccessFlagBits::eShaderWrite |
vk::AccessFlagBits::eTransferWrite |
vk::AccessFlagBits::eColorAttachmentWrite;
transition.src_stage = vk::PipelineStageFlagBits::eFragmentShader |
vk::PipelineStageFlagBits::eTransfer |
vk::PipelineStageFlagBits::eColorAttachmentOutput;
transition.dst_access = vk::AccessFlagBits::eShaderRead;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The mnemonic I use for transitions is "For this resource, all the commands before this may continue to src_access in src_stage and no commands after this proceed past dst_access in dst_stage.". I believe the src accesses here are right. You are waiting for any commands before this blit that write, transfer, specify this resource as color attachment as to finish. But, you are going to be using this as a blit source (I believe these are "transfers" in Vulkan parlance). So commands that read or transfer from it must wait.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, poop. Sorry, its the other way round. What I said was TextureToBuffer.

transition.dst_stage = vk::PipelineStageFlagBits::eVertexShader |
vk::PipelineStageFlagBits::eFragmentShader;

vk::BufferImageCopy image_copy;
image_copy.setBufferOffset(source.range.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(destination_origin.x, destination_origin.y, 0));
image_copy.setImageExtent(vk::Extent3D(destination->GetSize().width,
destination->GetSize().height, 1));

if (!dst.SetLayout(transition)) {
VALIDATION_LOG << "Could not encode layout transition.";
return false;
}

cmd_buffer.copyBufferToImage(src.GetBuffer(), //
dst.GetImage(), //
transition.new_layout, //
image_copy //
);

return true;
}

//------------------------------------------------------------------------------
/// BlitGenerateMipmapCommandVK
///
Expand Down
9 changes: 9 additions & 0 deletions impeller/renderer/backend/vulkan/blit_command_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ struct BlitCopyTextureToBufferCommandVK : public BlitCopyTextureToBufferCommand,
[[nodiscard]] bool Encode(CommandEncoderVK& encoder) const override;
};

struct BlitCopyBufferToTextureCommandVK : public BlitCopyBufferToTextureCommand,
public BlitEncodeVK {
~BlitCopyBufferToTextureCommandVK() override;

std::string GetLabel() const override;

[[nodiscard]] bool Encode(CommandEncoderVK& encoder) const override;
};

struct BlitGenerateMipmapCommandVK : public BlitGenerateMipmapCommand,
public BlitEncodeVK {
~BlitGenerateMipmapCommandVK() override;
Expand Down
20 changes: 20 additions & 0 deletions impeller/renderer/backend/vulkan/blit_command_vk_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,26 @@ TEST(BlitCommandVkTest, BlitCopyTextureToBufferCommandVK) {
EXPECT_TRUE(encoder.IsTracking(cmd.destination));
}

TEST(BlitCommandVkTest, BlitCopyBufferToTextureCommandVK) {
auto context = CreateMockVulkanContext();
auto pool = CommandPoolVK::GetThreadLocal(context.get());
CommandEncoderVK encoder(context->GetDevice(), context->GetGraphicsQueue(),
pool, context->GetFenceWaiter());
BlitCopyBufferToTextureCommandVK cmd;
cmd.destination = context->GetResourceAllocator()->CreateTexture({
.size = ISize(100, 100),
});
cmd.source = context->GetResourceAllocator()
->CreateBuffer({
.size = 1,
})
->AsBufferView();
bool result = cmd.Encode(encoder);
EXPECT_TRUE(result);
EXPECT_TRUE(encoder.IsTracking(cmd.source.buffer));
EXPECT_TRUE(encoder.IsTracking(cmd.destination));
}

TEST(BlitCommandVkTest, BlitGenerateMipmapCommandVK) {
auto context = CreateMockVulkanContext();
auto pool = CommandPoolVK::GetThreadLocal(context.get());
Expand Down
17 changes: 17 additions & 0 deletions impeller/renderer/backend/vulkan/blit_pass_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,23 @@ bool BlitPassVK::OnCopyTextureToBufferCommand(
return true;
}

// |BlitPass|
bool BlitPassVK::OnCopyBufferToTextureCommand(
BufferView source,
std::shared_ptr<Texture> destination,
IPoint destination_origin,
std::string label) {
auto command = std::make_unique<BlitCopyBufferToTextureCommandVK>();

command->source = std::move(source);
command->destination = std::move(destination);
command->destination_origin = destination_origin;
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) {
Expand Down
6 changes: 1 addition & 5 deletions impeller/renderer/backend/vulkan/blit_pass_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,7 @@ class BlitPassVK final : public BlitPass {
bool OnCopyBufferToTextureCommand(BufferView source,
std::shared_ptr<Texture> destination,
IPoint destination_origin,
std::string label) override {
IMPELLER_UNIMPLEMENTED;
return false;
}

std::string label) override;
// |BlitPass|
bool OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
std::string label) override;
Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/vulkan/capabilities_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ bool CapabilitiesVK::SupportsSSBO() const {

// |Capabilities|
bool CapabilitiesVK::SupportsBufferToTextureBlits() const {
return false;
return true;
}

// |Capabilities|
Expand Down
10 changes: 5 additions & 5 deletions impeller/renderer/backend/vulkan/command_encoder_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,14 @@ class TrackedObjectsVK {
tracked_objects_.insert(std::move(object));
}

void Track(std::shared_ptr<const DeviceBuffer> buffer) {
void Track(std::shared_ptr<const Buffer> buffer) {
if (!buffer) {
return;
}
tracked_buffers_.insert(std::move(buffer));
}

bool IsTracking(const std::shared_ptr<const DeviceBuffer>& buffer) const {
bool IsTracking(const std::shared_ptr<const Buffer>& buffer) const {
if (!buffer) {
return false;
}
Expand Down Expand Up @@ -88,7 +88,7 @@ class TrackedObjectsVK {
std::weak_ptr<CommandPoolVK> pool_;
vk::UniqueCommandBuffer buffer_;
std::set<std::shared_ptr<SharedObjectVK>> tracked_objects_;
std::set<std::shared_ptr<const DeviceBuffer>> tracked_buffers_;
std::set<std::shared_ptr<const Buffer>> tracked_buffers_;
std::set<std::shared_ptr<const TextureSourceVK>> tracked_textures_;
bool is_valid_ = false;

Expand Down Expand Up @@ -178,7 +178,7 @@ bool CommandEncoderVK::Track(std::shared_ptr<SharedObjectVK> object) {
return true;
}

bool CommandEncoderVK::Track(std::shared_ptr<const DeviceBuffer> buffer) {
bool CommandEncoderVK::Track(std::shared_ptr<const Buffer> buffer) {
if (!IsValid()) {
return false;
}
Expand All @@ -187,7 +187,7 @@ bool CommandEncoderVK::Track(std::shared_ptr<const DeviceBuffer> buffer) {
}

bool CommandEncoderVK::IsTracking(
const std::shared_ptr<const DeviceBuffer>& buffer) const {
const std::shared_ptr<const Buffer>& buffer) const {
if (!IsValid()) {
return false;
}
Expand Down
8 changes: 6 additions & 2 deletions impeller/renderer/backend/vulkan/command_encoder_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ namespace impeller {
namespace testing {
class BlitCommandVkTest_BlitCopyTextureToTextureCommandVK_Test;
class BlitCommandVkTest_BlitCopyTextureToBufferCommandVK_Test;
class BlitCommandVkTest_BlitCopyBufferToTextureCommandVK_Test;
class BlitCommandVkTest_BlitGenerateMipmapCommandVK_Test;
} // namespace testing

class ContextVK;
class DeviceBuffer;
class Buffer;
class Texture;
class TextureSourceVK;
class TrackedObjectsVK;
Expand All @@ -39,9 +41,9 @@ class CommandEncoderVK {

bool Track(std::shared_ptr<SharedObjectVK> object);

bool Track(std::shared_ptr<const DeviceBuffer> buffer);
bool Track(std::shared_ptr<const Buffer> buffer);

bool IsTracking(const std::shared_ptr<const DeviceBuffer>& texture) const;
bool IsTracking(const std::shared_ptr<const Buffer>& texture) const;

bool Track(const std::shared_ptr<const Texture>& texture);

Expand All @@ -68,6 +70,8 @@ class CommandEncoderVK {
BlitCommandVkTest_BlitCopyTextureToBufferCommandVK_Test;
friend class ::impeller::testing::
BlitCommandVkTest_BlitGenerateMipmapCommandVK_Test;
friend class ::impeller::testing::
BlitCommandVkTest_BlitCopyBufferToTextureCommandVK_Test;

vk::Device device_ = {};
std::shared_ptr<QueueVK> queue_;
Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/backend/vulkan/device_buffer_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
namespace impeller {

class DeviceBufferVK final : public DeviceBuffer,
public BackendCast<DeviceBufferVK, DeviceBuffer> {
public BackendCast<DeviceBufferVK, Buffer> {
public:
DeviceBufferVK(DeviceBufferDescriptor desc,
std::weak_ptr<Context> context,
Expand Down