Skip to content

Commit

Permalink
[Impeller] Make kHostVisible DeviceBuffers actually be host visible. (f…
Browse files Browse the repository at this point in the history
  • Loading branch information
dnfield authored Sep 30, 2022
1 parent 9e42e3a commit f7000ed
Show file tree
Hide file tree
Showing 15 changed files with 133 additions and 1 deletion.
4 changes: 4 additions & 0 deletions impeller/renderer/allocator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,8 @@ std::shared_ptr<Texture> Allocator::CreateTexture(
return OnCreateTexture(desc);
}

uint16_t Allocator::MinimumBytesPerRow(PixelFormat format) const {
return BytesPerPixelForPixelFormat(format);
}

} // namespace impeller
6 changes: 6 additions & 0 deletions impeller/renderer/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ class Allocator {

std::shared_ptr<Texture> CreateTexture(const TextureDescriptor& desc);

//------------------------------------------------------------------------------
/// @brief Minimum value for `row_bytes` on a Texture. The row
/// bytes parameter of that method must be aligned to this value.
///
virtual uint16_t MinimumBytesPerRow(PixelFormat format) const;

std::shared_ptr<DeviceBuffer> CreateBufferWithCopy(const uint8_t* buffer,
size_t length);

Expand Down
8 changes: 8 additions & 0 deletions impeller/renderer/backend/gles/device_buffer_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,14 @@ DeviceBufferGLES::~DeviceBufferGLES() {
}
}

// |DeviceBuffer|
uint8_t* DeviceBufferGLES::OnGetContents() const {
if (!reactor_) {
return nullptr;
}
return backing_store_->GetBuffer();
}

