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

[Impeller] Add blit command to copy texture to buffer #37198

Merged
merged 6 commits into from
Nov 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
39 changes: 39 additions & 0 deletions impeller/renderer/backend/gles/blit_command_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "flutter/fml/closure.h"
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/gles/device_buffer_gles.h"
#include "impeller/renderer/backend/gles/texture_gles.h"

namespace impeller {
Expand Down Expand Up @@ -116,6 +117,44 @@ bool BlitCopyTextureToTextureCommandGLES::Encode(
return true;
};

BlitCopyTextureToBufferCommandGLES::~BlitCopyTextureToBufferCommandGLES() =
default;

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

bool BlitCopyTextureToBufferCommandGLES::Encode(
const ReactorGLES& reactor) const {
if (source->GetTextureDescriptor().format != PixelFormat::kR8G8B8A8UNormInt) {
VALIDATION_LOG << "Only textures with pixel format RGBA are supported yet.";
return false;
}

const auto& gl = reactor.GetProcTable();

GLuint read_fbo = GL_NONE;
fml::ScopedCleanupClosure delete_fbos(
[&gl, &read_fbo]() { DeleteFBO(gl, read_fbo, GL_READ_FRAMEBUFFER); });

{
auto read = ConfigureFBO(gl, source, GL_READ_FRAMEBUFFER);
if (!read.has_value()) {
return false;
}
read_fbo = read.value();
}

DeviceBufferGLES::Cast(*destination)
.UpdateBufferData([&gl, this](uint8_t* data, size_t length) {
gl.ReadPixels(source_region.origin.x, source_region.origin.y,
source_region.size.width, source_region.size.height,
GL_RGBA, GL_UNSIGNED_BYTE, data + destination_offset);
});

return true;
};

BlitGenerateMipmapCommandGLES::~BlitGenerateMipmapCommandGLES() = default;

std::string BlitGenerateMipmapCommandGLES::GetLabel() const {
Expand Down
10 changes: 10 additions & 0 deletions impeller/renderer/backend/gles/blit_command_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ struct BlitCopyTextureToTextureCommandGLES
[[nodiscard]] bool Encode(const ReactorGLES& reactor) const override;
};

struct BlitCopyTextureToBufferCommandGLES
: public BlitEncodeGLES,
public BlitCopyTextureToBufferCommand {
~BlitCopyTextureToBufferCommandGLES() override;

std::string GetLabel() const override;

[[nodiscard]] bool Encode(const ReactorGLES& reactor) const override;
};

struct BlitGenerateMipmapCommandGLES : public BlitEncodeGLES,
public BlitGenerateMipmapCommand {
~BlitGenerateMipmapCommandGLES() override;
Expand Down
24 changes: 22 additions & 2 deletions impeller/renderer/backend/gles/blit_pass_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ bool BlitPassGLES::EncodeCommands(
}

// |BlitPass|
void BlitPassGLES::OnCopyTextureToTextureCommand(
bool BlitPassGLES::OnCopyTextureToTextureCommand(
std::shared_ptr<Texture> source,
std::shared_ptr<Texture> destination,
IRect source_region,
Expand All @@ -109,16 +109,36 @@ void BlitPassGLES::OnCopyTextureToTextureCommand(
command->destination_origin = destination_origin;

commands_.emplace_back(std::move(command));
return true;
}

// |BlitPass|
void BlitPassGLES::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
bool BlitPassGLES::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<BlitCopyTextureToBufferCommandGLES>();
command->label = label;
command->source = std::move(source);
command->destination = std::move(destination);
command->source_region = source_region;
command->destination_offset = destination_offset;

commands_.emplace_back(std::move(command));
return true;
}

// |BlitPass|
bool BlitPassGLES::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
std::string label) {
auto command = std::make_unique<BlitGenerateMipmapCommandGLES>();
command->label = label;
command->texture = std::move(texture);

commands_.emplace_back(std::move(command));
return true;
}

} // namespace impeller
11 changes: 9 additions & 2 deletions impeller/renderer/backend/gles/blit_pass_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,21 @@ class BlitPassGLES final : public BlitPass {
const std::shared_ptr<Allocator>& transients_allocator) const override;

// |BlitPass|
void OnCopyTextureToTextureCommand(std::shared_ptr<Texture> source,
bool OnCopyTextureToTextureCommand(std::shared_ptr<Texture> source,
std::shared_ptr<Texture> destination,
IRect source_region,
IPoint destination_origin,
std::string label) override;

// |BlitPass|
void OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
bool OnCopyTextureToBufferCommand(std::shared_ptr<Texture> source,
std::shared_ptr<DeviceBuffer> destination,
IRect source_region,
size_t destination_offset,
std::string label) override;

// |BlitPass|
bool OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
std::string label) override;

FML_DISALLOW_COPY_AND_ASSIGN(BlitPassGLES);
Expand Down
11 changes: 11 additions & 0 deletions impeller/renderer/backend/gles/device_buffer_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,15 @@ bool DeviceBufferGLES::SetLabel(const std::string& label, Range range) {
const uint8_t* DeviceBufferGLES::GetBufferData() const {
return backing_store_->GetBuffer();
}

void DeviceBufferGLES::UpdateBufferData(
const std::function<void(uint8_t* data, size_t length)>&
update_buffer_data) {
if (update_buffer_data) {
update_buffer_data(backing_store_->GetBuffer(),
backing_store_->GetLength());
++generation_;
}
}

} // namespace impeller
3 changes: 3 additions & 0 deletions impeller/renderer/backend/gles/device_buffer_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ class DeviceBufferGLES final

const uint8_t* GetBufferData() const;

void UpdateBufferData(
const std::function<void(uint8_t*, size_t length)>& update_buffer_data);

enum class BindingType {
kArrayBuffer,
kElementArrayBuffer,
Expand Down
3 changes: 2 additions & 1 deletion impeller/renderer/backend/gles/proc_table_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,8 @@ struct GLProc {
PROC(UniformMatrix4fv); \
PROC(UseProgram); \
PROC(VertexAttribPointer); \
PROC(Viewport);
PROC(Viewport); \
PROC(ReadPixels);

#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) PROC(BlitFramebuffer);

Expand Down
10 changes: 10 additions & 0 deletions impeller/renderer/backend/metal/blit_command_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@ struct BlitCopyTextureToTextureCommandMTL
[[nodiscard]] bool Encode(id<MTLBlitCommandEncoder> encoder) const override;
};

struct BlitCopyTextureToBufferCommandMTL
: public BlitCopyTextureToBufferCommand,
public BlitEncodeMTL {
~BlitCopyTextureToBufferCommandMTL() override;

std::string GetLabel() const override;

[[nodiscard]] bool Encode(id<MTLBlitCommandEncoder> encoder) const override;
};

struct BlitGenerateMipmapCommandMTL : public BlitGenerateMipmapCommand,
public BlitEncodeMTL {
~BlitGenerateMipmapCommandMTL() override;
Expand Down
45 changes: 45 additions & 0 deletions impeller/renderer/backend/metal/blit_command_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "impeller/renderer/backend/metal/blit_command_mtl.h"

#include "impeller/renderer/backend/metal/device_buffer_mtl.h"
#include "impeller/renderer/backend/metal/texture_mtl.h"

namespace impeller {
Expand Down Expand Up @@ -49,6 +50,50 @@
return true;
};

BlitCopyTextureToBufferCommandMTL::~BlitCopyTextureToBufferCommandMTL() =
default;

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

bool BlitCopyTextureToBufferCommandMTL::Encode(
id<MTLBlitCommandEncoder> encoder) const {
auto source_mtl = TextureMTL::Cast(*source).GetMTLTexture();
if (!source_mtl) {
return false;
}

auto destination_mtl = DeviceBufferMTL::Cast(*destination).GetMTLBuffer();
if (!destination_mtl) {
return false;
}

auto source_origin_mtl =
MTLOriginMake(source_region.origin.x, source_region.origin.y, 0);
auto source_size_mtl =
MTLSizeMake(source_region.size.width, source_region.size.height, 1);

auto destination_bytes_per_pixel =
BytesPerPixelForPixelFormat(source->GetTextureDescriptor().format);
auto destination_bytes_per_row =
source_size_mtl.width * destination_bytes_per_pixel;
auto destination_bytes_per_image =
source_size_mtl.height * destination_bytes_per_row;

[encoder copyFromTexture:source_mtl
sourceSlice:0
sourceLevel:0
sourceOrigin:source_origin_mtl
sourceSize:source_size_mtl
toBuffer:destination_mtl
destinationOffset:destination_offset
destinationBytesPerRow:destination_bytes_per_row
destinationBytesPerImage:destination_bytes_per_image];

return true;
};

BlitGenerateMipmapCommandMTL::~BlitGenerateMipmapCommandMTL() = default;

std::string BlitGenerateMipmapCommandMTL::GetLabel() const {
Expand Down
11 changes: 9 additions & 2 deletions impeller/renderer/backend/metal/blit_pass_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,21 @@ class BlitPassMTL final : public BlitPass {
bool EncodeCommands(id<MTLBlitCommandEncoder> pass) const;

// |BlitPass|
void OnCopyTextureToTextureCommand(std::shared_ptr<Texture> source,
bool OnCopyTextureToTextureCommand(std::shared_ptr<Texture> source,
std::shared_ptr<Texture> destination,
IRect source_region,
IPoint destination_origin,
std::string label) override;

// |BlitPass|
void OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
bool OnCopyTextureToBufferCommand(std::shared_ptr<Texture> source,
std::shared_ptr<DeviceBuffer> destination,
IRect source_region,
size_t destination_offset,
std::string label) override;

// |BlitPass|
bool OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
std::string label) override;

FML_DISALLOW_COPY_AND_ASSIGN(BlitPassMTL);
Expand Down
24 changes: 22 additions & 2 deletions impeller/renderer/backend/metal/blit_pass_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@
}

// |BlitPass|
void BlitPassMTL::OnCopyTextureToTextureCommand(
bool BlitPassMTL::OnCopyTextureToTextureCommand(
std::shared_ptr<Texture> source,
std::shared_ptr<Texture> destination,
IRect source_region,
Expand All @@ -102,16 +102,36 @@
command->destination_origin = destination_origin;

commands_.emplace_back(std::move(command));
return true;
}

// |BlitPass|
void BlitPassMTL::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
bool BlitPassMTL::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<BlitCopyTextureToBufferCommandMTL>();
command->label = label;
command->source = std::move(source);
command->destination = std::move(destination);
command->source_region = source_region;
command->destination_offset = destination_offset;

commands_.emplace_back(std::move(command));
return true;
}

// |BlitPass|
bool BlitPassMTL::OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
std::string label) {
auto command = std::make_unique<BlitGenerateMipmapCommandMTL>();
command->label = label;
command->texture = std::move(texture);

commands_.emplace_back(std::move(command));
return true;
}

} // namespace impeller
11 changes: 9 additions & 2 deletions impeller/renderer/backend/vulkan/blit_pass_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,21 @@ class BlitPassVK final : public BlitPass {
const std::shared_ptr<Allocator>& transients_allocator) const override;

// |BlitPass|
void OnCopyTextureToTextureCommand(std::shared_ptr<Texture> source,
bool OnCopyTextureToTextureCommand(std::shared_ptr<Texture> source,
std::shared_ptr<Texture> destination,
IRect source_region,
IPoint destination_origin,
std::string label) override;

// |BlitPass|
void OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
bool OnCopyTextureToBufferCommand(std::shared_ptr<Texture> source,
std::shared_ptr<DeviceBuffer> destination,
IRect source_region,
size_t destination_offset,
std::string label) override;

// |BlitPass|
bool OnGenerateMipmapCommand(std::shared_ptr<Texture> texture,
std::string label) override;

FML_DISALLOW_COPY_AND_ASSIGN(BlitPassVK);
Expand Down
9 changes: 9 additions & 0 deletions impeller/renderer/blit_command.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#pragma once

#include "impeller/geometry/rect.h"
#include "impeller/renderer/device_buffer.h"
#include "impeller/renderer/texture.h"

namespace impeller {
Expand All @@ -19,6 +21,13 @@ struct BlitCopyTextureToTextureCommand : public BlitCommand {
IPoint destination_origin;
};

struct BlitCopyTextureToBufferCommand : public BlitCommand {
std::shared_ptr<Texture> source;
std::shared_ptr<DeviceBuffer> destination;
IRect source_region;
size_t destination_offset;
};

struct BlitGenerateMipmapCommand : public BlitCommand {
std::shared_ptr<Texture> texture;
};
Expand Down
Loading