-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] have Hostbuffer write directly to block allocated device buffers. #49505
Changes from 10 commits
340ebdd
2cef26c
2f04349
88d7b95
9ddcacd
9f896fb
5a82b6e
723cc9b
fefb257
3ab6e0f
7dd9854
8c06294
65dda4b
b0d6e59
e1b8d5d
ad16416
9d4867e
b132dd7
5a553f1
d4a32ed
2ccdb59
809adf5
ac12014
3b1cbc5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,22 +4,31 @@ | |
|
|
||
| #include "impeller/core/host_buffer.h" | ||
|
|
||
| #include <algorithm> | ||
| #include <cstring> | ||
|
|
||
| #include "flutter/fml/logging.h" | ||
| #include <tuple> | ||
|
|
||
| #include "impeller/core/allocator.h" | ||
| #include "impeller/core/buffer_view.h" | ||
| #include "impeller/core/device_buffer.h" | ||
| #include "impeller/core/device_buffer_descriptor.h" | ||
| #include "impeller/core/formats.h" | ||
|
|
||
| namespace impeller { | ||
|
|
||
| std::shared_ptr<HostBuffer> HostBuffer::Create() { | ||
| return std::shared_ptr<HostBuffer>(new HostBuffer()); | ||
| constexpr size_t kAllocatorBlockSize = 1024000; // 1024 Kb. | ||
|
|
||
| std::shared_ptr<HostBuffer> HostBuffer::Create( | ||
| const std::shared_ptr<Allocator>& allocator) { | ||
| return std::shared_ptr<HostBuffer>(new HostBuffer(allocator)); | ||
| } | ||
|
|
||
| HostBuffer::HostBuffer() = default; | ||
| HostBuffer::HostBuffer(const std::shared_ptr<Allocator>& allocator) { | ||
| state_->allocator = allocator; | ||
| DeviceBufferDescriptor desc; | ||
| desc.size = kAllocatorBlockSize; | ||
| desc.storage_mode = StorageMode::kHostVisible; | ||
| state_->device_buffers.push_back(allocator->CreateBuffer(desc)); | ||
| } | ||
|
|
||
| HostBuffer::~HostBuffer() = default; | ||
|
|
||
|
|
@@ -30,104 +39,101 @@ void HostBuffer::SetLabel(std::string label) { | |
| BufferView HostBuffer::Emplace(const void* buffer, | ||
| size_t length, | ||
| size_t align) { | ||
| auto [device_buffer, range] = state_->Emplace(buffer, length, align); | ||
| auto [data, range, device_buffer] = state_->Emplace(buffer, length, align); | ||
| if (!device_buffer) { | ||
| return {}; | ||
| } | ||
| return BufferView{state_, device_buffer, range}; | ||
| return BufferView{std::move(device_buffer), data, range}; | ||
| } | ||
|
|
||
| BufferView HostBuffer::Emplace(const void* buffer, size_t length) { | ||
| auto [device_buffer, range] = state_->Emplace(buffer, length); | ||
| auto [data, range, device_buffer] = state_->Emplace(buffer, length); | ||
| if (!device_buffer) { | ||
| return {}; | ||
| } | ||
| return BufferView{state_, device_buffer, range}; | ||
| return BufferView{std::move(device_buffer), data, range}; | ||
| } | ||
|
|
||
| BufferView HostBuffer::Emplace(size_t length, | ||
| size_t align, | ||
| const EmplaceProc& cb) { | ||
| auto [buffer, range] = state_->Emplace(length, align, cb); | ||
| if (!buffer) { | ||
| auto [data, range, device_buffer] = state_->Emplace(length, align, cb); | ||
| if (!device_buffer) { | ||
| return {}; | ||
| } | ||
| return BufferView{state_, buffer, range}; | ||
| return BufferView{std::move(device_buffer), data, range}; | ||
| } | ||
|
|
||
| std::shared_ptr<const DeviceBuffer> HostBuffer::GetDeviceBuffer( | ||
| Allocator& allocator) const { | ||
| return state_->GetDeviceBuffer(allocator); | ||
| return nullptr; | ||
| } | ||
|
|
||
| void HostBuffer::Reset() { | ||
| state_->Reset(); | ||
| } | ||
|
|
||
| size_t HostBuffer::GetSize() const { | ||
| return state_->GetReservedLength(); | ||
| } | ||
|
|
||
| size_t HostBuffer::GetLength() const { | ||
| return state_->GetLength(); | ||
| void HostBuffer::HostBufferState::MaybeCreateNewBuffer(size_t required_size) { | ||
| if (current_buffer + 1 >= device_buffers.size()) { | ||
| if (required_size > kAllocatorBlockSize) { | ||
| FML_LOG(ERROR) << "Created oversized buffer: " << required_size; | ||
|
||
| } | ||
| DeviceBufferDescriptor desc; | ||
| desc.size = std::max(kAllocatorBlockSize, required_size); | ||
| desc.storage_mode = StorageMode::kHostVisible; | ||
| device_buffers.push_back(allocator->CreateBuffer(desc)); | ||
| } | ||
| current_buffer++; | ||
| offset = 0; | ||
| } | ||
|
|
||
| std::pair<uint8_t*, Range> HostBuffer::HostBufferState::Emplace( | ||
| size_t length, | ||
| size_t align, | ||
| const EmplaceProc& cb) { | ||
| std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>> | ||
| HostBuffer::HostBufferState::Emplace(size_t length, | ||
| size_t align, | ||
| const EmplaceProc& cb) { | ||
| if (!cb) { | ||
| return {}; | ||
| } | ||
| auto old_length = GetLength(); | ||
| if (!Truncate(old_length + length)) { | ||
| return {}; | ||
| if (old_length + length > kAllocatorBlockSize) { | ||
| MaybeCreateNewBuffer(length); | ||
| } | ||
| generation++; | ||
| cb(GetBuffer() + old_length); | ||
|
|
||
| return std::make_pair(GetBuffer(), Range{old_length, length}); | ||
| } | ||
| cb(GetCurrentBuffer()->OnGetContents() + old_length); | ||
| GetCurrentBuffer()->Flush(Range{old_length, length}); | ||
|
|
||
| std::shared_ptr<const DeviceBuffer> | ||
| HostBuffer::HostBufferState::GetDeviceBuffer(Allocator& allocator) const { | ||
| if (generation == device_buffer_generation) { | ||
| return device_buffer; | ||
| } | ||
| auto new_buffer = allocator.CreateBufferWithCopy(GetBuffer(), GetLength()); | ||
| if (!new_buffer) { | ||
| return nullptr; | ||
| } | ||
| new_buffer->SetLabel(label); | ||
| device_buffer_generation = generation; | ||
| device_buffer = std::move(new_buffer); | ||
| return device_buffer; | ||
| offset += length; | ||
| return std::make_tuple(GetCurrentBuffer()->OnGetContents(), | ||
| Range{old_length, length}, GetCurrentBuffer()); | ||
| } | ||
|
|
||
| std::pair<uint8_t*, Range> HostBuffer::HostBufferState::Emplace( | ||
| const void* buffer, | ||
| size_t length) { | ||
| std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>> | ||
| HostBuffer::HostBufferState::Emplace(const void* buffer, size_t length) { | ||
| auto old_length = GetLength(); | ||
| if (!Truncate(old_length + length)) { | ||
| return {}; | ||
| if (old_length + length > kAllocatorBlockSize) { | ||
| MaybeCreateNewBuffer(length); | ||
| } | ||
| generation++; | ||
|
|
||
| if (buffer) { | ||
| ::memmove(GetBuffer() + old_length, buffer, length); | ||
| ::memmove(GetCurrentBuffer()->OnGetContents() + old_length, buffer, length); | ||
| GetCurrentBuffer()->Flush(Range{old_length, length}); | ||
| } | ||
| return std::make_pair(GetBuffer(), Range{old_length, length}); | ||
| offset += length; | ||
| return std::make_tuple(GetCurrentBuffer()->OnGetContents(), | ||
| Range{old_length, length}, GetCurrentBuffer()); | ||
| } | ||
|
|
||
| std::pair<uint8_t*, Range> HostBuffer::HostBufferState::Emplace( | ||
| const void* buffer, | ||
| size_t length, | ||
| size_t align) { | ||
| std::tuple<uint8_t*, Range, std::shared_ptr<DeviceBuffer>> | ||
| HostBuffer::HostBufferState::Emplace(const void* buffer, | ||
| size_t length, | ||
| size_t align) { | ||
| if (align == 0 || (GetLength() % align) == 0) { | ||
| return Emplace(buffer, length); | ||
| } | ||
|
|
||
| { | ||
| auto [buffer, range] = Emplace(nullptr, align - (GetLength() % align)); | ||
| auto [buffer, range, device_buffer] = | ||
| Emplace(nullptr, align - (GetLength() % align)); | ||
| if (!buffer) { | ||
| return {}; | ||
| } | ||
|
|
@@ -137,10 +143,13 @@ std::pair<uint8_t*, Range> HostBuffer::HostBufferState::Emplace( | |
| } | ||
|
|
||
| void HostBuffer::HostBufferState::Reset() { | ||
| generation += 1; | ||
| device_buffer = nullptr; | ||
| bool did_truncate = Truncate(0); | ||
| FML_CHECK(did_truncate); | ||
| offset = 0u; | ||
| current_buffer = 0u; | ||
| device_buffers.clear(); | ||
|
||
| DeviceBufferDescriptor desc; | ||
| desc.size = kAllocatorBlockSize; | ||
| desc.storage_mode = StorageMode::kHostVisible; | ||
| device_buffers.push_back(allocator->CreateBuffer(desc)); | ||
| } | ||
|
|
||
| } // namespace impeller | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Place definition in
device_buffer.cc?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done