// |DeviceBuffer|
bool DeviceBufferGLES::OnCopyHostBuffer(const uint8_t* source,
Range source_range,
Expand Down
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 @@ -41,6 +41,9 @@ class DeviceBufferGLES final
mutable uint32_t generation_ = 0;
mutable uint32_t upload_generation_ = 0;

// |DeviceBuffer|
uint8_t* OnGetContents() const override;

// |DeviceBuffer|
bool OnCopyHostBuffer(const uint8_t* source,
Range source_range,
Expand Down
3 changes: 3 additions & 0 deletions impeller/renderer/backend/metal/allocator_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ class AllocatorMTL final : public Allocator {
std::shared_ptr<Texture> OnCreateTexture(
const TextureDescriptor& desc) override;

// |Allocator|
uint16_t MinimumBytesPerRow(PixelFormat format) const override;

// |Allocator|
ISize GetMaxTextureSizeSupported() const override;

Expand Down
5 changes: 5 additions & 0 deletions impeller/renderer/backend/metal/allocator_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,11 @@ static MTLStorageMode ToMTLStorageMode(StorageMode mode,
return std::make_shared<TextureMTL>(desc, texture);
}

uint16_t AllocatorMTL::MinimumBytesPerRow(PixelFormat format) const {
return static_cast<uint16_t>([device_
minimumLinearTextureAlignmentForPixelFormat:ToMTLPixelFormat(format)]);
}

ISize AllocatorMTL::GetMaxTextureSizeSupported() const {
return max_texture_supported_;
}
Expand Down
8 changes: 8 additions & 0 deletions impeller/renderer/backend/metal/device_buffer_mtl.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,14 @@ class DeviceBufferMTL final
id<MTLBuffer> buffer,
MTLStorageMode storage_mode);

// |DeviceBuffer|
uint8_t* OnGetContents() const override;

// |DeviceBuffer|
std::shared_ptr<Texture> AsTexture(Allocator& allocator,
const TextureDescriptor& descriptor,
uint16_t row_bytes) const override;

// |DeviceBuffer|
bool OnCopyHostBuffer(const uint8_t* source,
Range source_range,
Expand Down
27 changes: 27 additions & 0 deletions impeller/renderer/backend/metal/device_buffer_mtl.mm
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,33 @@
return buffer_;
}

uint8_t* DeviceBufferMTL::OnGetContents() const {
if (storage_mode_ != MTLStorageModeShared) {
return nullptr;
}
return reinterpret_cast<uint8_t*>(buffer_.contents);
}

std::shared_ptr<Texture> DeviceBufferMTL::AsTexture(
Allocator& allocator,
const TextureDescriptor& descriptor,
uint16_t row_bytes) const {
auto mtl_texture_desc = ToMTLTextureDescriptor(descriptor);

if (!mtl_texture_desc) {
VALIDATION_LOG << "Texture descriptor was invalid.";
return nullptr;
}

auto texture = [buffer_ newTextureWithDescriptor:mtl_texture_desc
offset:0
bytesPerRow:row_bytes];
if (!texture) {
return nullptr;
}
return std::make_shared<TextureMTL>(descriptor, texture);
}

[[nodiscard]] bool DeviceBufferMTL::OnCopyHostBuffer(const uint8_t* source,
Range source_range,
size_t offset) {
Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/backend/vulkan/device_buffer_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ DeviceBufferVK::DeviceBufferVK(

DeviceBufferVK::~DeviceBufferVK() = default;

uint8_t* DeviceBufferVK::OnGetContents() const {
return reinterpret_cast<uint8_t*>(device_allocation_->GetMapping());
}

bool DeviceBufferVK::OnCopyHostBuffer(const uint8_t* source,
Range source_range,
size_t offset) {
Expand Down
3 changes: 3 additions & 0 deletions impeller/renderer/backend/vulkan/device_buffer_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ class DeviceBufferVK final : public DeviceBuffer,
ContextVK& context_;
std::unique_ptr<DeviceBufferAllocationVK> device_allocation_;

// |DeviceBuffer|
uint8_t* OnGetContents() const override;

// |DeviceBuffer|
bool OnCopyHostBuffer(const uint8_t* source,
Range source_range,
Expand Down
1 change: 1 addition & 0 deletions impeller/renderer/buffer_view.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ namespace impeller {

struct BufferView {
std::shared_ptr<const Buffer> buffer;
uint8_t* contents;
Range range;

constexpr operator bool() const { return static_cast<bool>(buffer); }
Expand Down
16 changes: 16 additions & 0 deletions impeller/renderer/device_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,26 @@ std::shared_ptr<const DeviceBuffer> DeviceBuffer::GetDeviceBuffer(
BufferView DeviceBuffer::AsBufferView() const {
BufferView view;
view.buffer = shared_from_this();
view.contents = OnGetContents();
view.range = {0u, desc_.size};
return view;
}

std::shared_ptr<Texture> DeviceBuffer::AsTexture(
Allocator& allocator,
const TextureDescriptor& descriptor,
uint16_t row_bytes) const {
auto texture = allocator.CreateTexture(descriptor);
if (!texture) {
return nullptr;
}
if (!texture->SetContents(std::make_shared<fml::NonOwnedMapping>(
OnGetContents(), desc_.size))) {
return nullptr;
}
return texture;
}

[[nodiscard]] bool DeviceBuffer::CopyHostBuffer(const uint8_t* source,
Range source_range,
size_t offset) {
Expand Down
7 changes: 7 additions & 0 deletions impeller/renderer/device_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ class DeviceBuffer : public Buffer,

BufferView AsBufferView() const;

virtual std::shared_ptr<Texture> AsTexture(
Allocator& allocator,
const TextureDescriptor& descriptor,
uint16_t row_bytes) const;

// |Buffer|
std::shared_ptr<const DeviceBuffer> GetDeviceBuffer(
Allocator& allocator) const;
Expand All @@ -41,6 +46,8 @@ class DeviceBuffer : public Buffer,

explicit DeviceBuffer(DeviceBufferDescriptor desc);

virtual uint8_t* OnGetContents() const = 0;

virtual bool OnCopyHostBuffer(const uint8_t* source,
Range source_range,
size_t offset) = 0;
Expand Down
2 changes: 1 addition & 1 deletion impeller/renderer/host_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ BufferView HostBuffer::Emplace(const void* buffer, size_t length) {
if (buffer) {
::memmove(GetBuffer() + old_length, buffer, length);
}
return BufferView{shared_from_this(), Range{old_length, length}};
return BufferView{shared_from_this(), GetBuffer(), Range{old_length, length}};
}

std::shared_ptr<const DeviceBuffer> HostBuffer::GetDeviceBuffer(
Expand Down
37 changes: 37 additions & 0 deletions impeller/renderer/renderer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -841,5 +841,42 @@ TEST_P(RendererTest, InactiveUniforms) {
OpenPlaygroundHere(callback);
}

TEST_P(RendererTest, CanCreateCPUBackedTexture) {
if (GetParam() != PlaygroundBackend::kMetal) {
GTEST_SKIP_("CPU backed textures only supported on Metal right now.");
}

auto context = GetContext();
auto allocator = context->GetResourceAllocator();
size_t dimension = 2;

do {
ISize size(dimension, dimension);
TextureDescriptor texture_descriptor;
texture_descriptor.storage_mode = StorageMode::kHostVisible;
texture_descriptor.format = PixelFormat::kR8G8B8A8UNormInt;
texture_descriptor.size = size;
auto row_bytes =
std::max(static_cast<uint16_t>(size.width * 4),
allocator->MinimumBytesPerRow(texture_descriptor.format));
auto buffer_size = size.height * row_bytes;

DeviceBufferDescriptor buffer_descriptor;
buffer_descriptor.storage_mode = StorageMode::kHostVisible;
buffer_descriptor.size = buffer_size;

auto buffer = allocator->CreateBuffer(buffer_descriptor);

ASSERT_TRUE(buffer);

auto texture = buffer->AsTexture(*allocator, texture_descriptor, row_bytes);

ASSERT_TRUE(texture);
ASSERT_TRUE(texture->IsValid());

dimension *= 2;
} while (dimension <= 8192);
}

} // namespace testing
} // namespace impeller

0 comments on commit f7000ed

Please sign in to comment.