From 340ebdd4bed40016a9f3e5b76d301272d01467b0 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Wed, 3 Jan 2024 13:08:25 -0800 Subject: [PATCH 01/21] [Impeller] have Hostbuffer write directly to block allocated device buffers. --- impeller/base/allocation.h | 1 - impeller/core/host_buffer.cc | 114 +++++++++-------- impeller/core/host_buffer.h | 37 +++--- impeller/entity/inline_pass_context.cc | 2 +- .../renderer/backend/vulkan/context_vk.cc | 8 +- impeller/renderer/blit_pass.cc | 9 +- impeller/renderer/blit_pass.h | 6 - impeller/renderer/compute_pass.cc | 4 +- impeller/renderer/host_buffer_unittests.cc | 116 +++++++++--------- impeller/renderer/render_pass.cc | 12 +- impeller/scene/skin.cc | 2 +- lib/gpu/host_buffer.cc | 3 +- 12 files changed, 156 insertions(+), 158 deletions(-) diff --git a/impeller/base/allocation.h b/impeller/base/allocation.h index dd1b06befa6fe..bd9b2370ef7fb 100644 --- a/impeller/base/allocation.h +++ b/impeller/base/allocation.h @@ -6,7 +6,6 @@ #define FLUTTER_IMPELLER_BASE_ALLOCATION_H_ #include -#include #include #include "flutter/fml/mapping.h" diff --git a/impeller/core/host_buffer.cc b/impeller/core/host_buffer.cc index 7e2eae85ac97f..387e5d195f421 100644 --- a/impeller/core/host_buffer.cc +++ b/impeller/core/host_buffer.cc @@ -6,20 +6,30 @@ #include #include - -#include "flutter/fml/logging.h" +#include #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::Create() { - return std::shared_ptr(new HostBuffer()); +constexpr size_t kAllocatorBlockSize = 1024000; // 1024 Kb. + +std::shared_ptr HostBuffer::Create( + const std::shared_ptr& allocator) { + return std::shared_ptr(new HostBuffer(allocator)); } -HostBuffer::HostBuffer() = default; +HostBuffer::HostBuffer(const std::shared_ptr& 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,34 +40,34 @@ 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{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{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{device_buffer, data, range}; } std::shared_ptr HostBuffer::GetDeviceBuffer( Allocator& allocator) const { - return state_->GetDeviceBuffer(allocator); + return nullptr; } void HostBuffer::Reset() { @@ -65,69 +75,67 @@ void HostBuffer::Reset() { } size_t HostBuffer::GetSize() const { - return state_->GetReservedLength(); + return 1024; } size_t HostBuffer::GetLength() const { return state_->GetLength(); } -std::pair HostBuffer::HostBufferState::Emplace( - size_t length, - size_t align, - const EmplaceProc& cb) { +std::tuple> +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) { + // Allocate new block. + DeviceBufferDescriptor desc; + desc.size = std::max(kAllocatorBlockSize, length); + desc.storage_mode = StorageMode::kHostVisible; + device_buffers.push_back(allocator->CreateBuffer(desc)); } - generation++; - cb(GetBuffer() + old_length); - return std::make_pair(GetBuffer(), Range{old_length, length}); -} + cb(device_buffers.back()->OnGetContents() + old_length); -std::shared_ptr -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(device_buffers.back()->OnGetContents(), + Range{old_length, length}, device_buffers.back()); } -std::pair HostBuffer::HostBufferState::Emplace( - const void* buffer, - size_t length) { +std::tuple> +HostBuffer::HostBufferState::Emplace(const void* buffer, size_t length) { auto old_length = GetLength(); - if (!Truncate(old_length + length)) { - return {}; + if (old_length + length > kAllocatorBlockSize) { + // Allocate new block. + DeviceBufferDescriptor desc; + desc.size = std::max(kAllocatorBlockSize, length); + desc.storage_mode = StorageMode::kHostVisible; + device_buffers.push_back(allocator->CreateBuffer(desc)); } - generation++; + if (buffer) { - ::memmove(GetBuffer() + old_length, buffer, length); + ::memmove(device_buffers.back()->OnGetContents() + old_length, buffer, + length); } - return std::make_pair(GetBuffer(), Range{old_length, length}); + offset += length; + return std::make_tuple(device_buffers.back()->OnGetContents(), + Range{old_length, length}, device_buffers.back()); } -std::pair HostBuffer::HostBufferState::Emplace( - const void* buffer, - size_t length, - size_t align) { +std::tuple> +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 +145,8 @@ std::pair HostBuffer::HostBufferState::Emplace( } void HostBuffer::HostBufferState::Reset() { - generation += 1; - device_buffer = nullptr; - bool did_truncate = Truncate(0); - FML_CHECK(did_truncate); + offset = 0u; + device_buffers.clear(); } } // namespace impeller diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h index 5c3a69c75dcbf..22b917f79acd1 100644 --- a/impeller/core/host_buffer.h +++ b/impeller/core/host_buffer.h @@ -6,20 +6,24 @@ #define FLUTTER_IMPELLER_CORE_HOST_BUFFER_H_ #include +#include #include #include #include -#include "impeller/base/allocation.h" #include "impeller/core/buffer.h" #include "impeller/core/buffer_view.h" #include "impeller/core/platform.h" namespace impeller { +// TODO: make this called something else, have a single buffer for all +// render/compute/blit passes, add flush call that no-ops if necessary. +// This currently assumes that the memory is coherent. class HostBuffer final : public Buffer { public: - static std::shared_ptr Create(); + static std::shared_ptr Create( + const std::shared_ptr& allocator); // |Buffer| virtual ~HostBuffer(); @@ -124,26 +128,23 @@ class HostBuffer final : public Buffer { size_t GetLength() const; private: - struct HostBufferState : public Buffer, public Allocation { - std::shared_ptr GetDeviceBuffer( - Allocator& allocator) const override; + struct HostBufferState { + [[nodiscard]] std::tuple> + Emplace(const void* buffer, size_t length); - [[nodiscard]] std::pair Emplace(const void* buffer, - size_t length); + std::tuple> + Emplace(size_t length, size_t align, const EmplaceProc& cb); - std::pair Emplace(size_t length, - size_t align, - const EmplaceProc& cb); - - std::pair Emplace(const void* buffer, - size_t length, - size_t align); + std::tuple> + Emplace(const void* buffer, size_t length, size_t align); void Reset(); - mutable std::shared_ptr device_buffer; - mutable size_t device_buffer_generation = 0u; - size_t generation = 1u; + size_t GetLength() const { return offset; } + + std::shared_ptr allocator; + mutable std::vector> device_buffers; + mutable size_t offset = 0u; std::string label; }; @@ -155,7 +156,7 @@ class HostBuffer final : public Buffer { [[nodiscard]] BufferView Emplace(const void* buffer, size_t length); - HostBuffer(); + explicit HostBuffer(const std::shared_ptr& allocator); HostBuffer(const HostBuffer&) = delete; diff --git a/impeller/entity/inline_pass_context.cc b/impeller/entity/inline_pass_context.cc index a1904b743bce8..b8295c2cb444a 100644 --- a/impeller/entity/inline_pass_context.cc +++ b/impeller/entity/inline_pass_context.cc @@ -6,9 +6,9 @@ #include +#include "impeller/base/allocation.h" #include "impeller/base/validation.h" #include "impeller/core/formats.h" -#include "impeller/core/texture_descriptor.h" #include "impeller/entity/entity_pass_target.h" #include "impeller/renderer/command_buffer.h" diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 6c1804dd74022..c3d9ac448e979 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -156,11 +156,11 @@ void ContextVK::Setup(Settings settings) { // 1. The user has explicitly enabled it. // 2. We are in a combination of debug mode, and running on Android. // (It's possible 2 is overly conservative and we can simplify this) - auto enable_validation = settings.enable_validation; + auto enable_validation = false; -#if defined(FML_OS_ANDROID) && !defined(NDEBUG) - enable_validation = true; -#endif + // #if defined(FML_OS_ANDROID) && !defined(NDEBUG) + // enable_validation = true; + // #endif auto caps = std::shared_ptr(new CapabilitiesVK(enable_validation)); diff --git a/impeller/renderer/blit_pass.cc b/impeller/renderer/blit_pass.cc index e521a6a6543ca..81c4e500b0494 100644 --- a/impeller/renderer/blit_pass.cc +++ b/impeller/renderer/blit_pass.cc @@ -9,24 +9,17 @@ #include "impeller/base/strings.h" #include "impeller/base/validation.h" #include "impeller/core/formats.h" -#include "impeller/core/host_buffer.h" -#include "impeller/renderer/blit_command.h" namespace impeller { -BlitPass::BlitPass() : transients_buffer_(HostBuffer::Create()) {} +BlitPass::BlitPass() {} BlitPass::~BlitPass() = default; -HostBuffer& BlitPass::GetTransientsBuffer() { - return *transients_buffer_; -} - void BlitPass::SetLabel(std::string label) { if (label.empty()) { return; } - transients_buffer_->SetLabel(SPrintF("%s Transients", label.c_str())); OnSetLabel(std::move(label)); } diff --git a/impeller/renderer/blit_pass.h b/impeller/renderer/blit_pass.h index 61f53b49dc5f1..64ab734c1035b 100644 --- a/impeller/renderer/blit_pass.h +++ b/impeller/renderer/blit_pass.h @@ -6,11 +6,9 @@ #define FLUTTER_IMPELLER_RENDERER_BLIT_PASS_H_ #include -#include #include "impeller/core/device_buffer.h" #include "impeller/core/texture.h" -#include "impeller/renderer/blit_command.h" namespace impeller { @@ -33,8 +31,6 @@ class BlitPass { void SetLabel(std::string label); - HostBuffer& GetTransientsBuffer(); - //---------------------------------------------------------------------------- /// @brief Record a command to copy the contents of one texture to /// another texture. The blit area is limited by the intersection @@ -128,8 +124,6 @@ class BlitPass { const std::shared_ptr& transients_allocator) const = 0; protected: - std::shared_ptr transients_buffer_; - explicit BlitPass(); virtual void OnSetLabel(std::string label) = 0; diff --git a/impeller/renderer/compute_pass.cc b/impeller/renderer/compute_pass.cc index 95478f964acf9..0044231f39070 100644 --- a/impeller/renderer/compute_pass.cc +++ b/impeller/renderer/compute_pass.cc @@ -12,7 +12,9 @@ namespace impeller { ComputePass::ComputePass(std::weak_ptr context) - : context_(std::move(context)), transients_buffer_(HostBuffer::Create()) {} + : context_(std::move(context)), + transients_buffer_( + HostBuffer::Create(context_.lock()->GetResourceAllocator())) {} ComputePass::~ComputePass() = default; diff --git a/impeller/renderer/host_buffer_unittests.cc b/impeller/renderer/host_buffer_unittests.cc index 3046e801b24c0..29b0b63d99424 100644 --- a/impeller/renderer/host_buffer_unittests.cc +++ b/impeller/renderer/host_buffer_unittests.cc @@ -8,72 +8,72 @@ namespace impeller { namespace testing { -TEST(HostBufferTest, TestInitialization) { - ASSERT_TRUE(HostBuffer::Create()); - // Newly allocated buffers don't touch the heap till they have to. - ASSERT_EQ(HostBuffer::Create()->GetLength(), 0u); - ASSERT_EQ(HostBuffer::Create()->GetSize(), 0u); -} +// TEST(HostBufferTest, TestInitialization) { +// ASSERT_TRUE(HostBuffer::Create()); +// // Newly allocated buffers don't touch the heap till they have to. +// ASSERT_EQ(HostBuffer::Create()->GetLength(), 0u); +// ASSERT_EQ(HostBuffer::Create()->GetSize(), 0u); +// } -TEST(HostBufferTest, CanEmplace) { - struct Length2 { - uint8_t pad[2]; - }; - static_assert(sizeof(Length2) == 2u); +// TEST(HostBufferTest, CanEmplace) { +// struct Length2 { +// uint8_t pad[2]; +// }; +// static_assert(sizeof(Length2) == 2u); - auto buffer = HostBuffer::Create(); +// auto buffer = HostBuffer::Create(); - for (size_t i = 0; i < 12500; i++) { - auto view = buffer->Emplace(Length2{}); - ASSERT_TRUE(view); - ASSERT_EQ(buffer->GetLength(), (i + 1) * sizeof(Length2)); - ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u)); - } -} +// for (size_t i = 0; i < 12500; i++) { +// auto view = buffer->Emplace(Length2{}); +// ASSERT_TRUE(view); +// ASSERT_EQ(buffer->GetLength(), (i + 1) * sizeof(Length2)); +// ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u)); +// } +// } -TEST(HostBufferTest, CanEmplaceWithAlignment) { - struct Length2 { - uint8_t pad[2]; - }; - static_assert(sizeof(Length2) == 2); - struct alignas(16) Align16 { - uint8_t pad[2]; - }; - static_assert(alignof(Align16) == 16); - static_assert(sizeof(Align16) == 16); +// TEST(HostBufferTest, CanEmplaceWithAlignment) { +// struct Length2 { +// uint8_t pad[2]; +// }; +// static_assert(sizeof(Length2) == 2); +// struct alignas(16) Align16 { +// uint8_t pad[2]; +// }; +// static_assert(alignof(Align16) == 16); +// static_assert(sizeof(Align16) == 16); - auto buffer = HostBuffer::Create(); - ASSERT_TRUE(buffer); +// auto buffer = HostBuffer::Create(); +// ASSERT_TRUE(buffer); - { - auto view = buffer->Emplace(Length2{}); - ASSERT_TRUE(view); - ASSERT_EQ(buffer->GetLength(), 2u); - ASSERT_EQ(view.range, Range(0u, 2u)); - } +// { +// auto view = buffer->Emplace(Length2{}); +// ASSERT_TRUE(view); +// ASSERT_EQ(buffer->GetLength(), 2u); +// ASSERT_EQ(view.range, Range(0u, 2u)); +// } - { - auto view = buffer->Emplace(Align16{}); - ASSERT_TRUE(view); - ASSERT_EQ(view.range.offset, 16u); - ASSERT_EQ(view.range.length, 16u); - ASSERT_EQ(buffer->GetLength(), 32u); - } - { - auto view = buffer->Emplace(Length2{}); - ASSERT_TRUE(view); - ASSERT_EQ(buffer->GetLength(), 34u); - ASSERT_EQ(view.range, Range(32u, 2u)); - } +// { +// auto view = buffer->Emplace(Align16{}); +// ASSERT_TRUE(view); +// ASSERT_EQ(view.range.offset, 16u); +// ASSERT_EQ(view.range.length, 16u); +// ASSERT_EQ(buffer->GetLength(), 32u); +// } +// { +// auto view = buffer->Emplace(Length2{}); +// ASSERT_TRUE(view); +// ASSERT_EQ(buffer->GetLength(), 34u); +// ASSERT_EQ(view.range, Range(32u, 2u)); +// } - { - auto view = buffer->Emplace(Align16{}); - ASSERT_TRUE(view); - ASSERT_EQ(view.range.offset, 48u); - ASSERT_EQ(view.range.length, 16u); - ASSERT_EQ(buffer->GetLength(), 64u); - } -} +// { +// auto view = buffer->Emplace(Align16{}); +// ASSERT_TRUE(view); +// ASSERT_EQ(view.range.offset, 48u); +// ASSERT_EQ(view.range.length, 16u); +// ASSERT_EQ(buffer->GetLength(), 64u); +// } +// } } // namespace testing } // namespace impeller diff --git a/impeller/renderer/render_pass.cc b/impeller/renderer/render_pass.cc index 66b9551588743..624ceea6ef59e 100644 --- a/impeller/renderer/render_pass.cc +++ b/impeller/renderer/render_pass.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "impeller/renderer/render_pass.h" +#include "impeller/core/host_buffer.h" namespace impeller { @@ -17,14 +18,15 @@ RenderPass::RenderPass(std::weak_ptr context, transients_buffer_() { auto strong_context = context_.lock(); FML_DCHECK(strong_context); - transients_buffer_ = strong_context->GetHostBufferPool().Grab(); + transients_buffer_ = + HostBuffer::Create(strong_context->GetResourceAllocator()); } RenderPass::~RenderPass() { - auto strong_context = context_.lock(); - if (strong_context) { - strong_context->GetHostBufferPool().Recycle(transients_buffer_); - } + // auto strong_context = context_.lock(); + // if (strong_context) { + // strong_context->GetHostBufferPool().Recycle(transients_buffer_); + // } } SampleCount RenderPass::GetSampleCount() const { diff --git a/impeller/scene/skin.cc b/impeller/scene/skin.cc index b3ea96993a6e7..ffabd8253b243 100644 --- a/impeller/scene/skin.cc +++ b/impeller/scene/skin.cc @@ -6,10 +6,10 @@ #include #include -#include #include #include "flutter/fml/logging.h" +#include "impeller/base/allocation.h" #include "impeller/core/allocator.h" #include "impeller/scene/importer/conversions.h" diff --git a/lib/gpu/host_buffer.cc b/lib/gpu/host_buffer.cc index b7edccf5318d6..78830cbc64e17 100644 --- a/lib/gpu/host_buffer.cc +++ b/lib/gpu/host_buffer.cc @@ -13,7 +13,8 @@ namespace gpu { IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, HostBuffer); -HostBuffer::HostBuffer() : host_buffer_(impeller::HostBuffer::Create()) {} +HostBuffer::HostBuffer() + : host_buffer_(impeller::HostBuffer::Create(nullptr)) {} HostBuffer::~HostBuffer() = default; From 2cef26c826c098a410473a39556546008bf276e9 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 4 Jan 2024 14:23:54 -0800 Subject: [PATCH 02/21] more adjustments. --- impeller/aiks/testing/context_mock.h | 5 ++ impeller/core/host_buffer.cc | 49 ++++++++----------- impeller/core/host_buffer.h | 23 ++++----- .../renderer/backend/gles/context_gles.cc | 7 +++ impeller/renderer/backend/gles/context_gles.h | 5 ++ impeller/renderer/backend/metal/context_mtl.h | 4 ++ .../renderer/backend/metal/context_mtl.mm | 7 +++ .../backend/vulkan/command_pool_vk.cc | 3 +- .../renderer/backend/vulkan/command_pool_vk.h | 3 +- .../renderer/backend/vulkan/context_vk.cc | 6 +++ impeller/renderer/backend/vulkan/context_vk.h | 6 ++- .../backend/vulkan/device_buffer_vk.cc | 1 + .../backend/vulkan/device_buffer_vk.h | 3 -- .../backend/vulkan/surface_context_vk.cc | 6 +++ .../backend/vulkan/surface_context_vk.h | 4 ++ impeller/renderer/context.h | 6 +-- impeller/renderer/render_pass.cc | 4 -- impeller/renderer/render_pass.h | 5 +- impeller/renderer/testing/mocks.h | 5 ++ 19 files changed, 93 insertions(+), 59 deletions(-) diff --git a/impeller/aiks/testing/context_mock.h b/impeller/aiks/testing/context_mock.h index b2d9138503fbb..72c0abee77fa9 100644 --- a/impeller/aiks/testing/context_mock.h +++ b/impeller/aiks/testing/context_mock.h @@ -111,6 +111,11 @@ class ContextMock : public Context { (), (const, override)); + MOCK_METHOD(const std::shared_ptr, + GetTransientsBuffer, + (), + (const, override)); + MOCK_METHOD(void, Shutdown, (), (override)); }; diff --git a/impeller/core/host_buffer.cc b/impeller/core/host_buffer.cc index 387e5d195f421..67856e4789be8 100644 --- a/impeller/core/host_buffer.cc +++ b/impeller/core/host_buffer.cc @@ -4,7 +4,6 @@ #include "impeller/core/host_buffer.h" -#include #include #include @@ -44,7 +43,7 @@ BufferView HostBuffer::Emplace(const void* buffer, if (!device_buffer) { return {}; } - return BufferView{device_buffer, data, range}; + return BufferView{std::move(device_buffer), data, range}; } BufferView HostBuffer::Emplace(const void* buffer, size_t length) { @@ -52,7 +51,7 @@ BufferView HostBuffer::Emplace(const void* buffer, size_t length) { if (!device_buffer) { return {}; } - return BufferView{device_buffer, data, range}; + return BufferView{std::move(device_buffer), data, range}; } BufferView HostBuffer::Emplace(size_t length, @@ -62,7 +61,7 @@ BufferView HostBuffer::Emplace(size_t length, if (!device_buffer) { return {}; } - return BufferView{device_buffer, data, range}; + return BufferView{std::move(device_buffer), data, range}; } std::shared_ptr HostBuffer::GetDeviceBuffer( @@ -74,12 +73,15 @@ void HostBuffer::Reset() { state_->Reset(); } -size_t HostBuffer::GetSize() const { - return 1024; -} - -size_t HostBuffer::GetLength() const { - return state_->GetLength(); +void HostBuffer::HostBufferState::MaybeCreateNewBuffer() { + if (current_buffer + 1 >= device_buffers.size()) { + DeviceBufferDescriptor desc; + desc.size = kAllocatorBlockSize; + desc.storage_mode = StorageMode::kHostVisible; + device_buffers.push_back(allocator->CreateBuffer(desc)); + } + current_buffer++; + offset = 0; } std::tuple> @@ -91,38 +93,29 @@ HostBuffer::HostBufferState::Emplace(size_t length, } auto old_length = GetLength(); if (old_length + length > kAllocatorBlockSize) { - // Allocate new block. - DeviceBufferDescriptor desc; - desc.size = std::max(kAllocatorBlockSize, length); - desc.storage_mode = StorageMode::kHostVisible; - device_buffers.push_back(allocator->CreateBuffer(desc)); + MaybeCreateNewBuffer(); } - cb(device_buffers.back()->OnGetContents() + old_length); + cb(GetCurrentBuffer()->OnGetContents() + old_length); offset += length; - return std::make_tuple(device_buffers.back()->OnGetContents(), - Range{old_length, length}, device_buffers.back()); + return std::make_tuple(GetCurrentBuffer()->OnGetContents(), + Range{old_length, length}, GetCurrentBuffer()); } std::tuple> HostBuffer::HostBufferState::Emplace(const void* buffer, size_t length) { auto old_length = GetLength(); if (old_length + length > kAllocatorBlockSize) { - // Allocate new block. - DeviceBufferDescriptor desc; - desc.size = std::max(kAllocatorBlockSize, length); - desc.storage_mode = StorageMode::kHostVisible; - device_buffers.push_back(allocator->CreateBuffer(desc)); + MaybeCreateNewBuffer(); } if (buffer) { - ::memmove(device_buffers.back()->OnGetContents() + old_length, buffer, - length); + ::memmove(GetCurrentBuffer()->OnGetContents() + old_length, buffer, length); } offset += length; - return std::make_tuple(device_buffers.back()->OnGetContents(), - Range{old_length, length}, device_buffers.back()); + return std::make_tuple(GetCurrentBuffer()->OnGetContents(), + Range{old_length, length}, GetCurrentBuffer()); } std::tuple> @@ -146,7 +139,7 @@ HostBuffer::HostBufferState::Emplace(const void* buffer, void HostBuffer::HostBufferState::Reset() { offset = 0u; - device_buffers.clear(); + current_buffer++; } } // namespace impeller diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h index 22b917f79acd1..eff8ceac50e56 100644 --- a/impeller/core/host_buffer.h +++ b/impeller/core/host_buffer.h @@ -17,9 +17,6 @@ namespace impeller { -// TODO: make this called something else, have a single buffer for all -// render/compute/blit passes, add flush call that no-ops if necessary. -// This currently assumes that the memory is coherent. class HostBuffer final : public Buffer { public: static std::shared_ptr Create( @@ -118,15 +115,6 @@ class HostBuffer final : public Buffer { /// reused. void Reset(); - //---------------------------------------------------------------------------- - /// @brief Returns the capacity of the HostBuffer in memory in bytes. - size_t GetSize() const; - - //---------------------------------------------------------------------------- - /// @brief Returns the size of the currently allocated HostBuffer memory in - /// bytes. - size_t GetLength() const; - private: struct HostBufferState { [[nodiscard]] std::tuple> @@ -142,9 +130,16 @@ class HostBuffer final : public Buffer { size_t GetLength() const { return offset; } + void MaybeCreateNewBuffer(); + + std::shared_ptr GetCurrentBuffer() { + return device_buffers[current_buffer]; + } + std::shared_ptr allocator; - mutable std::vector> device_buffers; - mutable size_t offset = 0u; + std::vector> device_buffers; + size_t current_buffer = 0u; + size_t offset = 0u; std::string label; }; diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index 779255dffa6c4..a9a06bc0e3b62 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -7,6 +7,7 @@ #include "impeller/base/config.h" #include "impeller/base/validation.h" +#include "impeller/core/host_buffer.h" #include "impeller/renderer/backend/gles/command_buffer_gles.h" #include "impeller/renderer/backend/gles/gpu_tracer_gles.h" @@ -65,6 +66,7 @@ ContextGLES::ContextGLES( std::shared_ptr(new SamplerLibraryGLES( device_capabilities_->SupportsDecalSamplerAddressMode())); } + host_buffer_ = HostBuffer::Create(resource_allocator_); gpu_tracer_ = std::make_shared(GetReactor()->GetProcTable(), enable_gpu_tracing); is_valid_ = true; @@ -132,6 +134,11 @@ std::shared_ptr ContextGLES::CreateCommandBuffer() const { new CommandBufferGLES(weak_from_this(), reactor_)); } +// |Context| +const std::shared_ptr ContextGLES::GetTransientsBuffer() const { + return host_buffer_; +} + // |Context| const std::shared_ptr& ContextGLES::GetCapabilities() const { diff --git a/impeller/renderer/backend/gles/context_gles.h b/impeller/renderer/backend/gles/context_gles.h index a81b10ec75fb3..2286473a9eecd 100644 --- a/impeller/renderer/backend/gles/context_gles.h +++ b/impeller/renderer/backend/gles/context_gles.h @@ -9,6 +9,7 @@ #include #include "flutter/fml/macros.h" #include "impeller/base/backend_cast.h" +#include "impeller/core/host_buffer.h" #include "impeller/renderer/backend/gles/allocator_gles.h" #include "impeller/renderer/backend/gles/capabilities_gles.h" #include "impeller/renderer/backend/gles/gpu_tracer_gles.h" @@ -52,6 +53,7 @@ class ContextGLES final : public Context, std::shared_ptr sampler_library_; std::shared_ptr resource_allocator_; std::shared_ptr gpu_tracer_; + std::shared_ptr host_buffer_; // Note: This is stored separately from the ProcTableGLES CapabilitiesGLES // in order to satisfy the Context::GetCapabilities signature which returns @@ -88,6 +90,9 @@ class ContextGLES final : public Context, // |Context| const std::shared_ptr& GetCapabilities() const override; + // |Context| + const std::shared_ptr GetTransientsBuffer() const override; + // |Context| void Shutdown() override; diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index d7561f52c3f7d..fe4486fc9740d 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -83,6 +83,9 @@ class ContextMTL final : public Context, // |Context| const std::shared_ptr& GetCapabilities() const override; + // |Context| + const std::shared_ptr GetTransientsBuffer() const override; + void SetCapabilities(const std::shared_ptr& capabilities); // |Context| @@ -129,6 +132,7 @@ class ContextMTL final : public Context, #endif // IMPELLER_DEBUG std::deque> tasks_awaiting_gpu_; std::unique_ptr sync_switch_observer_; + std::shared_ptr host_buffer_; bool is_valid_ = false; ContextMTL( diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index 90054aa21dcbd..045adab1ad2fb 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -13,6 +13,7 @@ #include "flutter/fml/paths.h" #include "flutter/fml/synchronization/sync_switch.h" #include "impeller/core/formats.h" +#include "impeller/core/host_buffer.h" #include "impeller/core/sampler_descriptor.h" #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h" #include "impeller/renderer/backend/metal/sampler_library_mtl.h" @@ -147,6 +148,7 @@ static bool DeviceSupportsComputeSubgroups(id device) { device_capabilities_ = InferMetalCapabilities(device_, PixelFormat::kB8G8R8A8UNormInt); + host_buffer_ = HostBuffer::Create(resource_allocator_); #ifdef IMPELLER_DEBUG gpu_tracer_ = std::make_shared(); #endif // IMPELLER_DEBUG @@ -309,6 +311,11 @@ new ContextMTL(device, command_queue, return is_valid_; } +// |Context| +const std::shared_ptr ContextMTL::GetTransientsBuffer() const { + return host_buffer_; +} + // |Context| std::shared_ptr ContextMTL::GetShaderLibrary() const { return shader_library_; diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.cc b/impeller/renderer/backend/vulkan/command_pool_vk.cc index 018a2199882c2..8f85cc956f27f 100644 --- a/impeller/renderer/backend/vulkan/command_pool_vk.cc +++ b/impeller/renderer/backend/vulkan/command_pool_vk.cc @@ -9,8 +9,9 @@ #include #include "fml/thread_local.h" -#include "fml/trace_event.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/resource_manager_vk.h" + #include "impeller/renderer/backend/vulkan/vk.h" // IWYU pragma: keep. #include "vulkan/vulkan_structs.hpp" diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.h b/impeller/renderer/backend/vulkan/command_pool_vk.h index 6fb1bcadcd3e2..6df3c81006751 100644 --- a/impeller/renderer/backend/vulkan/command_pool_vk.h +++ b/impeller/renderer/backend/vulkan/command_pool_vk.h @@ -8,9 +8,8 @@ #include #include #include -#include "fml/macros.h" + #include "impeller/base/thread.h" -#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/vk.h" // IWYU pragma: keep. namespace impeller { diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index c3d9ac448e979..4954ca88ff534 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -5,6 +5,7 @@ #include "impeller/renderer/backend/vulkan/context_vk.h" #include "fml/concurrent_message_loop.h" +#include "impeller/core/host_buffer.h" #ifdef FML_OS_ANDROID #include @@ -445,6 +446,7 @@ void ContextVK::Setup(Settings settings) { command_pool_recycler_ = std::move(command_pool_recycler); descriptor_pool_recycler_ = std::move(descriptor_pool_recycler); device_name_ = std::string(physical_device_properties.deviceName); + host_buffer_ = HostBuffer::Create(allocator_); is_valid_ = true; // Create the GPU Tracer later because it depends on state from @@ -471,6 +473,10 @@ bool ContextVK::IsValid() const { return is_valid_; } +const std::shared_ptr ContextVK::GetTransientsBuffer() const { + return host_buffer_; +} + std::shared_ptr ContextVK::GetResourceAllocator() const { return allocator_; } diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 2bb9927dca65d..6ac075623ae4a 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -8,12 +8,12 @@ #include #include "flutter/fml/concurrent_message_loop.h" -#include "flutter/fml/macros.h" #include "flutter/fml/mapping.h" #include "flutter/fml/unique_fd.h" #include "fml/thread.h" #include "impeller/base/backend_cast.h" #include "impeller/core/formats.h" +#include "impeller/core/host_buffer.h" #include "impeller/renderer/backend/vulkan/command_pool_vk.h" #include "impeller/renderer/backend/vulkan/device_holder.h" #include "impeller/renderer/backend/vulkan/pipeline_library_vk.h" @@ -86,6 +86,9 @@ class ContextVK final : public Context, // |Context| const std::shared_ptr& GetCapabilities() const override; + // |Context| + const std::shared_ptr GetTransientsBuffer() const override; + // |Context| void Shutdown() override; @@ -198,6 +201,7 @@ class ContextVK final : public Context, std::unique_ptr queue_submit_thread_; std::shared_ptr gpu_tracer_; std::shared_ptr descriptor_pool_recycler_; + std::shared_ptr host_buffer_; bool sync_presentation_ = false; const uint64_t hash_; diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.cc b/impeller/renderer/backend/vulkan/device_buffer_vk.cc index 483bfab7c2f7f..247d2cd2f029e 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.cc @@ -5,6 +5,7 @@ #include "impeller/renderer/backend/vulkan/device_buffer_vk.h" #include "flutter/fml/trace_event.h" +#include "impeller/renderer/backend/vulkan/context_vk.h" namespace impeller { diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.h b/impeller/renderer/backend/vulkan/device_buffer_vk.h index c2e617dff3b8f..686cb2ec72e05 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.h +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.h @@ -7,11 +7,8 @@ #include -#include "flutter/fml/macros.h" -#include "flutter/fml/trace_event.h" #include "impeller/base/backend_cast.h" #include "impeller/core/device_buffer.h" -#include "impeller/renderer/backend/vulkan/context_vk.h" #include "impeller/renderer/backend/vulkan/resource_manager_vk.h" #include "impeller/renderer/backend/vulkan/vma.h" diff --git a/impeller/renderer/backend/vulkan/surface_context_vk.cc b/impeller/renderer/backend/vulkan/surface_context_vk.cc index afc1407f6f3f5..8c9c1c4a44ad0 100644 --- a/impeller/renderer/backend/vulkan/surface_context_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_context_vk.cc @@ -48,6 +48,12 @@ std::shared_ptr SurfaceContextVK::CreateCommandBuffer() const { return parent_->CreateCommandBuffer(); } +// |Context| +const std::shared_ptr SurfaceContextVK::GetTransientsBuffer() + const { + return parent_->GetTransientsBuffer(); +} + const std::shared_ptr& SurfaceContextVK::GetCapabilities() const { return parent_->GetCapabilities(); diff --git a/impeller/renderer/backend/vulkan/surface_context_vk.h b/impeller/renderer/backend/vulkan/surface_context_vk.h index 5c8a327685dba..4ac727d156390 100644 --- a/impeller/renderer/backend/vulkan/surface_context_vk.h +++ b/impeller/renderer/backend/vulkan/surface_context_vk.h @@ -8,6 +8,7 @@ #include #include "impeller/base/backend_cast.h" +#include "impeller/core/host_buffer.h" #include "impeller/renderer/backend/vulkan/vk.h" #include "impeller/renderer/context.h" @@ -49,6 +50,9 @@ class SurfaceContextVK : public Context, // |Context| std::shared_ptr CreateCommandBuffer() const override; + // |Context| + const std::shared_ptr GetTransientsBuffer() const override; + // |Context| const std::shared_ptr& GetCapabilities() const override; diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index 36ad0c2e1899d..f079a2d7d83cb 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -181,9 +181,7 @@ class Context { /// pending work. virtual void SetSyncPresentation(bool value) {} - //---------------------------------------------------------------------------- - /// @brief Accessor for a pool of HostBuffers. - Pool& GetHostBufferPool() const { return host_buffer_pool_; } + virtual const std::shared_ptr GetTransientsBuffer() const = 0; CaptureContext capture; @@ -204,8 +202,6 @@ class Context { Context(); private: - mutable Pool host_buffer_pool_ = Pool(1'000'000); - Context(const Context&) = delete; Context& operator=(const Context&) = delete; diff --git a/impeller/renderer/render_pass.cc b/impeller/renderer/render_pass.cc index 624ceea6ef59e..aedac9e365f96 100644 --- a/impeller/renderer/render_pass.cc +++ b/impeller/renderer/render_pass.cc @@ -49,10 +49,6 @@ ISize RenderPass::GetRenderTargetSize() const { return render_target_size_; } -HostBuffer& RenderPass::GetTransientsBuffer() { - return *transients_buffer_; -} - void RenderPass::SetLabel(std::string label) { if (label.empty()) { return; diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index ff0d6d50c9be6..b0c543b06b407 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -47,7 +47,10 @@ class RenderPass { commands_.reserve(command_count); } - HostBuffer& GetTransientsBuffer(); + HostBuffer& GetTransientsBuffer() { + // Hack. + return *GetContext().lock()->GetTransientsBuffer(); + } //---------------------------------------------------------------------------- /// @brief Record a command for subsequent encoding to the underlying diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index 4960a57ef78fd..bb7bc488b74cf 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -160,6 +160,11 @@ class MockImpellerContext : public Context { (), (const, override)); + MOCK_METHOD(const std::shared_ptr, + GetTransientsBuffer, + (), + (const, override)); + MOCK_METHOD(const std::shared_ptr&, GetCapabilities, (), From 2f0434920f976a1c259490c0a5a2ff1161fadac3 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 4 Jan 2024 19:18:05 -0800 Subject: [PATCH 03/21] flush work. --- impeller/core/device_buffer.h | 2 ++ impeller/core/host_buffer.cc | 20 ++++++++++++++----- impeller/core/host_buffer.h | 2 +- impeller/entity/entity_pass.cc | 10 +++++----- impeller/playground/playground.cc | 1 + .../backend/vulkan/command_encoder_vk.cc | 12 ++++++----- .../backend/vulkan/command_encoder_vk.h | 4 +++- .../backend/vulkan/device_buffer_vk.cc | 7 +++++++ .../backend/vulkan/device_buffer_vk.h | 3 +++ 9 files changed, 44 insertions(+), 17 deletions(-) diff --git a/impeller/core/device_buffer.h b/impeller/core/device_buffer.h index c3ed289922d30..2b16e97a2ce61 100644 --- a/impeller/core/device_buffer.h +++ b/impeller/core/device_buffer.h @@ -45,6 +45,8 @@ class DeviceBuffer : public Buffer, virtual uint8_t* OnGetContents() const = 0; + virtual void Flush(std::optional range) const {} + protected: const DeviceBufferDescriptor desc_; diff --git a/impeller/core/host_buffer.cc b/impeller/core/host_buffer.cc index 67856e4789be8..422bde4d1c94c 100644 --- a/impeller/core/host_buffer.cc +++ b/impeller/core/host_buffer.cc @@ -73,10 +73,13 @@ void HostBuffer::Reset() { state_->Reset(); } -void HostBuffer::HostBufferState::MaybeCreateNewBuffer() { +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 = kAllocatorBlockSize; + desc.size = std::max(kAllocatorBlockSize, required_size); desc.storage_mode = StorageMode::kHostVisible; device_buffers.push_back(allocator->CreateBuffer(desc)); } @@ -93,10 +96,11 @@ HostBuffer::HostBufferState::Emplace(size_t length, } auto old_length = GetLength(); if (old_length + length > kAllocatorBlockSize) { - MaybeCreateNewBuffer(); + MaybeCreateNewBuffer(length); } cb(GetCurrentBuffer()->OnGetContents() + old_length); + GetCurrentBuffer()->Flush(Range{old_length, length}); offset += length; return std::make_tuple(GetCurrentBuffer()->OnGetContents(), @@ -107,11 +111,12 @@ std::tuple> HostBuffer::HostBufferState::Emplace(const void* buffer, size_t length) { auto old_length = GetLength(); if (old_length + length > kAllocatorBlockSize) { - MaybeCreateNewBuffer(); + MaybeCreateNewBuffer(length); } if (buffer) { ::memmove(GetCurrentBuffer()->OnGetContents() + old_length, buffer, length); + GetCurrentBuffer()->Flush(Range{old_length, length}); } offset += length; return std::make_tuple(GetCurrentBuffer()->OnGetContents(), @@ -139,7 +144,12 @@ HostBuffer::HostBufferState::Emplace(const void* buffer, void HostBuffer::HostBufferState::Reset() { offset = 0u; - current_buffer++; + 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 diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h index eff8ceac50e56..49fd28c994b01 100644 --- a/impeller/core/host_buffer.h +++ b/impeller/core/host_buffer.h @@ -130,7 +130,7 @@ class HostBuffer final : public Buffer { size_t GetLength() const { return offset; } - void MaybeCreateNewBuffer(); + void MaybeCreateNewBuffer(size_t required_size); std::shared_ptr GetCurrentBuffer() { return device_buffers[current_buffer]; diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 495b038273b68..1cc56baeb9fff 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -304,6 +304,11 @@ bool EntityPass::Render(ContentContext& renderer, renderer.GetContext()->capture.GetDocument(kCaptureDocumentName); renderer.GetRenderTargetCache()->Start(); + fml::ScopedCleanupClosure reset_state([&renderer]() { + renderer.GetLazyGlyphAtlas()->ResetTextFrames(); + renderer.GetRenderTargetCache()->End(); + renderer.GetContext()->GetTransientsBuffer()->Reset(); + }); auto root_render_target = render_target; @@ -317,11 +322,6 @@ bool EntityPass::Render(ContentContext& renderer, Rect::MakeSize(root_render_target.GetRenderTargetSize()), {.readonly = true}); - fml::ScopedCleanupClosure reset_state([&renderer]() { - renderer.GetLazyGlyphAtlas()->ResetTextFrames(); - renderer.GetRenderTargetCache()->End(); - }); - IterateAllEntities([lazy_glyph_atlas = renderer.GetLazyGlyphAtlas()](const Entity& entity) { if (const auto& contents = entity.GetContents()) { diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index 1c6dbfa694b49..07bb72c09b355 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -317,6 +317,7 @@ bool Playground::OpenPlaygroundHere( if (!ShouldKeepRendering()) { break; } + renderer_->GetContext()->GetTransientsBuffer()->Reset(); } ::glfwHideWindow(window); diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.cc b/impeller/renderer/backend/vulkan/command_encoder_vk.cc index 31ab804027da9..4750928450a31 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.cc +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.cc @@ -142,20 +142,22 @@ std::shared_ptr CommandEncoderFactoryVK::Create() { tracked_objects->GetGPUProbe().RecordCmdBufferStart( tracked_objects->GetCommandBuffer()); - return std::make_shared(context->GetDeviceHolder(), - tracked_objects, queue, - context->GetFenceWaiter()); + return std::make_shared( + context->GetDeviceHolder(), tracked_objects, queue, + context->GetFenceWaiter(), context->GetTransientsBuffer()); } CommandEncoderVK::CommandEncoderVK( std::weak_ptr device_holder, std::shared_ptr tracked_objects, const std::shared_ptr& queue, - std::shared_ptr fence_waiter) + std::shared_ptr fence_waiter, + std::shared_ptr host_buffer) : device_holder_(std::move(device_holder)), tracked_objects_(std::move(tracked_objects)), queue_(queue), - fence_waiter_(std::move(fence_waiter)) {} + fence_waiter_(std::move(fence_waiter)), + host_buffer_(std::move(host_buffer)) {} CommandEncoderVK::~CommandEncoderVK() = default; diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.h b/impeller/renderer/backend/vulkan/command_encoder_vk.h index 612c63f213034..fed6ff5199ba0 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.h +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.h @@ -54,7 +54,8 @@ class CommandEncoderVK { CommandEncoderVK(std::weak_ptr device_holder, std::shared_ptr tracked_objects, const std::shared_ptr& queue, - std::shared_ptr fence_waiter); + std::shared_ptr fence_waiter, + std::shared_ptr host_buffer); ~CommandEncoderVK(); @@ -95,6 +96,7 @@ class CommandEncoderVK { std::shared_ptr tracked_objects_; std::shared_ptr queue_; const std::shared_ptr fence_waiter_; + std::shared_ptr host_buffer_; bool is_valid_ = true; void Reset(); diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.cc b/impeller/renderer/backend/vulkan/device_buffer_vk.cc index 247d2cd2f029e..9a8792b2dfeff 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.cc @@ -63,6 +63,13 @@ bool DeviceBufferVK::SetLabel(const std::string& label) { label); } +void DeviceBufferVK::Flush(std::optional range) const { + auto flush_range = range.value_or(Range{0, GetDeviceBufferDescriptor().size}); + ::vmaFlushAllocation(resource_->buffer.get().allocator, + resource_->buffer.get().allocation, flush_range.offset, + flush_range.length); +} + bool DeviceBufferVK::SetLabel(const std::string& label, Range range) { // We do not have the ability to name ranges. Just name the whole thing. return SetLabel(label); diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.h b/impeller/renderer/backend/vulkan/device_buffer_vk.h index 686cb2ec72e05..33182c52f31af 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.h +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.h @@ -66,6 +66,9 @@ class DeviceBufferVK final : public DeviceBuffer, // |DeviceBuffer| bool SetLabel(const std::string& label, Range range) override; + // |DeviceBuffer| + void Flush(std::optional range) const override; + DeviceBufferVK(const DeviceBufferVK&) = delete; DeviceBufferVK& operator=(const DeviceBufferVK&) = delete; From 88d7b953fb8b9af9737472b4071c55a70e8e9a3d Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 4 Jan 2024 20:09:05 -0800 Subject: [PATCH 04/21] ++ --- impeller/renderer/compute_pass.cc | 11 ++- impeller/renderer/host_buffer_unittests.cc | 106 +++++++++------------ impeller/renderer/render_pass.cc | 15 +-- impeller/renderer/render_pass.h | 3 +- 4 files changed, 57 insertions(+), 78 deletions(-) diff --git a/impeller/renderer/compute_pass.cc b/impeller/renderer/compute_pass.cc index 0044231f39070..1d0987d81d289 100644 --- a/impeller/renderer/compute_pass.cc +++ b/impeller/renderer/compute_pass.cc @@ -5,16 +5,18 @@ #include "impeller/renderer/compute_pass.h" #include -#include "impeller/base/strings.h" +#include "fml/logging.h" #include "impeller/base/validation.h" #include "impeller/core/host_buffer.h" namespace impeller { ComputePass::ComputePass(std::weak_ptr context) - : context_(std::move(context)), - transients_buffer_( - HostBuffer::Create(context_.lock()->GetResourceAllocator())) {} + : context_(std::move(context)) { + auto strong_context = context_.lock(); + FML_DCHECK(strong_context); + transients_buffer_ = strong_context->GetTransientsBuffer(); +} ComputePass::~ComputePass() = default; @@ -26,7 +28,6 @@ void ComputePass::SetLabel(const std::string& label) { if (label.empty()) { return; } - transients_buffer_->SetLabel(SPrintF("%s Transients", label.c_str())); OnSetLabel(label); } diff --git a/impeller/renderer/host_buffer_unittests.cc b/impeller/renderer/host_buffer_unittests.cc index 29b0b63d99424..0533b0355242c 100644 --- a/impeller/renderer/host_buffer_unittests.cc +++ b/impeller/renderer/host_buffer_unittests.cc @@ -8,72 +8,60 @@ namespace impeller { namespace testing { -// TEST(HostBufferTest, TestInitialization) { -// ASSERT_TRUE(HostBuffer::Create()); -// // Newly allocated buffers don't touch the heap till they have to. -// ASSERT_EQ(HostBuffer::Create()->GetLength(), 0u); -// ASSERT_EQ(HostBuffer::Create()->GetSize(), 0u); -// } +TEST(HostBufferTest, CanEmplace) { + struct Length2 { + uint8_t pad[2]; + }; + static_assert(sizeof(Length2) == 2u); -// TEST(HostBufferTest, CanEmplace) { -// struct Length2 { -// uint8_t pad[2]; -// }; -// static_assert(sizeof(Length2) == 2u); + auto buffer = HostBuffer::Create(std::make_shared()); -// auto buffer = HostBuffer::Create(); + for (size_t i = 0; i < 12500; i++) { + auto view = buffer->Emplace(Length2{}); + ASSERT_TRUE(view); + ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u)); + } +} -// for (size_t i = 0; i < 12500; i++) { -// auto view = buffer->Emplace(Length2{}); -// ASSERT_TRUE(view); -// ASSERT_EQ(buffer->GetLength(), (i + 1) * sizeof(Length2)); -// ASSERT_EQ(view.range, Range(i * sizeof(Length2), 2u)); -// } -// } +TEST(HostBufferTest, CanEmplaceWithAlignment) { + struct Length2 { + uint8_t pad[2]; + }; + static_assert(sizeof(Length2) == 2); + struct alignas(16) Align16 { + uint8_t pad[2]; + }; + static_assert(alignof(Align16) == 16); + static_assert(sizeof(Align16) == 16); -// TEST(HostBufferTest, CanEmplaceWithAlignment) { -// struct Length2 { -// uint8_t pad[2]; -// }; -// static_assert(sizeof(Length2) == 2); -// struct alignas(16) Align16 { -// uint8_t pad[2]; -// }; -// static_assert(alignof(Align16) == 16); -// static_assert(sizeof(Align16) == 16); + auto buffer = HostBuffer::Create(std::make_shared()); + ASSERT_TRUE(buffer); -// auto buffer = HostBuffer::Create(); -// ASSERT_TRUE(buffer); + { + auto view = buffer->Emplace(Length2{}); + ASSERT_TRUE(view); + ASSERT_EQ(view.range, Range(0u, 2u)); + } -// { -// auto view = buffer->Emplace(Length2{}); -// ASSERT_TRUE(view); -// ASSERT_EQ(buffer->GetLength(), 2u); -// ASSERT_EQ(view.range, Range(0u, 2u)); -// } + { + auto view = buffer->Emplace(Align16{}); + ASSERT_TRUE(view); + ASSERT_EQ(view.range.offset, 16u); + ASSERT_EQ(view.range.length, 16u); + } + { + auto view = buffer->Emplace(Length2{}); + ASSERT_TRUE(view); + ASSERT_EQ(view.range, Range(32u, 2u)); + } -// { -// auto view = buffer->Emplace(Align16{}); -// ASSERT_TRUE(view); -// ASSERT_EQ(view.range.offset, 16u); -// ASSERT_EQ(view.range.length, 16u); -// ASSERT_EQ(buffer->GetLength(), 32u); -// } -// { -// auto view = buffer->Emplace(Length2{}); -// ASSERT_TRUE(view); -// ASSERT_EQ(buffer->GetLength(), 34u); -// ASSERT_EQ(view.range, Range(32u, 2u)); -// } - -// { -// auto view = buffer->Emplace(Align16{}); -// ASSERT_TRUE(view); -// ASSERT_EQ(view.range.offset, 48u); -// ASSERT_EQ(view.range.length, 16u); -// ASSERT_EQ(buffer->GetLength(), 64u); -// } -// } + { + auto view = buffer->Emplace(Align16{}); + ASSERT_TRUE(view); + ASSERT_EQ(view.range.offset, 48u); + ASSERT_EQ(view.range.length, 16u); + } +} } // namespace testing } // namespace impeller diff --git a/impeller/renderer/render_pass.cc b/impeller/renderer/render_pass.cc index aedac9e365f96..1771763c74d57 100644 --- a/impeller/renderer/render_pass.cc +++ b/impeller/renderer/render_pass.cc @@ -3,7 +3,6 @@ // found in the LICENSE file. #include "impeller/renderer/render_pass.h" -#include "impeller/core/host_buffer.h" namespace impeller { @@ -14,20 +13,13 @@ RenderPass::RenderPass(std::weak_ptr context, pixel_format_(target.GetRenderTargetPixelFormat()), has_stencil_attachment_(target.GetStencilAttachment().has_value()), render_target_size_(target.GetRenderTargetSize()), - render_target_(target), - transients_buffer_() { + render_target_(target) { auto strong_context = context_.lock(); FML_DCHECK(strong_context); - transients_buffer_ = - HostBuffer::Create(strong_context->GetResourceAllocator()); + transients_buffer_ = strong_context->GetTransientsBuffer(); } -RenderPass::~RenderPass() { - // auto strong_context = context_.lock(); - // if (strong_context) { - // strong_context->GetHostBufferPool().Recycle(transients_buffer_); - // } -} +RenderPass::~RenderPass() {} SampleCount RenderPass::GetSampleCount() const { return sample_count_; @@ -53,7 +45,6 @@ void RenderPass::SetLabel(std::string label) { if (label.empty()) { return; } - transients_buffer_->SetLabel(SPrintF("%s Transients", label.c_str())); OnSetLabel(std::move(label)); } diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index b0c543b06b407..94d8d0ea3150f 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -48,8 +48,7 @@ class RenderPass { } HostBuffer& GetTransientsBuffer() { - // Hack. - return *GetContext().lock()->GetTransientsBuffer(); + return *transients_buffer_; } //---------------------------------------------------------------------------- From 9ddcacdb11dcfe97d9a1fc92f8ab26789bd21a8a Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 4 Jan 2024 20:09:33 -0800 Subject: [PATCH 05/21] ++ --- impeller/renderer/render_pass.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index 94d8d0ea3150f..f9c99155d7562 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -47,9 +47,7 @@ class RenderPass { commands_.reserve(command_count); } - HostBuffer& GetTransientsBuffer() { - return *transients_buffer_; - } + HostBuffer& GetTransientsBuffer() { return *transients_buffer_; } //---------------------------------------------------------------------------- /// @brief Record a command for subsequent encoding to the underlying From 9f896fb85b7bf929db54a1854f7855ddd8e32311 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 8 Jan 2024 14:17:23 -0800 Subject: [PATCH 06/21] oofta --- impeller/aiks/testing/context_mock.h | 5 - impeller/entity/contents/atlas_contents.cc | 6 +- .../entity/contents/checkerboard_contents.cc | 2 +- impeller/entity/contents/clip_contents.cc | 12 +- .../contents/conical_gradient_contents.cc | 14 ++- impeller/entity/contents/content_context.cc | 3 +- impeller/entity/contents/content_context.h | 8 ++ .../contents/filters/blend_filter_contents.cc | 8 +- .../border_mask_blur_filter_contents.cc | 2 +- .../filters/color_matrix_filter_contents.cc | 2 +- ...rectional_gaussian_blur_filter_contents.cc | 2 +- .../filters/gaussian_blur_filter_contents.cc | 4 +- .../filters/linear_to_srgb_filter_contents.cc | 2 +- .../filters/morphology_filter_contents.cc | 2 +- .../filters/srgb_to_linear_filter_contents.cc | 2 +- .../filters/yuv_to_rgb_filter_contents.cc | 2 +- .../contents/framebuffer_blend_contents.cc | 2 +- .../contents/linear_gradient_contents.cc | 14 ++- .../contents/radial_gradient_contents.cc | 14 ++- .../contents/runtime_effect_contents.cc | 5 +- .../entity/contents/solid_color_contents.cc | 3 +- .../contents/solid_rrect_blur_contents.cc | 9 +- .../contents/sweep_gradient_contents.cc | 14 ++- impeller/entity/contents/text_contents.cc | 7 +- impeller/entity/contents/texture_contents.cc | 2 +- .../entity/contents/tiled_texture_contents.cc | 2 +- impeller/entity/contents/vertices_contents.cc | 4 +- impeller/entity/entity_pass.cc | 5 +- impeller/entity/entity_unittests.cc | 6 +- impeller/entity/geometry/circle_geometry.cc | 5 +- impeller/entity/geometry/cover_geometry.cc | 2 +- impeller/entity/geometry/ellipse_geometry.cc | 2 + .../entity/geometry/fill_path_geometry.cc | 6 +- impeller/entity/geometry/geometry.cc | 9 +- impeller/entity/geometry/geometry.h | 2 + impeller/entity/geometry/line_geometry.cc | 9 +- .../entity/geometry/point_field_geometry.cc | 6 +- impeller/entity/geometry/rect_geometry.cc | 2 +- .../entity/geometry/round_rect_geometry.cc | 4 +- .../entity/geometry/stroke_path_geometry.cc | 4 +- .../playground/imgui/imgui_impl_impeller.cc | 8 +- impeller/playground/playground.cc | 1 - .../renderer/backend/gles/context_gles.cc | 7 -- impeller/renderer/backend/gles/context_gles.h | 3 - impeller/renderer/backend/metal/context_mtl.h | 3 - .../renderer/backend/metal/context_mtl.mm | 7 -- .../backend/vulkan/command_encoder_vk.cc | 12 +- .../backend/vulkan/command_encoder_vk.h | 3 +- .../backend/vulkan/command_pool_vk.cc | 7 +- .../renderer/backend/vulkan/command_pool_vk.h | 4 +- .../renderer/backend/vulkan/context_vk.cc | 6 - impeller/renderer/backend/vulkan/context_vk.h | 3 - .../backend/vulkan/surface_context_vk.cc | 6 - .../backend/vulkan/surface_context_vk.h | 3 - impeller/renderer/compute_pass.cc | 11 +- impeller/renderer/compute_pass.h | 2 - .../renderer/compute_subgroup_unittests.cc | 33 +++--- impeller/renderer/compute_tessellator.cc | 15 ++- impeller/renderer/compute_tessellator.h | 1 + impeller/renderer/compute_unittests.cc | 42 +++---- impeller/renderer/context.h | 2 - impeller/renderer/host_buffer_unittests.cc | 11 +- impeller/renderer/render_pass.cc | 6 +- impeller/renderer/render_pass.h | 3 - impeller/renderer/renderer_unittests.cc | 106 +++++++++--------- impeller/renderer/testing/mocks.h | 5 - impeller/scene/scene_context.cc | 3 +- impeller/scene/scene_context.h | 4 + impeller/scene/scene_encoder.cc | 2 +- 69 files changed, 265 insertions(+), 268 deletions(-) diff --git a/impeller/aiks/testing/context_mock.h b/impeller/aiks/testing/context_mock.h index 72c0abee77fa9..b2d9138503fbb 100644 --- a/impeller/aiks/testing/context_mock.h +++ b/impeller/aiks/testing/context_mock.h @@ -111,11 +111,6 @@ class ContextMock : public Context { (), (const, override)); - MOCK_METHOD(const std::shared_ptr, - GetTransientsBuffer, - (), - (const, override)); - MOCK_METHOD(void, Shutdown, (), (override)); }; diff --git a/impeller/entity/contents/atlas_contents.cc b/impeller/entity/contents/atlas_contents.cc index 8e2bb80d07d71..367966fa53eae 100644 --- a/impeller/entity/contents/atlas_contents.cc +++ b/impeller/entity/contents/atlas_contents.cc @@ -223,7 +223,7 @@ bool AtlasContents::Render(const ContentContext& renderer, VertexBufferBuilder vtx_builder; vtx_builder.Reserve(texture_coords_.size() * 6); const auto texture_size = texture_->GetSize(); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); for (size_t i = 0; i < texture_coords_.size(); i++) { auto sample_rect = texture_coords_[i]; @@ -406,7 +406,7 @@ bool AtlasTextureContents::Render(const ContentContext& renderer, Command cmd; DEBUG_COMMAND_INFO(cmd, "AtlasTexture"); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * @@ -494,7 +494,7 @@ bool AtlasColorContents::Render(const ContentContext& renderer, Command cmd; DEBUG_COMMAND_INFO(cmd, "AtlasColors"); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * diff --git a/impeller/entity/contents/checkerboard_contents.cc b/impeller/entity/contents/checkerboard_contents.cc index f58bb38850891..91f6959bf6d6f 100644 --- a/impeller/entity/contents/checkerboard_contents.cc +++ b/impeller/entity/contents/checkerboard_contents.cc @@ -21,7 +21,7 @@ CheckerboardContents::~CheckerboardContents() = default; bool CheckerboardContents::Render(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); using VS = CheckerboardPipeline::VertexShader; using FS = CheckerboardPipeline::FragmentShader; diff --git a/impeller/entity/contents/clip_contents.cc b/impeller/entity/contents/clip_contents.cc index 514d42f5f062f..aed4f9ec5300d 100644 --- a/impeller/entity/contents/clip_contents.cc +++ b/impeller/entity/contents/clip_contents.cc @@ -96,11 +96,12 @@ bool ClipContents::Render(const ContentContext& renderer, auto vertices = VertexBufferBuilder{} .AddVertices({{points[0]}, {points[1]}, {points[2]}, {points[3]}}) - .CreateVertexBuffer(pass.GetTransientsBuffer()); + .CreateVertexBuffer(renderer.GetTransientsBuffer()); cmd.BindVertices(std::move(vertices)); info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(info)); options.primitive_type = PrimitiveType::kTriangleStrip; cmd.pipeline = renderer.GetClipPipeline(options); @@ -128,7 +129,7 @@ bool ClipContents::Render(const ContentContext& renderer, cmd.BindVertices(std::move(geometry_result.vertex_buffer)); info.mvp = geometry_result.transform; - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info)); + VS::BindFrameInfo(cmd, renderer.GetTransientsBuffer().EmplaceUniform(info)); pass.AddCommand(std::move(cmd)); return true; @@ -197,11 +198,12 @@ bool ClipRestoreContents::Render(const ContentContext& renderer, {Point(ltrb[0], ltrb[3])}, {Point(ltrb[2], ltrb[3])}, }); - cmd.BindVertices(vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + cmd.BindVertices( + vtx_builder.CreateVertexBuffer(renderer.GetTransientsBuffer())); VS::FrameInfo info; info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(info)); + VS::BindFrameInfo(cmd, renderer.GetTransientsBuffer().EmplaceUniform(info)); pass.AddCommand(std::move(cmd)); return true; diff --git a/impeller/entity/contents/conical_gradient_contents.cc b/impeller/entity/contents/conical_gradient_contents.cc index fbfe31a9c1174..3de036c7b8aa7 100644 --- a/impeller/entity/contents/conical_gradient_contents.cc +++ b/impeller/entity/contents/conical_gradient_contents.cc @@ -80,7 +80,7 @@ bool ConicalGradientContents::RenderSSBO(const ContentContext& renderer, frag_info.focus_radius = 0.0; } - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto colors = CreateGradientColors(colors_, stops_); frag_info.colors_length = colors.size(); @@ -108,9 +108,11 @@ bool ConicalGradientContents::RenderSSBO(const ContentContext& renderer, cmd.pipeline = renderer.GetConicalGradientSSBOFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); FS::BindColorData(cmd, color_buffer); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; @@ -174,14 +176,16 @@ bool ConicalGradientContents::RenderTexture(const ContentContext& renderer, cmd.pipeline = renderer.GetConicalGradientFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); SamplerDescriptor sampler_desc; sampler_desc.min_filter = MinMagFilter::kLinear; sampler_desc.mag_filter = MinMagFilter::kLinear; FS::BindTextureSampler( cmd, gradient_texture, renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 886bc54e95225..25544a53bb34a 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -184,7 +184,8 @@ ContentContext::ContentContext( render_target_cache_(render_target_allocator == nullptr ? std::make_shared( context_->GetResourceAllocator()) - : std::move(render_target_allocator)) { + : std::move(render_target_allocator)), + host_buffer_(HostBuffer::Create(context_->GetResourceAllocator())) { if (!context_ || !context_->IsValid()) { return; } diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index 98dc447f009fb..b245228fc8dd3 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -15,6 +15,7 @@ #include "flutter/fml/status_or.h" #include "impeller/base/validation.h" #include "impeller/core/formats.h" +#include "impeller/core/host_buffer.h" #include "impeller/entity/entity.h" #include "impeller/renderer/capabilities.h" #include "impeller/renderer/pipeline.h" @@ -713,6 +714,12 @@ class ContentContext { return render_target_cache_; } + /// @brief Retrieve the currnent host buffer for transient storage. + /// + /// This is only safe to use from the raster threads. Other threads should + /// allocate their own device buffers. + HostBuffer& GetTransientsBuffer() const { return *host_buffer_; } + private: std::shared_ptr context_; std::shared_ptr lazy_glyph_atlas_; @@ -922,6 +929,7 @@ class ContentContext { std::shared_ptr scene_context_; #endif // IMPELLER_ENABLE_3D std::shared_ptr render_target_cache_; + std::shared_ptr host_buffer_; bool wireframe_ = false; ContentContext(const ContentContext&) = delete; diff --git a/impeller/entity/contents/filters/blend_filter_contents.cc b/impeller/entity/contents/filters/blend_filter_contents.cc index cb56c3f1eafac..20acc95bb8e43 100644 --- a/impeller/entity/contents/filters/blend_filter_contents.cc +++ b/impeller/entity/contents/filters/blend_filter_contents.cc @@ -148,7 +148,7 @@ static std::optional AdvancedBlend( ContentContext::SubpassCallback callback = [&](const ContentContext& renderer, RenderPass& pass) { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto size = pass.GetRenderTargetSize(); VertexBufferBuilder vtx_builder; @@ -266,7 +266,7 @@ std::optional BlendFilterContents::CreateForegroundAdvancedBlend( using VS = BlendScreenPipeline::VertexShader; using FS = BlendScreenPipeline::FragmentShader; - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(coverage); if (!maybe_dst_uvs.has_value()) { @@ -436,7 +436,7 @@ std::optional BlendFilterContents::CreateForegroundPorterDuffBlend( using VS = PorterDuffBlendPipeline::VertexShader; using FS = PorterDuffBlendPipeline::FragmentShader; - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto maybe_dst_uvs = dst_snapshot->GetCoverageUVs(coverage); if (!maybe_dst_uvs.has_value()) { @@ -554,7 +554,7 @@ static std::optional PipelineBlend( ContentContext::SubpassCallback callback = [&](const ContentContext& renderer, RenderPass& pass) { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); Command cmd; DEBUG_COMMAND_INFO(cmd, SPrintF("Pipeline Blend Filter (%s)", diff --git a/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc b/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc index 207b079d29ef7..f8c379fa9355c 100644 --- a/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/border_mask_blur_filter_contents.cc @@ -90,7 +90,7 @@ std::optional BorderMaskBlurFilterContents::RenderFilter( outer_blur_factor = outer_blur_factor_, sigma]( const ContentContext& renderer, const Entity& entity, RenderPass& pass) -> bool { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); VertexBufferBuilder vtx_builder; auto origin = coverage.GetOrigin(); diff --git a/impeller/entity/contents/filters/color_matrix_filter_contents.cc b/impeller/entity/contents/filters/color_matrix_filter_contents.cc index 2ce6526169f3e..2d475a7176831 100644 --- a/impeller/entity/contents/filters/color_matrix_filter_contents.cc +++ b/impeller/entity/contents/filters/color_matrix_filter_contents.cc @@ -73,7 +73,7 @@ std::optional ColorMatrixFilterContents::RenderFilter( {Point(0, 1)}, {Point(1, 1)}, }); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); cmd.BindVertices(vtx_builder.CreateVertexBuffer(host_buffer)); VS::FrameInfo frame_info; diff --git a/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc index 5760d7ac250d2..211cb68a0d29e 100644 --- a/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents.cc @@ -158,7 +158,7 @@ std::optional DirectionalGaussianBlurFilterContents::RenderFilter( ContentContext::SubpassCallback subpass_callback = [&](const ContentContext& renderer, RenderPass& pass) { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); VertexBufferBuilder vtx_builder; vtx_builder.AddVertices({ diff --git a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc index 453c37dd4b28b..ca7deff571f19 100644 --- a/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc +++ b/impeller/entity/contents/filters/gaussian_blur_filter_contents.cc @@ -74,7 +74,7 @@ fml::StatusOr MakeDownsampleSubpass( Entity::TileMode tile_mode) { ContentContext::SubpassCallback subpass_callback = [&](const ContentContext& renderer, RenderPass& pass) { - HostBuffer& host_buffer = pass.GetTransientsBuffer(); + HostBuffer& host_buffer = renderer.GetTransientsBuffer(); Command cmd; DEBUG_COMMAND_INFO(cmd, "Gaussian blur downsample"); @@ -137,7 +137,7 @@ fml::StatusOr MakeBlurSubpass( .mvp = Matrix::MakeOrthographic(ISize(1, 1)), .texture_sampler_y_coord_scale = 1.0}; - HostBuffer& host_buffer = pass.GetTransientsBuffer(); + HostBuffer& host_buffer = renderer.GetTransientsBuffer(); Command cmd; ContentContextOptions options = OptionsFromPass(pass); diff --git a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc index 2bad955bf0416..85df4fde3da6d 100644 --- a/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc +++ b/impeller/entity/contents/filters/linear_to_srgb_filter_contents.cc @@ -64,7 +64,7 @@ std::optional LinearToSrgbFilterContents::RenderFilter( {Point(1, 1)}, }); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); cmd.BindVertices(vtx_builder.CreateVertexBuffer(host_buffer)); VS::FrameInfo frame_info; diff --git a/impeller/entity/contents/filters/morphology_filter_contents.cc b/impeller/entity/contents/filters/morphology_filter_contents.cc index f94156e8c0dc6..5d5db0524feb7 100644 --- a/impeller/entity/contents/filters/morphology_filter_contents.cc +++ b/impeller/entity/contents/filters/morphology_filter_contents.cc @@ -76,7 +76,7 @@ std::optional DirectionalMorphologyFilterContents::RenderFilter( ContentContext::SubpassCallback callback = [&](const ContentContext& renderer, RenderPass& pass) { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); VertexBufferBuilder vtx_builder; vtx_builder.AddVertices({ diff --git a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc index 4488b5f21b5f7..51e1a62dc3f79 100644 --- a/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc +++ b/impeller/entity/contents/filters/srgb_to_linear_filter_contents.cc @@ -64,7 +64,7 @@ std::optional SrgbToLinearFilterContents::RenderFilter( {Point(1, 1)}, }); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); cmd.BindVertices(vtx_builder.CreateVertexBuffer(host_buffer)); VS::FrameInfo frame_info; diff --git a/impeller/entity/contents/filters/yuv_to_rgb_filter_contents.cc b/impeller/entity/contents/filters/yuv_to_rgb_filter_contents.cc index 99c5ac545ee4b..1ad3a9c0650fd 100644 --- a/impeller/entity/contents/filters/yuv_to_rgb_filter_contents.cc +++ b/impeller/entity/contents/filters/yuv_to_rgb_filter_contents.cc @@ -92,7 +92,7 @@ std::optional YUVToRGBFilterContents::RenderFilter( {Point(1, 1)}, }); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); cmd.BindVertices(vtx_builder.CreateVertexBuffer(host_buffer)); VS::FrameInfo frame_info; diff --git a/impeller/entity/contents/framebuffer_blend_contents.cc b/impeller/entity/contents/framebuffer_blend_contents.cc index 838ce3d679980..462e3ad7f9910 100644 --- a/impeller/entity/contents/framebuffer_blend_contents.cc +++ b/impeller/entity/contents/framebuffer_blend_contents.cc @@ -39,7 +39,7 @@ bool FramebufferBlendContents::Render(const ContentContext& renderer, using VS = FramebufferBlendScreenPipeline::VertexShader; using FS = FramebufferBlendScreenPipeline::FragmentShader; - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto src_snapshot = child_contents_->RenderToSnapshot( renderer, // renderer diff --git a/impeller/entity/contents/linear_gradient_contents.cc b/impeller/entity/contents/linear_gradient_contents.cc index d96525e7a0c0c..7d08656e1c627 100644 --- a/impeller/entity/contents/linear_gradient_contents.cc +++ b/impeller/entity/contents/linear_gradient_contents.cc @@ -108,14 +108,16 @@ bool LinearGradientContents::RenderTexture(const ContentContext& renderer, cmd.pipeline = renderer.GetLinearGradientFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); SamplerDescriptor sampler_desc; sampler_desc.min_filter = MinMagFilter::kLinear; sampler_desc.mag_filter = MinMagFilter::kLinear; FS::BindTextureSampler( cmd, std::move(gradient_texture), renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; @@ -142,7 +144,7 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, frag_info.decal_border_color = decal_border_color_; frag_info.alpha = GetOpacityFactor(); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto colors = CreateGradientColors(colors_, stops_); frag_info.colors_length = colors.size(); @@ -170,9 +172,11 @@ bool LinearGradientContents::RenderSSBO(const ContentContext& renderer, cmd.pipeline = renderer.GetLinearGradientSSBOFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); FS::BindColorData(cmd, color_buffer); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; diff --git a/impeller/entity/contents/radial_gradient_contents.cc b/impeller/entity/contents/radial_gradient_contents.cc index 0eee4d448e8bb..ea11dcdae403a 100644 --- a/impeller/entity/contents/radial_gradient_contents.cc +++ b/impeller/entity/contents/radial_gradient_contents.cc @@ -79,7 +79,7 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer, frag_info.decal_border_color = decal_border_color_; frag_info.alpha = GetOpacityFactor(); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto colors = CreateGradientColors(colors_, stops_); frag_info.colors_length = colors.size(); @@ -107,9 +107,11 @@ bool RadialGradientContents::RenderSSBO(const ContentContext& renderer, cmd.pipeline = renderer.GetRadialGradientSSBOFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); FS::BindColorData(cmd, color_buffer); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; @@ -166,14 +168,16 @@ bool RadialGradientContents::RenderTexture(const ContentContext& renderer, cmd.pipeline = renderer.GetRadialGradientFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); SamplerDescriptor sampler_desc; sampler_desc.min_filter = MinMagFilter::kLinear; sampler_desc.mag_filter = MinMagFilter::kLinear; FS::BindTextureSampler( cmd, gradient_texture, renderer.GetContext()->GetSamplerLibrary()->GetSampler(sampler_desc)); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; diff --git a/impeller/entity/contents/runtime_effect_contents.cc b/impeller/entity/contents/runtime_effect_contents.cc index a2a5244b6b038..35d1274a16c6d 100644 --- a/impeller/entity/contents/runtime_effect_contents.cc +++ b/impeller/entity/contents/runtime_effect_contents.cc @@ -200,7 +200,8 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, VS::FrameInfo frame_info; frame_info.mvp = geometry_result.transform; - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); //-------------------------------------------------------------------------- /// Fragment stage uniforms. @@ -229,7 +230,7 @@ bool RuntimeEffectContents::Render(const ContentContext& renderer, case kFloat: { size_t alignment = std::max(uniform.bit_width / 8, DefaultUniformAlignment()); - auto buffer_view = pass.GetTransientsBuffer().Emplace( + auto buffer_view = renderer.GetTransientsBuffer().Emplace( uniform_data_->data() + buffer_offset, uniform.GetSize(), alignment); diff --git a/impeller/entity/contents/solid_color_contents.cc b/impeller/entity/contents/solid_color_contents.cc index 323da22797e7c..2683bf07e04bd 100644 --- a/impeller/entity/contents/solid_color_contents.cc +++ b/impeller/entity/contents/solid_color_contents.cc @@ -72,7 +72,8 @@ bool SolidColorContents::Render(const ContentContext& renderer, VS::FrameInfo frame_info; frame_info.mvp = capture.AddMatrix("Transform", geometry_result.transform); frame_info.color = capture.AddColor("Color", GetColor()).Premultiply(); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; diff --git a/impeller/entity/contents/solid_rrect_blur_contents.cc b/impeller/entity/contents/solid_rrect_blur_contents.cc index d045c42be2dd2..e6d3fa5ca8488 100644 --- a/impeller/entity/contents/solid_rrect_blur_contents.cc +++ b/impeller/entity/contents/solid_rrect_blur_contents.cc @@ -106,13 +106,15 @@ bool SolidRRectBlurContents::Render(const ContentContext& renderer, cmd.pipeline = renderer.GetRRectBlurPipeline(opts); cmd.stencil_reference = entity.GetClipDepth(); - cmd.BindVertices(vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + cmd.BindVertices( + vtx_builder.CreateVertexBuffer(renderer.GetTransientsBuffer())); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * entity.GetTransform() * Matrix::MakeTranslation(positive_rect.GetOrigin()); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); FS::FragInfo frag_info; frag_info.color = color; @@ -121,7 +123,8 @@ bool SolidRRectBlurContents::Render(const ContentContext& renderer, frag_info.corner_radius = std::min(corner_radius_, std::min(positive_rect.GetWidth() / 2.0f, positive_rect.GetHeight() / 2.0f)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); if (!pass.AddCommand(std::move(cmd))) { return false; diff --git a/impeller/entity/contents/sweep_gradient_contents.cc b/impeller/entity/contents/sweep_gradient_contents.cc index f9b22e3c12e0d..345045354dd0a 100644 --- a/impeller/entity/contents/sweep_gradient_contents.cc +++ b/impeller/entity/contents/sweep_gradient_contents.cc @@ -85,7 +85,7 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer, frag_info.decal_border_color = decal_border_color_; frag_info.alpha = GetOpacityFactor(); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto colors = CreateGradientColors(colors_, stops_); frag_info.colors_length = colors.size(); @@ -113,9 +113,11 @@ bool SweepGradientContents::RenderSSBO(const ContentContext& renderer, cmd.pipeline = renderer.GetSweepGradientSSBOFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); FS::BindColorData(cmd, color_buffer); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; @@ -173,8 +175,10 @@ bool SweepGradientContents::RenderTexture(const ContentContext& renderer, cmd.pipeline = renderer.GetSweepGradientFillPipeline(options); cmd.BindVertices(std::move(geometry_result.vertex_buffer)); - FS::BindFragInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frag_info)); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + FS::BindFragInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); SamplerDescriptor sampler_desc; sampler_desc.min_filter = MinMagFilter::kLinear; sampler_desc.mag_filter = MinMagFilter::kLinear; diff --git a/impeller/entity/contents/text_contents.cc b/impeller/entity/contents/text_contents.cc index ba36f27497101..8fb515f221a24 100644 --- a/impeller/entity/contents/text_contents.cc +++ b/impeller/entity/contents/text_contents.cc @@ -119,14 +119,15 @@ bool TextContents::Render(const ContentContext& renderer, frame_info.entity_transform = entity.GetTransform(); frame_info.text_color = ToVector(color.Premultiply()); - VS::BindFrameInfo(cmd, pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (type == GlyphAtlas::Type::kColorBitmap) { using FSS = GlyphAtlasColorPipeline::FragmentShader; FSS::FragInfo frag_info; frag_info.use_text_color = force_text_color_ ? 1.0 : 0.0; FSS::BindFragInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frag_info)); + renderer.GetTransientsBuffer().EmplaceUniform(frag_info)); } SamplerDescriptor sampler_desc; @@ -162,7 +163,7 @@ bool TextContents::Render(const ContentContext& renderer, Point{0, 1}, Point{1, 0}, Point{0, 1}, Point{1, 1}}; - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); size_t vertex_count = 0; for (const auto& run : frame_->GetRuns()) { vertex_count += run.GetGlyphPositions().size(); diff --git a/impeller/entity/contents/texture_contents.cc b/impeller/entity/contents/texture_contents.cc index 1555ebe2272e4..5ba8ea7592c04 100644 --- a/impeller/entity/contents/texture_contents.cc +++ b/impeller/entity/contents/texture_contents.cc @@ -139,7 +139,7 @@ bool TextureContents::Render(const ContentContext& renderer, {destination_rect.GetRightBottom(), texture_coords.GetRightBottom()}, }); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc index 67bd941007354..ebf129fdb3478 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -131,7 +131,7 @@ bool TiledTextureContents::Render(const ContentContext& renderer, bool is_external_texture = texture_->GetTextureDescriptor().type == TextureType::kTextureExternalOES; - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto geometry_result = GetGeometry()->GetPositionUVBuffer( Rect::MakeSize(texture_size), GetInverseEffectTransform(), renderer, diff --git a/impeller/entity/contents/vertices_contents.cc b/impeller/entity/contents/vertices_contents.cc index 47fdc1e9d1837..63bfbab3eb32c 100644 --- a/impeller/entity/contents/vertices_contents.cc +++ b/impeller/entity/contents/vertices_contents.cc @@ -122,7 +122,7 @@ bool VerticesUVContents::Render(const ContentContext& renderer, Command cmd; DEBUG_COMMAND_INFO(cmd, "VerticesUV"); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto geometry = parent_.GetGeometry(); auto coverage = src_contents->GetCoverage(Entity{}); @@ -176,7 +176,7 @@ bool VerticesColorContents::Render(const ContentContext& renderer, Command cmd; DEBUG_COMMAND_INFO(cmd, "VerticesColors"); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto geometry = parent_.GetGeometry(); auto geometry_result = diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 1cc56baeb9fff..47c2dbae151c9 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -307,7 +307,10 @@ bool EntityPass::Render(ContentContext& renderer, fml::ScopedCleanupClosure reset_state([&renderer]() { renderer.GetLazyGlyphAtlas()->ResetTextFrames(); renderer.GetRenderTargetCache()->End(); - renderer.GetContext()->GetTransientsBuffer()->Reset(); + renderer.GetTransientsBuffer().Reset(); +#if IMPELLER_ENABLE_3D + renderer.GetSceneContext().GetTransientsBuffer().Reset(); +#endif // IMPELLER_ENABLE_3D }); auto root_render_target = render_target; diff --git a/impeller/entity/entity_unittests.cc b/impeller/entity/entity_unittests.cc index 91d6b6a2735c8..96d7a4c58bfca 100644 --- a/impeller/entity/entity_unittests.cc +++ b/impeller/entity/entity_unittests.cc @@ -880,14 +880,14 @@ TEST_P(EntityTest, BlendingModeOptions) { options.primitive_type = PrimitiveType::kTriangle; cmd.pipeline = context.GetSolidFillPipeline(options); cmd.BindVertices( - vtx_builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + vtx_builder.CreateVertexBuffer(context.GetTransientsBuffer())); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix; frame_info.color = color.Premultiply(); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo( + cmd, context.GetTransientsBuffer().EmplaceUniform(frame_info)); return pass.AddCommand(std::move(cmd)); }; diff --git a/impeller/entity/geometry/circle_geometry.cc b/impeller/entity/geometry/circle_geometry.cc index 908485a811924..bd9aa8c796378 100644 --- a/impeller/entity/geometry/circle_geometry.cc +++ b/impeller/entity/geometry/circle_geometry.cc @@ -41,7 +41,7 @@ GeometryResult CircleGeometry::GetPositionBuffer(const ContentContext& renderer, auto generator = tessellator->StrokedCircle(transform, center_, radius_, half_width); - return ComputePositionGeometry(generator, entity, pass); + return ComputePositionGeometry(renderer, generator, entity, pass); } // |Geometry| @@ -65,7 +65,8 @@ GeometryResult CircleGeometry::GetPositionUVBuffer( auto generator = tessellator->StrokedCircle(transform, center_, radius_, half_width); - return ComputePositionUVGeometry(generator, uv_transform, entity, pass); + return ComputePositionUVGeometry(renderer, generator, uv_transform, entity, + pass); } GeometryVertexType CircleGeometry::GetVertexType() const { diff --git a/impeller/entity/geometry/cover_geometry.cc b/impeller/entity/geometry/cover_geometry.cc index 0fb6e44d45242..39ef35cbfc270 100644 --- a/impeller/entity/geometry/cover_geometry.cc +++ b/impeller/entity/geometry/cover_geometry.cc @@ -15,7 +15,7 @@ GeometryResult CoverGeometry::GetPositionBuffer(const ContentContext& renderer, RenderPass& pass) const { auto rect = Rect::MakeSize(pass.GetRenderTargetSize()); constexpr uint16_t kRectIndicies[4] = {0, 1, 2, 3}; - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); return GeometryResult{ .type = PrimitiveType::kTriangleStrip, .vertex_buffer = diff --git a/impeller/entity/geometry/ellipse_geometry.cc b/impeller/entity/geometry/ellipse_geometry.cc index ef4438e6ede67..b0d21324b437e 100644 --- a/impeller/entity/geometry/ellipse_geometry.cc +++ b/impeller/entity/geometry/ellipse_geometry.cc @@ -17,6 +17,7 @@ GeometryResult EllipseGeometry::GetPositionBuffer( const Entity& entity, RenderPass& pass) const { return ComputePositionGeometry( + renderer, renderer.GetTessellator()->FilledEllipse(entity.GetTransform(), bounds_), entity, pass); } @@ -29,6 +30,7 @@ GeometryResult EllipseGeometry::GetPositionUVBuffer( const Entity& entity, RenderPass& pass) const { return ComputePositionUVGeometry( + renderer, renderer.GetTessellator()->FilledEllipse(entity.GetTransform(), bounds_), texture_coverage.GetNormalizingTransform() * effect_transform, entity, pass); diff --git a/impeller/entity/geometry/fill_path_geometry.cc b/impeller/entity/geometry/fill_path_geometry.cc index 054a66b9f0eba..1b17225a99b44 100644 --- a/impeller/entity/geometry/fill_path_geometry.cc +++ b/impeller/entity/geometry/fill_path_geometry.cc @@ -14,7 +14,7 @@ GeometryResult FillPathGeometry::GetPositionBuffer( const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); VertexBuffer vertex_buffer; if (path_.GetFillType() == FillType::kNonZero && // @@ -96,7 +96,7 @@ GeometryResult FillPathGeometry::GetPositionUVBuffer( return GeometryResult{ .type = PrimitiveType::kTriangleStrip, .vertex_buffer = - vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer()), + vertex_builder.CreateVertexBuffer(renderer.GetTransientsBuffer()), .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * entity.GetTransform(), .prevent_overdraw = false, @@ -130,7 +130,7 @@ GeometryResult FillPathGeometry::GetPositionUVBuffer( return GeometryResult{ .type = PrimitiveType::kTriangle, .vertex_buffer = - vertex_builder.CreateVertexBuffer(pass.GetTransientsBuffer()), + vertex_builder.CreateVertexBuffer(renderer.GetTransientsBuffer()), .transform = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * entity.GetTransform(), .prevent_overdraw = false, diff --git a/impeller/entity/geometry/geometry.cc b/impeller/entity/geometry/geometry.cc index a9855033e2769..23e65e1181baa 100644 --- a/impeller/entity/geometry/geometry.cc +++ b/impeller/entity/geometry/geometry.cc @@ -7,6 +7,7 @@ #include #include +#include "impeller/entity/contents/content_context.h" #include "impeller/entity/geometry/circle_geometry.h" #include "impeller/entity/geometry/cover_geometry.h" #include "impeller/entity/geometry/ellipse_geometry.h" @@ -21,6 +22,7 @@ namespace impeller { GeometryResult Geometry::ComputePositionGeometry( + const ContentContext& renderer, const Tessellator::VertexGenerator& generator, const Entity& entity, RenderPass& pass) { @@ -32,7 +34,7 @@ GeometryResult Geometry::ComputePositionGeometry( .type = generator.GetTriangleType(), .vertex_buffer = { - .vertex_buffer = pass.GetTransientsBuffer().Emplace( + .vertex_buffer = renderer.GetTransientsBuffer().Emplace( count * sizeof(VT), alignof(VT), [&generator](uint8_t* buffer) { auto vertices = reinterpret_cast(buffer); @@ -54,6 +56,7 @@ GeometryResult Geometry::ComputePositionGeometry( } GeometryResult Geometry::ComputePositionUVGeometry( + const ContentContext& renderer, const Tessellator::VertexGenerator& generator, const Matrix& uv_transform, const Entity& entity, @@ -66,7 +69,7 @@ GeometryResult Geometry::ComputePositionUVGeometry( .type = generator.GetTriangleType(), .vertex_buffer = { - .vertex_buffer = pass.GetTransientsBuffer().Emplace( + .vertex_buffer = renderer.GetTransientsBuffer().Emplace( count * sizeof(VT), alignof(VT), [&generator, &uv_transform](uint8_t* buffer) { auto vertices = reinterpret_cast(buffer); @@ -116,7 +119,7 @@ GeometryResult ComputeUVGeometryForRect(Rect source_rect, const ContentContext& renderer, const Entity& entity, RenderPass& pass) { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto uv_transform = texture_coverage.GetNormalizingTransform() * effect_transform; diff --git a/impeller/entity/geometry/geometry.h b/impeller/entity/geometry/geometry.h index a958f8e5aacaa..685820fe9ed6b 100644 --- a/impeller/entity/geometry/geometry.h +++ b/impeller/entity/geometry/geometry.h @@ -123,11 +123,13 @@ class Geometry { protected: static GeometryResult ComputePositionGeometry( + const ContentContext& renderer, const Tessellator::VertexGenerator& generator, const Entity& entity, RenderPass& pass); static GeometryResult ComputePositionUVGeometry( + const ContentContext& renderer, const Tessellator::VertexGenerator& generator, const Matrix& uv_transform, const Entity& entity, diff --git a/impeller/entity/geometry/line_geometry.cc b/impeller/entity/geometry/line_geometry.cc index d2a9bd5d496c0..54cc7948d5cc2 100644 --- a/impeller/entity/geometry/line_geometry.cc +++ b/impeller/entity/geometry/line_geometry.cc @@ -75,7 +75,7 @@ GeometryResult LineGeometry::GetPositionBuffer(const ContentContext& renderer, if (cap_ == Cap::kRound) { std::shared_ptr tessellator = renderer.GetTessellator(); auto generator = tessellator->RoundCapLine(transform, p0_, p1_, radius); - return ComputePositionGeometry(generator, entity, pass); + return ComputePositionGeometry(renderer, generator, entity, pass); } Point corners[4]; @@ -83,7 +83,7 @@ GeometryResult LineGeometry::GetPositionBuffer(const ContentContext& renderer, return kEmptyResult; } - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); size_t count = 4; BufferView vertex_buffer = host_buffer.Emplace( @@ -116,7 +116,7 @@ GeometryResult LineGeometry::GetPositionUVBuffer(Rect texture_coverage, const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); using VT = TextureFillVertexShader::PerVertexData; auto& transform = entity.GetTransform(); @@ -128,7 +128,8 @@ GeometryResult LineGeometry::GetPositionUVBuffer(Rect texture_coverage, if (cap_ == Cap::kRound) { std::shared_ptr tessellator = renderer.GetTessellator(); auto generator = tessellator->RoundCapLine(transform, p0_, p1_, radius); - return ComputePositionUVGeometry(generator, uv_transform, entity, pass); + return ComputePositionUVGeometry(renderer, generator, uv_transform, entity, + pass); } Point corners[4]; diff --git a/impeller/entity/geometry/point_field_geometry.cc b/impeller/entity/geometry/point_field_geometry.cc index cd1c5791e9642..b8390d9b10a8f 100644 --- a/impeller/entity/geometry/point_field_geometry.cc +++ b/impeller/entity/geometry/point_field_geometry.cc @@ -26,7 +26,7 @@ GeometryResult PointFieldGeometry::GetPositionBuffer( return {}; } - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); return { .type = PrimitiveType::kTriangleStrip, .vertex_buffer = vtx_builder->CreateVertexBuffer(host_buffer), @@ -55,7 +55,7 @@ GeometryResult PointFieldGeometry::GetPositionUVBuffer( ComputeUVGeometryCPU(vtx_builder.value(), {0, 0}, texture_coverage.GetSize(), effect_transform); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); return { .type = PrimitiveType::kTriangleStrip, .vertex_buffer = uv_vtx_builder.CreateVertexBuffer(host_buffer), @@ -154,7 +154,7 @@ GeometryResult PointFieldGeometry::GetPositionBufferGPU( auto cmd_buffer = renderer.GetContext()->CreateCommandBuffer(); auto compute_pass = cmd_buffer->CreateComputePass(); - auto& host_buffer = compute_pass->GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto points_data = host_buffer.Emplace(points_.data(), points_.size() * sizeof(Point), diff --git a/impeller/entity/geometry/rect_geometry.cc b/impeller/entity/geometry/rect_geometry.cc index e0bdbb1ea4f7d..688793862e4d2 100644 --- a/impeller/entity/geometry/rect_geometry.cc +++ b/impeller/entity/geometry/rect_geometry.cc @@ -11,7 +11,7 @@ RectGeometry::RectGeometry(Rect rect) : rect_(rect) {} GeometryResult RectGeometry::GetPositionBuffer(const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); return GeometryResult{ .type = PrimitiveType::kTriangleStrip, .vertex_buffer = diff --git a/impeller/entity/geometry/round_rect_geometry.cc b/impeller/entity/geometry/round_rect_geometry.cc index b8f3883033049..28cf77d9798ec 100644 --- a/impeller/entity/geometry/round_rect_geometry.cc +++ b/impeller/entity/geometry/round_rect_geometry.cc @@ -17,7 +17,8 @@ GeometryResult RoundRectGeometry::GetPositionBuffer( const ContentContext& renderer, const Entity& entity, RenderPass& pass) const { - return ComputePositionGeometry(renderer.GetTessellator()->FilledRoundRect( + return ComputePositionGeometry(renderer, + renderer.GetTessellator()->FilledRoundRect( entity.GetTransform(), bounds_, radii_), entity, pass); } @@ -30,6 +31,7 @@ GeometryResult RoundRectGeometry::GetPositionUVBuffer( const Entity& entity, RenderPass& pass) const { return ComputePositionUVGeometry( + renderer, renderer.GetTessellator()->FilledRoundRect(entity.GetTransform(), bounds_, radii_), texture_coverage.GetNormalizingTransform() * effect_transform, entity, diff --git a/impeller/entity/geometry/stroke_path_geometry.cc b/impeller/entity/geometry/stroke_path_geometry.cc index 5d0b26d29ffa6..1b1875787ea63 100644 --- a/impeller/entity/geometry/stroke_path_geometry.cc +++ b/impeller/entity/geometry/stroke_path_geometry.cc @@ -451,7 +451,7 @@ GeometryResult StrokePathGeometry::GetPositionBuffer( Scalar min_size = 1.0f / sqrt(std::abs(determinant)); Scalar stroke_width = std::max(stroke_width_, min_size); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto vertex_builder = CreateSolidStrokeVertices( path_, stroke_width, miter_limit_ * stroke_width_ * 0.5, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_), @@ -483,7 +483,7 @@ GeometryResult StrokePathGeometry::GetPositionUVBuffer( Scalar min_size = 1.0f / sqrt(std::abs(determinant)); Scalar stroke_width = std::max(stroke_width_, min_size); - auto& host_buffer = pass.GetTransientsBuffer(); + auto& host_buffer = renderer.GetTransientsBuffer(); auto stroke_builder = CreateSolidStrokeVertices( path_, stroke_width, miter_limit_ * stroke_width_ * 0.5, GetJoinProc(stroke_join_), GetCapProc(stroke_cap_), diff --git a/impeller/playground/imgui/imgui_impl_impeller.cc b/impeller/playground/imgui/imgui_impl_impeller.cc index 37f3adb0e7523..8b58e9cc32532 100644 --- a/impeller/playground/imgui/imgui_impl_impeller.cc +++ b/impeller/playground/imgui/imgui_impl_impeller.cc @@ -9,6 +9,8 @@ #include #include +#include "impeller/core/host_buffer.h" +#include "impeller/core/platform.h" #include "impeller/geometry/scalar.h" #include "impeller/geometry/vector.h" #include "impeller/playground/imgui/imgui_raster.frag.h" @@ -124,6 +126,8 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data, if (draw_data->CmdListsCount == 0) { return; // Nothing to render. } + auto host_buffer = impeller::HostBuffer::Create( + render_pass.GetContext().lock()->GetResourceAllocator()); using VS = impeller::ImguiRasterVertexShader; using FS = impeller::ImguiRasterFragmentShader; @@ -157,8 +161,7 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data, VS::UniformBuffer uniforms; uniforms.mvp = impeller::Matrix::MakeOrthographic(display_rect.GetSize()) .Translate(-display_rect.GetOrigin()); - auto vtx_uniforms = - render_pass.GetTransientsBuffer().EmplaceUniform(uniforms); + auto vtx_uniforms = host_buffer->EmplaceUniform(uniforms); size_t vertex_buffer_offset = 0; size_t index_buffer_offset = total_vtx_bytes; @@ -270,4 +273,5 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data, vertex_buffer_offset += draw_list_vtx_bytes; index_buffer_offset += draw_list_idx_bytes; } + host_buffer->Reset(); } diff --git a/impeller/playground/playground.cc b/impeller/playground/playground.cc index 07bb72c09b355..1c6dbfa694b49 100644 --- a/impeller/playground/playground.cc +++ b/impeller/playground/playground.cc @@ -317,7 +317,6 @@ bool Playground::OpenPlaygroundHere( if (!ShouldKeepRendering()) { break; } - renderer_->GetContext()->GetTransientsBuffer()->Reset(); } ::glfwHideWindow(window); diff --git a/impeller/renderer/backend/gles/context_gles.cc b/impeller/renderer/backend/gles/context_gles.cc index a9a06bc0e3b62..779255dffa6c4 100644 --- a/impeller/renderer/backend/gles/context_gles.cc +++ b/impeller/renderer/backend/gles/context_gles.cc @@ -7,7 +7,6 @@ #include "impeller/base/config.h" #include "impeller/base/validation.h" -#include "impeller/core/host_buffer.h" #include "impeller/renderer/backend/gles/command_buffer_gles.h" #include "impeller/renderer/backend/gles/gpu_tracer_gles.h" @@ -66,7 +65,6 @@ ContextGLES::ContextGLES( std::shared_ptr(new SamplerLibraryGLES( device_capabilities_->SupportsDecalSamplerAddressMode())); } - host_buffer_ = HostBuffer::Create(resource_allocator_); gpu_tracer_ = std::make_shared(GetReactor()->GetProcTable(), enable_gpu_tracing); is_valid_ = true; @@ -134,11 +132,6 @@ std::shared_ptr ContextGLES::CreateCommandBuffer() const { new CommandBufferGLES(weak_from_this(), reactor_)); } -// |Context| -const std::shared_ptr ContextGLES::GetTransientsBuffer() const { - return host_buffer_; -} - // |Context| const std::shared_ptr& ContextGLES::GetCapabilities() const { diff --git a/impeller/renderer/backend/gles/context_gles.h b/impeller/renderer/backend/gles/context_gles.h index 2286473a9eecd..295cba8bfb9a4 100644 --- a/impeller/renderer/backend/gles/context_gles.h +++ b/impeller/renderer/backend/gles/context_gles.h @@ -90,9 +90,6 @@ class ContextGLES final : public Context, // |Context| const std::shared_ptr& GetCapabilities() const override; - // |Context| - const std::shared_ptr GetTransientsBuffer() const override; - // |Context| void Shutdown() override; diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index fe4486fc9740d..9a761db5706ae 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -83,9 +83,6 @@ class ContextMTL final : public Context, // |Context| const std::shared_ptr& GetCapabilities() const override; - // |Context| - const std::shared_ptr GetTransientsBuffer() const override; - void SetCapabilities(const std::shared_ptr& capabilities); // |Context| diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index 045adab1ad2fb..90054aa21dcbd 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -13,7 +13,6 @@ #include "flutter/fml/paths.h" #include "flutter/fml/synchronization/sync_switch.h" #include "impeller/core/formats.h" -#include "impeller/core/host_buffer.h" #include "impeller/core/sampler_descriptor.h" #include "impeller/renderer/backend/metal/gpu_tracer_mtl.h" #include "impeller/renderer/backend/metal/sampler_library_mtl.h" @@ -148,7 +147,6 @@ static bool DeviceSupportsComputeSubgroups(id device) { device_capabilities_ = InferMetalCapabilities(device_, PixelFormat::kB8G8R8A8UNormInt); - host_buffer_ = HostBuffer::Create(resource_allocator_); #ifdef IMPELLER_DEBUG gpu_tracer_ = std::make_shared(); #endif // IMPELLER_DEBUG @@ -311,11 +309,6 @@ new ContextMTL(device, command_queue, return is_valid_; } -// |Context| -const std::shared_ptr ContextMTL::GetTransientsBuffer() const { - return host_buffer_; -} - // |Context| std::shared_ptr ContextMTL::GetShaderLibrary() const { return shader_library_; diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.cc b/impeller/renderer/backend/vulkan/command_encoder_vk.cc index 4750928450a31..31ab804027da9 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.cc +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.cc @@ -142,22 +142,20 @@ std::shared_ptr CommandEncoderFactoryVK::Create() { tracked_objects->GetGPUProbe().RecordCmdBufferStart( tracked_objects->GetCommandBuffer()); - return std::make_shared( - context->GetDeviceHolder(), tracked_objects, queue, - context->GetFenceWaiter(), context->GetTransientsBuffer()); + return std::make_shared(context->GetDeviceHolder(), + tracked_objects, queue, + context->GetFenceWaiter()); } CommandEncoderVK::CommandEncoderVK( std::weak_ptr device_holder, std::shared_ptr tracked_objects, const std::shared_ptr& queue, - std::shared_ptr fence_waiter, - std::shared_ptr host_buffer) + std::shared_ptr fence_waiter) : device_holder_(std::move(device_holder)), tracked_objects_(std::move(tracked_objects)), queue_(queue), - fence_waiter_(std::move(fence_waiter)), - host_buffer_(std::move(host_buffer)) {} + fence_waiter_(std::move(fence_waiter)) {} CommandEncoderVK::~CommandEncoderVK() = default; diff --git a/impeller/renderer/backend/vulkan/command_encoder_vk.h b/impeller/renderer/backend/vulkan/command_encoder_vk.h index fed6ff5199ba0..4c682e8284884 100644 --- a/impeller/renderer/backend/vulkan/command_encoder_vk.h +++ b/impeller/renderer/backend/vulkan/command_encoder_vk.h @@ -54,8 +54,7 @@ class CommandEncoderVK { CommandEncoderVK(std::weak_ptr device_holder, std::shared_ptr tracked_objects, const std::shared_ptr& queue, - std::shared_ptr fence_waiter, - std::shared_ptr host_buffer); + std::shared_ptr fence_waiter); ~CommandEncoderVK(); diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.cc b/impeller/renderer/backend/vulkan/command_pool_vk.cc index 8f85cc956f27f..1c5d0dec6c843 100644 --- a/impeller/renderer/backend/vulkan/command_pool_vk.cc +++ b/impeller/renderer/backend/vulkan/command_pool_vk.cc @@ -135,9 +135,10 @@ FML_THREAD_LOCAL fml::ThreadLocalUniquePtr tls_command_pool_map; // Map each context to a list of all thread-local command pools associated // with that context. static Mutex g_all_pools_map_mutex; -static std::unordered_map>> - g_all_pools_map IPLR_GUARDED_BY(g_all_pools_map_mutex); +static std::unordered_map< + const ContextVK*, + std::vector>> g_all_pools_map + IPLR_GUARDED_BY(g_all_pools_map_mutex); // TODO(matanlurey): Return a status_or<> instead of nullptr when we have one. std::shared_ptr CommandPoolRecyclerVK::Get() { diff --git a/impeller/renderer/backend/vulkan/command_pool_vk.h b/impeller/renderer/backend/vulkan/command_pool_vk.h index 6df3c81006751..4db6c098c98ae 100644 --- a/impeller/renderer/backend/vulkan/command_pool_vk.h +++ b/impeller/renderer/backend/vulkan/command_pool_vk.h @@ -66,8 +66,8 @@ class CommandPoolVK final { std::weak_ptr& context_; // Used to retain a reference on these until the pool is reset. - std::vector collected_buffers_ - IPLR_GUARDED_BY(pool_mutex_); + std::vector collected_buffers_ IPLR_GUARDED_BY( + pool_mutex_); }; //------------------------------------------------------------------------------ diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 4954ca88ff534..c3d9ac448e979 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -5,7 +5,6 @@ #include "impeller/renderer/backend/vulkan/context_vk.h" #include "fml/concurrent_message_loop.h" -#include "impeller/core/host_buffer.h" #ifdef FML_OS_ANDROID #include @@ -446,7 +445,6 @@ void ContextVK::Setup(Settings settings) { command_pool_recycler_ = std::move(command_pool_recycler); descriptor_pool_recycler_ = std::move(descriptor_pool_recycler); device_name_ = std::string(physical_device_properties.deviceName); - host_buffer_ = HostBuffer::Create(allocator_); is_valid_ = true; // Create the GPU Tracer later because it depends on state from @@ -473,10 +471,6 @@ bool ContextVK::IsValid() const { return is_valid_; } -const std::shared_ptr ContextVK::GetTransientsBuffer() const { - return host_buffer_; -} - std::shared_ptr ContextVK::GetResourceAllocator() const { return allocator_; } diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 6ac075623ae4a..efd6240b66ea3 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -86,9 +86,6 @@ class ContextVK final : public Context, // |Context| const std::shared_ptr& GetCapabilities() const override; - // |Context| - const std::shared_ptr GetTransientsBuffer() const override; - // |Context| void Shutdown() override; diff --git a/impeller/renderer/backend/vulkan/surface_context_vk.cc b/impeller/renderer/backend/vulkan/surface_context_vk.cc index 8c9c1c4a44ad0..afc1407f6f3f5 100644 --- a/impeller/renderer/backend/vulkan/surface_context_vk.cc +++ b/impeller/renderer/backend/vulkan/surface_context_vk.cc @@ -48,12 +48,6 @@ std::shared_ptr SurfaceContextVK::CreateCommandBuffer() const { return parent_->CreateCommandBuffer(); } -// |Context| -const std::shared_ptr SurfaceContextVK::GetTransientsBuffer() - const { - return parent_->GetTransientsBuffer(); -} - const std::shared_ptr& SurfaceContextVK::GetCapabilities() const { return parent_->GetCapabilities(); diff --git a/impeller/renderer/backend/vulkan/surface_context_vk.h b/impeller/renderer/backend/vulkan/surface_context_vk.h index 4ac727d156390..0394d45c9650f 100644 --- a/impeller/renderer/backend/vulkan/surface_context_vk.h +++ b/impeller/renderer/backend/vulkan/surface_context_vk.h @@ -50,9 +50,6 @@ class SurfaceContextVK : public Context, // |Context| std::shared_ptr CreateCommandBuffer() const override; - // |Context| - const std::shared_ptr GetTransientsBuffer() const override; - // |Context| const std::shared_ptr& GetCapabilities() const override; diff --git a/impeller/renderer/compute_pass.cc b/impeller/renderer/compute_pass.cc index 1d0987d81d289..8446fffdc53a2 100644 --- a/impeller/renderer/compute_pass.cc +++ b/impeller/renderer/compute_pass.cc @@ -7,23 +7,14 @@ #include "fml/logging.h" #include "impeller/base/validation.h" -#include "impeller/core/host_buffer.h" namespace impeller { ComputePass::ComputePass(std::weak_ptr context) - : context_(std::move(context)) { - auto strong_context = context_.lock(); - FML_DCHECK(strong_context); - transients_buffer_ = strong_context->GetTransientsBuffer(); -} + : context_(std::move(context)) {} ComputePass::~ComputePass() = default; -HostBuffer& ComputePass::GetTransientsBuffer() { - return *transients_buffer_; -} - void ComputePass::SetLabel(const std::string& label) { if (label.empty()) { return; diff --git a/impeller/renderer/compute_pass.h b/impeller/renderer/compute_pass.h index 155f36e4b9513..252aa22cd634d 100644 --- a/impeller/renderer/compute_pass.h +++ b/impeller/renderer/compute_pass.h @@ -35,8 +35,6 @@ class ComputePass { void SetThreadGroupSize(const ISize& size); - HostBuffer& GetTransientsBuffer(); - //---------------------------------------------------------------------------- /// @brief Record a command for subsequent encoding to the underlying /// command buffer. No work is encoded into the command buffer at diff --git a/impeller/renderer/compute_subgroup_unittests.cc b/impeller/renderer/compute_subgroup_unittests.cc index b49968fcdb6d8..b8f75db2a2635 100644 --- a/impeller/renderer/compute_subgroup_unittests.cc +++ b/impeller/renderer/compute_subgroup_unittests.cc @@ -12,6 +12,7 @@ #include "gmock/gmock.h" #include "impeller/base/strings.h" #include "impeller/core/formats.h" +#include "impeller/core/host_buffer.h" #include "impeller/display_list/skia_conversions.h" #include "impeller/entity/contents/content_context.h" #include "impeller/fixtures/golden_paths.h" @@ -88,11 +89,12 @@ TEST_P(ComputeSubgroupTest, PathPlayground) { auto future = promise.get_future(); auto path = skia_conversions::ToPath(sk_path); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); auto status = ComputeTessellator{} .SetStrokeWidth(stroke_width) .Tessellate( - path, context, vertex_buffer->AsBufferView(), + path, *host_buffer, context, vertex_buffer->AsBufferView(), vertex_buffer_count->AsBufferView(), [vertex_buffer_count, &vertex_count, &promise](CommandBuffer::Status status) { @@ -163,8 +165,8 @@ TEST_P(ComputeSubgroupTest, PathPlayground) { frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix; frame_info.color = Color::Red().Premultiply(); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo( + cmd, renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; @@ -317,22 +319,22 @@ TEST_P(ComputeSubgroupTest, LargePath) { ::memset(vertex_buffer->AsBufferView().contents, 0, sizeof(SS::VertexBuffer<2048>)); + ContentContext renderer(context, nullptr); + if (!renderer.IsValid()) { + return false; + } + ComputeTessellator{} .SetStrokeWidth(stroke_width) .Tessellate( - complex_path, context, vertex_buffer->AsBufferView(), - vertex_buffer_count->AsBufferView(), + complex_path, renderer.GetTransientsBuffer(), context, + vertex_buffer->AsBufferView(), vertex_buffer_count->AsBufferView(), [vertex_buffer_count, &vertex_count](CommandBuffer::Status status) { vertex_count = reinterpret_cast( vertex_buffer_count->AsBufferView().contents) ->count; }); - ContentContext renderer(context, nullptr); - if (!renderer.IsValid()) { - return false; - } - using VS = SolidFillPipeline::VertexShader; Command cmd; @@ -366,8 +368,8 @@ TEST_P(ComputeSubgroupTest, LargePath) { frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix; frame_info.color = Color::Red().Premultiply(); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo( + cmd, renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; @@ -400,8 +402,9 @@ TEST_P(ComputeSubgroupTest, QuadAndCubicInOnePath) { fml::AutoResetWaitableEvent latch; + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); auto status = tessellator.Tessellate( - path, context, vertex_buffer->AsBufferView(), + path, *host_buffer, context, vertex_buffer->AsBufferView(), vertex_buffer_count->AsBufferView(), [&latch](CommandBuffer::Status status) { EXPECT_EQ(status, CommandBuffer::Status::kCompleted); @@ -449,8 +452,8 @@ TEST_P(ComputeSubgroupTest, QuadAndCubicInOnePath) { frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * world_matrix; frame_info.color = Color::Red().Premultiply(); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo( + cmd, renderer.GetTransientsBuffer().EmplaceUniform(frame_info)); if (!pass.AddCommand(std::move(cmd))) { return false; diff --git a/impeller/renderer/compute_tessellator.cc b/impeller/renderer/compute_tessellator.cc index 87f27fc88f31b..1c6a22f2d77da 100644 --- a/impeller/renderer/compute_tessellator.cc +++ b/impeller/renderer/compute_tessellator.cc @@ -62,6 +62,7 @@ ComputeTessellator& ComputeTessellator::SetQuadraticTolerance(Scalar value) { ComputeTessellator::Status ComputeTessellator::Tessellate( const Path& path, + HostBuffer& host_buffer, const std::shared_ptr& context, BufferView vertex_buffer, BufferView vertex_buffer_count, @@ -127,13 +128,11 @@ ComputeTessellator::Status ComputeTessellator::Tessellate( DEBUG_COMMAND_INFO(cmd, "Generate Polyline"); cmd.pipeline = compute_pipeline; - PS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config)); - PS::BindCubics(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(cubics)); - PS::BindQuads(cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(quads)); - PS::BindLines(cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(lines)); - PS::BindComponents( - cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(components)); + PS::BindConfig(cmd, host_buffer.EmplaceUniform(config)); + PS::BindCubics(cmd, host_buffer.EmplaceStorageBuffer(cubics)); + PS::BindQuads(cmd, host_buffer.EmplaceStorageBuffer(quads)); + PS::BindLines(cmd, host_buffer.EmplaceStorageBuffer(lines)); + PS::BindComponents(cmd, host_buffer.EmplaceStorageBuffer(components)); PS::BindPolyline(cmd, polyline_buffer->AsBufferView()); if (!pass->AddCommand(std::move(cmd))) { @@ -163,7 +162,7 @@ ComputeTessellator::Status ComputeTessellator::Tessellate( .join = static_cast(stroke_join_), .miter_limit = miter_limit_, }; - SS::BindConfig(cmd, pass->GetTransientsBuffer().EmplaceUniform(config)); + SS::BindConfig(cmd, host_buffer.EmplaceUniform(config)); SS::BindPolyline(cmd, polyline_buffer->AsBufferView()); SS::BindVertexBufferCount(cmd, std::move(vertex_buffer_count)); diff --git a/impeller/renderer/compute_tessellator.h b/impeller/renderer/compute_tessellator.h index f8ccd0d8dfe2a..0dc6b56bc1e76 100644 --- a/impeller/renderer/compute_tessellator.h +++ b/impeller/renderer/compute_tessellator.h @@ -65,6 +65,7 @@ class ComputeTessellator { // and heap allocated buffers on Metal. Status Tessellate( const Path& path, + HostBuffer& host_buffer, const std::shared_ptr& context, BufferView vertex_buffer, BufferView vertex_buffer_count, diff --git a/impeller/renderer/compute_unittests.cc b/impeller/renderer/compute_unittests.cc index bcaeff41bb924..03eb2686806d5 100644 --- a/impeller/renderer/compute_unittests.cc +++ b/impeller/renderer/compute_unittests.cc @@ -8,6 +8,7 @@ #include "gmock/gmock.h" #include "impeller/base/strings.h" #include "impeller/core/formats.h" +#include "impeller/core/host_buffer.h" #include "impeller/fixtures/sample.comp.h" #include "impeller/fixtures/stage1.comp.h" #include "impeller/fixtures/stage2.comp.h" @@ -35,6 +36,7 @@ TEST_P(ComputeTest, CapabilitiesReportSupport) { TEST_P(ComputeTest, CanCreateComputePass) { using CS = SampleComputeShader; auto context = GetContext(); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); ASSERT_TRUE(context); ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); @@ -74,11 +76,9 @@ TEST_P(ComputeTest, CanCreateComputePass) { auto output_buffer = CreateHostVisibleDeviceBuffer>( context, "Output Buffer"); - CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info)); - CS::BindInput0(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0)); - CS::BindInput1(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1)); + CS::BindInfo(cmd, host_buffer->EmplaceUniform(info)); + CS::BindInput0(cmd, host_buffer->EmplaceStorageBuffer(input_0)); + CS::BindInput1(cmd, host_buffer->EmplaceStorageBuffer(input_1)); CS::BindOutput(cmd, output_buffer->AsBufferView()); ASSERT_TRUE(pass->AddCommand(std::move(cmd))); @@ -113,6 +113,7 @@ TEST_P(ComputeTest, CanCreateComputePass) { TEST_P(ComputeTest, CanComputePrefixSum) { using CS = PrefixSumTestComputeShader; auto context = GetContext(); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); ASSERT_TRUE(context); ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); @@ -145,8 +146,7 @@ TEST_P(ComputeTest, CanComputePrefixSum) { auto output_buffer = CreateHostVisibleDeviceBuffer>( context, "Output Buffer"); - CS::BindInputData( - cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(input_data)); + CS::BindInputData(cmd, host_buffer->EmplaceStorageBuffer(input_data)); CS::BindOutputData(cmd, output_buffer->AsBufferView()); ASSERT_TRUE(pass->AddCommand(std::move(cmd))); @@ -231,6 +231,8 @@ TEST_P(ComputeTest, CanComputePrefixSumLargeInteractive) { using CS = PrefixSumTestComputeShader; auto context = GetContext(); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); + ASSERT_TRUE(context); ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); @@ -260,12 +262,12 @@ TEST_P(ComputeTest, CanComputePrefixSumLargeInteractive) { auto output_buffer = CreateHostVisibleDeviceBuffer>( context, "Output Buffer"); - CS::BindInputData( - cmd, pass->GetTransientsBuffer().EmplaceStorageBuffer(input_data)); + CS::BindInputData(cmd, host_buffer->EmplaceStorageBuffer(input_data)); CS::BindOutputData(cmd, output_buffer->AsBufferView()); pass->AddCommand(std::move(cmd)); pass->EncodeCommands(); + host_buffer->Reset(); return cmd_buffer->SubmitCommands(); }; ASSERT_TRUE(OpenPlaygroundHere(callback)); @@ -278,6 +280,7 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) { using Stage2PipelineBuilder = ComputePipelineBuilder; auto context = GetContext(); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); ASSERT_TRUE(context); ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); @@ -326,8 +329,7 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) { ComputeCommand cmd; cmd.pipeline = compute_pipeline_1; - CS1::BindInput(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1)); + CS1::BindInput(cmd, host_buffer->EmplaceStorageBuffer(input_1)); CS1::BindOutput(cmd, output_buffer_1->AsBufferView()); ASSERT_TRUE(pass->AddCommand(std::move(cmd))); @@ -373,6 +375,7 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) { TEST_P(ComputeTest, CanCompute1DimensionalData) { using CS = SampleComputeShader; auto context = GetContext(); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); ASSERT_TRUE(context); ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); @@ -411,11 +414,9 @@ TEST_P(ComputeTest, CanCompute1DimensionalData) { auto output_buffer = CreateHostVisibleDeviceBuffer>( context, "Output Buffer"); - CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info)); - CS::BindInput0(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0)); - CS::BindInput1(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1)); + CS::BindInfo(cmd, host_buffer->EmplaceUniform(info)); + CS::BindInput0(cmd, host_buffer->EmplaceStorageBuffer(input_0)); + CS::BindInput1(cmd, host_buffer->EmplaceStorageBuffer(input_1)); CS::BindOutput(cmd, output_buffer->AsBufferView()); ASSERT_TRUE(pass->AddCommand(std::move(cmd))); @@ -450,6 +451,7 @@ TEST_P(ComputeTest, CanCompute1DimensionalData) { TEST_P(ComputeTest, ReturnsEarlyWhenAnyGridDimensionIsZero) { using CS = SampleComputeShader; auto context = GetContext(); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); ASSERT_TRUE(context); ASSERT_TRUE(context->GetCapabilities()->SupportsCompute()); @@ -491,11 +493,9 @@ TEST_P(ComputeTest, ReturnsEarlyWhenAnyGridDimensionIsZero) { auto output_buffer = CreateHostVisibleDeviceBuffer>( context, "Output Buffer"); - CS::BindInfo(cmd, pass->GetTransientsBuffer().EmplaceUniform(info)); - CS::BindInput0(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(input_0)); - CS::BindInput1(cmd, - pass->GetTransientsBuffer().EmplaceStorageBuffer(input_1)); + CS::BindInfo(cmd, host_buffer->EmplaceUniform(info)); + CS::BindInput0(cmd, host_buffer->EmplaceStorageBuffer(input_0)); + CS::BindInput1(cmd, host_buffer->EmplaceStorageBuffer(input_1)); CS::BindOutput(cmd, output_buffer->AsBufferView()); ASSERT_TRUE(pass->AddCommand(std::move(cmd))); diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index f079a2d7d83cb..f3218e56a3a51 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -181,8 +181,6 @@ class Context { /// pending work. virtual void SetSyncPresentation(bool value) {} - virtual const std::shared_ptr GetTransientsBuffer() const = 0; - CaptureContext capture; /// Stores a task on the `ContextMTL` that is awaiting access for the GPU. diff --git a/impeller/renderer/host_buffer_unittests.cc b/impeller/renderer/host_buffer_unittests.cc index 0533b0355242c..b59270ad08935 100644 --- a/impeller/renderer/host_buffer_unittests.cc +++ b/impeller/renderer/host_buffer_unittests.cc @@ -4,17 +4,20 @@ #include "flutter/testing/testing.h" #include "impeller/core/host_buffer.h" +#include "impeller/entity/entity_playground.h" namespace impeller { namespace testing { -TEST(HostBufferTest, CanEmplace) { +using HostBufferTest = EntityPlayground; + +TEST_P(HostBufferTest, CanEmplace) { struct Length2 { uint8_t pad[2]; }; static_assert(sizeof(Length2) == 2u); - auto buffer = HostBuffer::Create(std::make_shared()); + auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); for (size_t i = 0; i < 12500; i++) { auto view = buffer->Emplace(Length2{}); @@ -23,7 +26,7 @@ TEST(HostBufferTest, CanEmplace) { } } -TEST(HostBufferTest, CanEmplaceWithAlignment) { +TEST_P(HostBufferTest, CanEmplaceWithAlignment) { struct Length2 { uint8_t pad[2]; }; @@ -34,7 +37,7 @@ TEST(HostBufferTest, CanEmplaceWithAlignment) { static_assert(alignof(Align16) == 16); static_assert(sizeof(Align16) == 16); - auto buffer = HostBuffer::Create(std::make_shared()); + auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); ASSERT_TRUE(buffer); { diff --git a/impeller/renderer/render_pass.cc b/impeller/renderer/render_pass.cc index 1771763c74d57..aef704bf703d9 100644 --- a/impeller/renderer/render_pass.cc +++ b/impeller/renderer/render_pass.cc @@ -13,11 +13,7 @@ RenderPass::RenderPass(std::weak_ptr context, pixel_format_(target.GetRenderTargetPixelFormat()), has_stencil_attachment_(target.GetStencilAttachment().has_value()), render_target_size_(target.GetRenderTargetSize()), - render_target_(target) { - auto strong_context = context_.lock(); - FML_DCHECK(strong_context); - transients_buffer_ = strong_context->GetTransientsBuffer(); -} + render_target_(target) {} RenderPass::~RenderPass() {} diff --git a/impeller/renderer/render_pass.h b/impeller/renderer/render_pass.h index f9c99155d7562..b1376cd1f5078 100644 --- a/impeller/renderer/render_pass.h +++ b/impeller/renderer/render_pass.h @@ -47,8 +47,6 @@ class RenderPass { commands_.reserve(command_count); } - HostBuffer& GetTransientsBuffer() { return *transients_buffer_; } - //---------------------------------------------------------------------------- /// @brief Record a command for subsequent encoding to the underlying /// command buffer. No work is encoded into the command buffer at @@ -99,7 +97,6 @@ class RenderPass { const bool has_stencil_attachment_; const ISize render_target_size_; const RenderTarget render_target_; - std::shared_ptr transients_buffer_; std::vector commands_; RenderPass(std::weak_ptr context, const RenderTarget& target); diff --git a/impeller/renderer/renderer_unittests.cc b/impeller/renderer/renderer_unittests.cc index a40735040278a..3f73ffc9236b3 100644 --- a/impeller/renderer/renderer_unittests.cc +++ b/impeller/renderer/renderer_unittests.cc @@ -7,6 +7,7 @@ #include "impeller/base/strings.h" #include "impeller/core/device_buffer_descriptor.h" #include "impeller/core/formats.h" +#include "impeller/core/host_buffer.h" #include "impeller/core/sampler.h" #include "impeller/core/sampler_descriptor.h" #include "impeller/fixtures/array.frag.h" @@ -77,6 +78,8 @@ TEST_P(RendererTest, CanCreateBoxPrimitive) { ASSERT_TRUE(bridge && boston); auto sampler = context->GetSamplerLibrary()->GetSampler({}); ASSERT_TRUE(sampler); + + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); SinglePassCallback callback = [&](RenderPass& pass) { ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); static bool wireframe; @@ -98,8 +101,7 @@ TEST_P(RendererTest, CanCreateBoxPrimitive) { VS::UniformBuffer uniforms; uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * Matrix::MakeScale(GetContentScale()); - VS::BindUniformBuffer(cmd, - pass.GetTransientsBuffer().EmplaceUniform(uniforms)); + VS::BindUniformBuffer(cmd, host_buffer->EmplaceUniform(uniforms)); FS::FrameInfo frame_info; frame_info.current_time = GetSecondsElapsed(); @@ -107,10 +109,11 @@ TEST_P(RendererTest, CanCreateBoxPrimitive) { frame_info.window_size.x = GetWindowSize().width; frame_info.window_size.y = GetWindowSize().height; - FS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + FS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::BindContents1(cmd, boston, sampler); FS::BindContents2(cmd, bridge, sampler); + + host_buffer->Reset(); if (!pass.AddCommand(std::move(cmd))) { return false; } @@ -175,6 +178,7 @@ TEST_P(RendererTest, CanRenderPerspectiveCube) { ASSERT_TRUE(sampler); Vector3 euler_angles; + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); SinglePassCallback callback = [&](RenderPass& pass) { static Degrees fov_y(60); static Scalar distance = 10; @@ -200,8 +204,9 @@ TEST_P(RendererTest, CanRenderPerspectiveCube) { Matrix::MakeRotationX(Radians(euler_angles.x)) * Matrix::MakeRotationY(Radians(euler_angles.y)) * Matrix::MakeRotationZ(Radians(euler_angles.z)); - VS::BindUniformBuffer(cmd, - pass.GetTransientsBuffer().EmplaceUniform(uniforms)); + VS::BindUniformBuffer(cmd, host_buffer->EmplaceUniform(uniforms)); + + host_buffer->Reset(); if (!pass.AddCommand(std::move(cmd))) { return false; } @@ -245,6 +250,7 @@ TEST_P(RendererTest, CanRenderMultiplePrimitives) { auto sampler = context->GetSamplerLibrary()->GetSampler({}); ASSERT_TRUE(sampler); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); SinglePassCallback callback = [&](RenderPass& pass) { Command cmd; DEBUG_COMMAND_INFO(cmd, "Box"); @@ -258,8 +264,7 @@ TEST_P(RendererTest, CanRenderMultiplePrimitives) { frame_info.window_size.x = GetWindowSize().width; frame_info.window_size.y = GetWindowSize().height; - FS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + FS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::BindContents1(cmd, boston, sampler); FS::BindContents2(cmd, bridge, sampler); @@ -269,14 +274,14 @@ TEST_P(RendererTest, CanRenderMultiplePrimitives) { uniforms.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * Matrix::MakeScale(GetContentScale()) * Matrix::MakeTranslation({i * 50.0f, j * 50.0f, 0.0f}); - VS::BindUniformBuffer( - cmd, pass.GetTransientsBuffer().EmplaceUniform(uniforms)); + VS::BindUniformBuffer(cmd, host_buffer->EmplaceUniform(uniforms)); if (!pass.AddCommand(std::move(cmd))) { return false; } } } + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); @@ -296,6 +301,7 @@ TEST_P(RendererTest, CanRenderToTexture) { auto box_pipeline = context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get(); ASSERT_TRUE(box_pipeline); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); VertexBufferBuilder vertex_builder; vertex_builder.SetLabel("Box"); @@ -372,16 +378,14 @@ TEST_P(RendererTest, CanRenderToTexture) { frame_info.window_size.x = GetWindowSize().width; frame_info.window_size.y = GetWindowSize().height; - FS::BindFrameInfo(cmd, - r2t_pass->GetTransientsBuffer().EmplaceUniform(frame_info)); + FS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::BindContents1(cmd, boston, sampler); FS::BindContents2(cmd, bridge, sampler); VS::UniformBuffer uniforms; uniforms.mvp = Matrix::MakeOrthographic(ISize{1024, 768}) * Matrix::MakeTranslation({50.0f, 50.0f, 0.0f}); - VS::BindUniformBuffer( - cmd, r2t_pass->GetTransientsBuffer().EmplaceUniform(uniforms)); + VS::BindUniformBuffer(cmd, host_buffer->EmplaceUniform(uniforms)); ASSERT_TRUE(r2t_pass->AddCommand(std::move(cmd))); ASSERT_TRUE(r2t_pass->EncodeCommands()); } @@ -436,18 +440,19 @@ TEST_P(RendererTest, CanRenderInstanced) { instances.colors[i] = Color::Random(); } + auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool { VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * Matrix::MakeScale(GetContentScale()); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); - VS::BindInstanceInfo( - cmd, pass.GetTransientsBuffer().EmplaceStorageBuffer(instances)); - cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + VS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); + VS::BindInstanceInfo(cmd, host_buffer->EmplaceStorageBuffer(instances)); + cmd.BindVertices(builder.CreateVertexBuffer(*host_buffer)); cmd.instance_count = kInstancesCount; pass.AddCommand(std::move(cmd)); + + host_buffer->Reset(); return true; })); } @@ -499,6 +504,7 @@ TEST_P(RendererTest, CanBlitTextureToTexture) { vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()); ASSERT_TRUE(vertex_buffer); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); Renderer::RenderCallback callback = [&](RenderTarget& render_target) { auto buffer = context->CreateCommandBuffer(); if (!buffer) { @@ -541,13 +547,11 @@ TEST_P(RendererTest, CanBlitTextureToTexture) { VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass->GetRenderTargetSize()) * Matrix::MakeScale(GetContentScale()); - VS::BindFrameInfo( - cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::FragInfo frag_info; frag_info.lod = 0; - FS::BindFragInfo(cmd, - pass->GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, host_buffer->EmplaceUniform(frag_info)); auto sampler = context->GetSamplerLibrary()->GetSampler({}); FS::BindTex(cmd, texture, sampler); @@ -560,6 +564,7 @@ TEST_P(RendererTest, CanBlitTextureToTexture) { if (!buffer->SubmitCommands()) { return false; } + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); @@ -617,6 +622,7 @@ TEST_P(RendererTest, CanBlitTextureToBuffer) { vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator()); ASSERT_TRUE(vertex_buffer); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); Renderer::RenderCallback callback = [&](RenderTarget& render_target) { { auto buffer = context->CreateCommandBuffer(); @@ -666,13 +672,11 @@ TEST_P(RendererTest, CanBlitTextureToBuffer) { VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass->GetRenderTargetSize()) * Matrix::MakeScale(GetContentScale()); - VS::BindFrameInfo( - cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::FragInfo frag_info; frag_info.lod = 0; - FS::BindFragInfo(cmd, - pass->GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, host_buffer->EmplaceUniform(frag_info)); auto sampler = context->GetSamplerLibrary()->GetSampler({}); auto buffer_view = device_buffer->AsBufferView(); @@ -692,6 +696,7 @@ TEST_P(RendererTest, CanBlitTextureToBuffer) { return false; } } + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); @@ -731,6 +736,7 @@ TEST_P(RendererTest, CanGenerateMipmaps) { ASSERT_TRUE(vertex_buffer); bool first_frame = true; + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); Renderer::RenderCallback callback = [&](RenderTarget& render_target) { const char* mip_filter_names[] = {"Nearest", "Linear"}; const MipFilter mip_filters[] = {MipFilter::kNearest, MipFilter::kLinear}; @@ -787,13 +793,11 @@ TEST_P(RendererTest, CanGenerateMipmaps) { VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(pass->GetRenderTargetSize()) * Matrix::MakeScale(GetContentScale()); - VS::BindFrameInfo( - cmd, pass->GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::FragInfo frag_info; frag_info.lod = lod; - FS::BindFragInfo(cmd, - pass->GetTransientsBuffer().EmplaceUniform(frag_info)); + FS::BindFragInfo(cmd, host_buffer->EmplaceUniform(frag_info)); SamplerDescriptor sampler_desc; sampler_desc.mip_filter = mip_filters[selected_mip_filter]; @@ -809,6 +813,7 @@ TEST_P(RendererTest, CanGenerateMipmaps) { if (!buffer->SubmitCommands()) { return false; } + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); @@ -840,6 +845,7 @@ TEST_P(RendererTest, TheImpeller) { "table_mountain_py.png", "table_mountain_ny.png", "table_mountain_pz.png", "table_mountain_nz.png"}); auto cube_map_sampler = context->GetSamplerLibrary()->GetSampler({}); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); SinglePassCallback callback = [&](RenderPass& pass) { auto size = pass.GetRenderTargetSize(); @@ -854,22 +860,21 @@ TEST_P(RendererTest, TheImpeller) { {Point(size.width, 0)}, {Point(0, size.height)}, {Point(size.width, size.height)}}); - cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + cmd.BindVertices(builder.CreateVertexBuffer(*host_buffer)); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(size); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::FragInfo fs_uniform; fs_uniform.texture_size = Point(size); fs_uniform.time = GetSecondsElapsed(); - FS::BindFragInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(fs_uniform)); + FS::BindFragInfo(cmd, host_buffer->EmplaceUniform(fs_uniform)); FS::BindBlueNoise(cmd, blue_noise, noise_sampler); FS::BindCubeMap(cmd, cube_map, cube_map_sampler); pass.AddCommand(std::move(cmd)); + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); @@ -889,6 +894,7 @@ TEST_P(RendererTest, ArrayUniforms) { context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get(); ASSERT_TRUE(pipeline && pipeline->IsValid()); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); SinglePassCallback callback = [&](RenderPass& pass) { auto size = pass.GetRenderTargetSize(); @@ -902,13 +908,12 @@ TEST_P(RendererTest, ArrayUniforms) { {Point(size.width, 0)}, {Point(0, size.height)}, {Point(size.width, size.height)}}); - cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + cmd.BindVertices(builder.CreateVertexBuffer(*host_buffer)); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(size) * Matrix::MakeScale(GetContentScale()); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); auto time = GetSecondsElapsed(); auto y_pos = [&time](float x) { @@ -923,10 +928,10 @@ TEST_P(RendererTest, ArrayUniforms) { Color::MakeRGBA8(244, 180, 0, 255), Color::MakeRGBA8(15, 157, 88, 255)}, }; - FS::BindFragInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(fs_uniform)); + FS::BindFragInfo(cmd, host_buffer->EmplaceUniform(fs_uniform)); pass.AddCommand(std::move(cmd)); + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); @@ -946,6 +951,7 @@ TEST_P(RendererTest, InactiveUniforms) { context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get(); ASSERT_TRUE(pipeline && pipeline->IsValid()); + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); SinglePassCallback callback = [&](RenderPass& pass) { auto size = pass.GetRenderTargetSize(); @@ -959,20 +965,19 @@ TEST_P(RendererTest, InactiveUniforms) { {Point(size.width, 0)}, {Point(0, size.height)}, {Point(size.width, size.height)}}); - cmd.BindVertices(builder.CreateVertexBuffer(pass.GetTransientsBuffer())); + cmd.BindVertices(builder.CreateVertexBuffer(*host_buffer)); VS::FrameInfo frame_info; frame_info.mvp = Matrix::MakeOrthographic(size) * Matrix::MakeScale(GetContentScale()); - VS::BindFrameInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(frame_info)); + VS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::FragInfo fs_uniform = {.unused_color = Color::Red(), .color = Color::Green()}; - FS::BindFragInfo(cmd, - pass.GetTransientsBuffer().EmplaceUniform(fs_uniform)); + FS::BindFragInfo(cmd, host_buffer->EmplaceUniform(fs_uniform)); pass.AddCommand(std::move(cmd)); + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); @@ -1145,6 +1150,8 @@ TEST_P(RendererTest, StencilMask) { CompareFunctionUI().IndexOf(CompareFunction::kLessEqual); static int current_back_compare = CompareFunctionUI().IndexOf(CompareFunction::kLessEqual); + + auto host_buffer = HostBuffer::Create(context->GetResourceAllocator()); Renderer::RenderCallback callback = [&](RenderTarget& render_target) { auto buffer = context->CreateCommandBuffer(); if (!buffer) { @@ -1228,8 +1235,7 @@ TEST_P(RendererTest, StencilMask) { if (mirror) { uniforms.mvp = Matrix::MakeScale(Vector2(-1, 1)) * uniforms.mvp; } - VS::BindUniformBuffer( - cmd, pass->GetTransientsBuffer().EmplaceUniform(uniforms)); + VS::BindUniformBuffer(cmd, host_buffer->EmplaceUniform(uniforms)); FS::FrameInfo frame_info; frame_info.current_time = GetSecondsElapsed(); @@ -1237,8 +1243,7 @@ TEST_P(RendererTest, StencilMask) { frame_info.window_size.x = GetWindowSize().width; frame_info.window_size.y = GetWindowSize().height; - FS::BindFrameInfo(cmd, - pass->GetTransientsBuffer().EmplaceUniform(frame_info)); + FS::BindFrameInfo(cmd, host_buffer->EmplaceUniform(frame_info)); FS::BindContents1(cmd, boston, sampler); FS::BindContents2(cmd, bridge, sampler); if (!pass->AddCommand(std::move(cmd))) { @@ -1250,6 +1255,7 @@ TEST_P(RendererTest, StencilMask) { if (!buffer->SubmitCommands()) { return false; } + host_buffer->Reset(); return true; }; OpenPlaygroundHere(callback); diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index bb7bc488b74cf..4960a57ef78fd 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -160,11 +160,6 @@ class MockImpellerContext : public Context { (), (const, override)); - MOCK_METHOD(const std::shared_ptr, - GetTransientsBuffer, - (), - (const, override)); - MOCK_METHOD(const std::shared_ptr&, GetCapabilities, (), diff --git a/impeller/scene/scene_context.cc b/impeller/scene/scene_context.cc index baece932832a2..c4637837b3644 100644 --- a/impeller/scene/scene_context.cc +++ b/impeller/scene/scene_context.cc @@ -4,6 +4,7 @@ #include "impeller/scene/scene_context.h" #include "impeller/core/formats.h" +#include "impeller/core/host_buffer.h" #include "impeller/scene/material.h" #include "impeller/scene/shaders/skinned.vert.h" #include "impeller/scene/shaders/unlit.frag.h" @@ -80,7 +81,7 @@ SceneContext::SceneContext(std::shared_ptr context) return; } } - + host_buffer_ = HostBuffer::Create(GetContext()->GetResourceAllocator()); is_valid_ = true; } diff --git a/impeller/scene/scene_context.h b/impeller/scene/scene_context.h index 24d49249f7ac0..4c99e99867213 100644 --- a/impeller/scene/scene_context.h +++ b/impeller/scene/scene_context.h @@ -7,6 +7,7 @@ #include +#include "impeller/core/host_buffer.h" #include "impeller/renderer/context.h" #include "impeller/renderer/pipeline.h" #include "impeller/renderer/pipeline_descriptor.h" @@ -53,6 +54,8 @@ class SceneContext { std::shared_ptr GetPlaceholderTexture() const; + HostBuffer& GetTransientsBuffer() const { return *host_buffer_; } + private: class PipelineVariants { public: @@ -144,6 +147,7 @@ class SceneContext { // A 1x1 opaque white texture that can be used as a placeholder binding. // Available for the lifetime of the scene context std::shared_ptr placeholder_texture_; + std::shared_ptr host_buffer_; SceneContext(const SceneContext&) = delete; diff --git a/impeller/scene/scene_encoder.cc b/impeller/scene/scene_encoder.cc index e0572ffdb6971..43c9c85af8caa 100644 --- a/impeller/scene/scene_encoder.cc +++ b/impeller/scene/scene_encoder.cc @@ -24,7 +24,7 @@ static void EncodeCommand(const SceneContext& scene_context, const Matrix& view_transform, RenderPass& render_pass, const SceneCommand& scene_command) { - auto& host_buffer = render_pass.GetTransientsBuffer(); + auto& host_buffer = scene_context.GetTransientsBuffer(); Command cmd; DEBUG_COMMAND_INFO(cmd, scene_command.label); From 5a82b6efd59ef520a189252b2030845363631fc3 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 8 Jan 2024 15:09:26 -0800 Subject: [PATCH 07/21] move test file. --- impeller/entity/BUILD.gn | 1 + impeller/{renderer => entity/contents}/host_buffer_unittests.cc | 0 impeller/renderer/BUILD.gn | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename impeller/{renderer => entity/contents}/host_buffer_unittests.cc (100%) diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index f324e6a1fa133..ad3ff1edbe7ed 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -266,6 +266,7 @@ impeller_component("entity_unittests") { "contents/filters/directional_gaussian_blur_filter_contents_unittests.cc", "contents/filters/gaussian_blur_filter_contents_unittests.cc", "contents/filters/inputs/filter_input_unittests.cc", + "contents/host_buffer_unittests.cc", "contents/tiled_texture_contents_unittests.cc", "contents/vertices_contents_unittests.cc", "entity_pass_target_unittests.cc", diff --git a/impeller/renderer/host_buffer_unittests.cc b/impeller/entity/contents/host_buffer_unittests.cc similarity index 100% rename from impeller/renderer/host_buffer_unittests.cc rename to impeller/entity/contents/host_buffer_unittests.cc diff --git a/impeller/renderer/BUILD.gn b/impeller/renderer/BUILD.gn index 8d6a2061f9e59..6b17817b849f3 100644 --- a/impeller/renderer/BUILD.gn +++ b/impeller/renderer/BUILD.gn @@ -125,7 +125,6 @@ impeller_component("renderer_unittests") { "blit_pass_unittests.cc", "capabilities_unittests.cc", "device_buffer_unittests.cc", - "host_buffer_unittests.cc", "pipeline_descriptor_unittests.cc", "pool_unittests.cc", "renderer_unittests.cc", From fefb257e96a5f3bf0797ed2af9ba5813e0413d85 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 8 Jan 2024 15:16:51 -0800 Subject: [PATCH 08/21] reset transients in playground. --- impeller/entity/contents/clip_contents.cc | 3 ++- impeller/entity/entity_playground.cc | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/impeller/entity/contents/clip_contents.cc b/impeller/entity/contents/clip_contents.cc index c07628d92fe88..16f10b0603fc4 100644 --- a/impeller/entity/contents/clip_contents.cc +++ b/impeller/entity/contents/clip_contents.cc @@ -100,7 +100,8 @@ bool ClipContents::Render(const ContentContext& renderer, cmd.BindVertices(std::move(vertices)); info.mvp = pass.GetOrthographicTransform(); - VS::BindFrameInfo(cmd, renderer.GetTransientsBuffer().EmplaceUniform(info)); + VS::BindFrameInfo(cmd, + renderer.GetTransientsBuffer().EmplaceUniform(info)); options.primitive_type = PrimitiveType::kTriangleStrip; cmd.pipeline = renderer.GetClipPipeline(options); diff --git a/impeller/entity/entity_playground.cc b/impeller/entity/entity_playground.cc index 3763cac125780..d74e177e2e382 100644 --- a/impeller/entity/entity_playground.cc +++ b/impeller/entity/entity_playground.cc @@ -53,6 +53,7 @@ bool EntityPlayground::OpenPlaygroundHere(Entity entity) { content_context->GetRenderTargetCache()->Start(); bool result = entity.Render(*content_context, pass); content_context->GetRenderTargetCache()->End(); + content_context->GetTransientsBuffer().Reset(); return result; }; return Playground::OpenPlaygroundHere(callback); @@ -76,6 +77,7 @@ bool EntityPlayground::OpenPlaygroundHere(EntityPlaygroundCallback callback) { content_context.GetRenderTargetCache()->Start(); bool result = callback(content_context, pass); content_context.GetRenderTargetCache()->End(); + content_context.GetTransientsBuffer().Reset(); return result; }; return Playground::OpenPlaygroundHere(pass_callback); From 3ab6e0f90a9190e37cd52ee89ca5a0e820bfdfcd Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 8 Jan 2024 16:48:16 -0800 Subject: [PATCH 09/21] GLES buffer starts out dirty. --- ci/licenses_golden/excluded_files | 2 +- impeller/entity/entity_pass.cc | 2 +- impeller/renderer/backend/gles/device_buffer_gles.h | 5 ++--- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index c99621d35d403..3f43d429ad4b8 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -146,6 +146,7 @@ ../../../flutter/impeller/entity/contents/filters/directional_gaussian_blur_filter_contents_unittests.cc ../../../flutter/impeller/entity/contents/filters/gaussian_blur_filter_contents_unittests.cc ../../../flutter/impeller/entity/contents/filters/inputs/filter_input_unittests.cc +../../../flutter/impeller/entity/contents/host_buffer_unittests.cc ../../../flutter/impeller/entity/contents/test ../../../flutter/impeller/entity/contents/tiled_texture_contents_unittests.cc ../../../flutter/impeller/entity/contents/vertices_contents_unittests.cc @@ -187,7 +188,6 @@ ../../../flutter/impeller/renderer/compute_subgroup_unittests.cc ../../../flutter/impeller/renderer/compute_unittests.cc ../../../flutter/impeller/renderer/device_buffer_unittests.cc -../../../flutter/impeller/renderer/host_buffer_unittests.cc ../../../flutter/impeller/renderer/pipeline_descriptor_unittests.cc ../../../flutter/impeller/renderer/pool_unittests.cc ../../../flutter/impeller/renderer/renderer_dart_unittests.cc diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 47c2dbae151c9..b56ccd7c136e6 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -309,7 +309,7 @@ bool EntityPass::Render(ContentContext& renderer, renderer.GetRenderTargetCache()->End(); renderer.GetTransientsBuffer().Reset(); #if IMPELLER_ENABLE_3D - renderer.GetSceneContext().GetTransientsBuffer().Reset(); + renderer.GetSceneContext()->GetTransientsBuffer().Reset(); #endif // IMPELLER_ENABLE_3D }); diff --git a/impeller/renderer/backend/gles/device_buffer_gles.h b/impeller/renderer/backend/gles/device_buffer_gles.h index 8aee746127fea..8d884c608b7a8 100644 --- a/impeller/renderer/backend/gles/device_buffer_gles.h +++ b/impeller/renderer/backend/gles/device_buffer_gles.h @@ -8,7 +8,6 @@ #include #include -#include "flutter/fml/macros.h" #include "impeller/base/allocation.h" #include "impeller/base/backend_cast.h" #include "impeller/core/device_buffer.h" @@ -43,8 +42,8 @@ class DeviceBufferGLES final ReactorGLES::Ref reactor_; HandleGLES handle_; mutable std::shared_ptr backing_store_; - mutable uint32_t generation_ = 0; - mutable uint32_t upload_generation_ = 0; + mutable int32_t generation_ = 0; + mutable int32_t upload_generation_ = -1; // |DeviceBuffer| uint8_t* OnGetContents() const override; From 7dd9854a2a9eb02746fb86af44666db1ad5c638c Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Mon, 8 Jan 2024 17:09:27 -0800 Subject: [PATCH 10/21] ++ --- impeller/entity/contents/host_buffer_unittests.cc | 1 + impeller/renderer/backend/vulkan/context_vk.cc | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/impeller/entity/contents/host_buffer_unittests.cc b/impeller/entity/contents/host_buffer_unittests.cc index b59270ad08935..c73451ebbc59f 100644 --- a/impeller/entity/contents/host_buffer_unittests.cc +++ b/impeller/entity/contents/host_buffer_unittests.cc @@ -10,6 +10,7 @@ namespace impeller { namespace testing { using HostBufferTest = EntityPlayground; +INSTANTIATE_PLAYGROUND_SUITE(HostBufferTest); TEST_P(HostBufferTest, CanEmplace) { struct Length2 { diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index c3d9ac448e979..336204108fed5 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -158,9 +158,9 @@ void ContextVK::Setup(Settings settings) { // (It's possible 2 is overly conservative and we can simplify this) auto enable_validation = false; - // #if defined(FML_OS_ANDROID) && !defined(NDEBUG) - // enable_validation = true; - // #endif + #if defined(FML_OS_ANDROID) && !defined(NDEBUG) + enable_validation = true; + #endif auto caps = std::shared_ptr(new CapabilitiesVK(enable_validation)); From 8c062941197602687b8932f1ae968b048cb53b60 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 09:43:14 -0800 Subject: [PATCH 11/21] cleanups, make flush work for GLES. --- impeller/core/buffer.h | 3 +- impeller/core/device_buffer.cc | 5 +- impeller/core/device_buffer.h | 12 +++-- impeller/core/host_buffer.cc | 51 +++++++++++++++---- impeller/core/host_buffer.h | 10 ++-- impeller/entity/entity_pass.cc | 3 -- .../backend/gles/buffer_bindings_gles.cc | 3 +- impeller/renderer/backend/gles/context_gles.h | 5 -- .../backend/gles/device_buffer_gles.cc | 4 ++ .../backend/gles/device_buffer_gles.h | 6 ++- .../renderer/backend/gles/render_pass_gles.cc | 6 +-- .../backend/metal/compute_pass_mtl.mm | 2 +- impeller/renderer/backend/metal/context_mtl.h | 1 - .../renderer/backend/metal/render_pass_mtl.mm | 4 +- .../backend/vulkan/binding_helpers_vk.cc | 2 +- .../renderer/backend/vulkan/context_vk.cc | 6 +-- impeller/renderer/backend/vulkan/context_vk.h | 2 - .../backend/vulkan/device_buffer_vk.cc | 1 + .../renderer/backend/vulkan/render_pass_vk.cc | 4 +- impeller/scene/scene.cc | 4 ++ lib/gpu/render_pass.cc | 6 +-- 21 files changed, 88 insertions(+), 52 deletions(-) diff --git a/impeller/core/buffer.h b/impeller/core/buffer.h index 0664f1afc53b3..df58b56c0c62c 100644 --- a/impeller/core/buffer.h +++ b/impeller/core/buffer.h @@ -16,8 +16,7 @@ class Buffer { public: virtual ~Buffer(); - virtual std::shared_ptr GetDeviceBuffer( - Allocator& allocator) const = 0; + virtual std::shared_ptr GetDeviceBuffer() const = 0; }; } // namespace impeller diff --git a/impeller/core/device_buffer.cc b/impeller/core/device_buffer.cc index 741a4d7ee2386..9637b83108d4d 100644 --- a/impeller/core/device_buffer.cc +++ b/impeller/core/device_buffer.cc @@ -11,11 +11,12 @@ DeviceBuffer::DeviceBuffer(DeviceBufferDescriptor desc) : desc_(desc) {} DeviceBuffer::~DeviceBuffer() = default; // |Buffer| -std::shared_ptr DeviceBuffer::GetDeviceBuffer( - Allocator& allocator) const { +std::shared_ptr DeviceBuffer::GetDeviceBuffer() const { return shared_from_this(); } +void DeviceBuffer::Flush(std::optional range) {} + BufferView DeviceBuffer::AsBufferView() const { BufferView view; view.buffer = shared_from_this(); diff --git a/impeller/core/device_buffer.h b/impeller/core/device_buffer.h index 2b16e97a2ce61..5ab542d3d57a2 100644 --- a/impeller/core/device_buffer.h +++ b/impeller/core/device_buffer.h @@ -38,14 +38,20 @@ class DeviceBuffer : public Buffer, uint16_t row_bytes) const; // |Buffer| - std::shared_ptr GetDeviceBuffer( - Allocator& allocator) const; + std::shared_ptr GetDeviceBuffer() const; const DeviceBufferDescriptor& GetDeviceBufferDescriptor() const; virtual uint8_t* OnGetContents() const = 0; - virtual void Flush(std::optional range) const {} + /// Make any pending writes visible to the GPU. + /// + /// This method must be called if the device pointer provided by + /// [OnGetContents] is written to, and the host memory allocation is not host + /// coherent. + /// + /// If the range is not provided, the entire buffer is flushed. + virtual void Flush(std::optional range = std::nullopt); protected: const DeviceBufferDescriptor desc_; diff --git a/impeller/core/host_buffer.cc b/impeller/core/host_buffer.cc index 422bde4d1c94c..c400f03ec28d3 100644 --- a/impeller/core/host_buffer.cc +++ b/impeller/core/host_buffer.cc @@ -64,22 +64,15 @@ BufferView HostBuffer::Emplace(size_t length, return BufferView{std::move(device_buffer), data, range}; } -std::shared_ptr HostBuffer::GetDeviceBuffer( - Allocator& allocator) const { - return nullptr; -} - void HostBuffer::Reset() { state_->Reset(); } 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; - } + FML_DCHECK(required_size <= kAllocatorBlockSize); DeviceBufferDescriptor desc; - desc.size = std::max(kAllocatorBlockSize, required_size); + desc.size = kAllocatorBlockSize; desc.storage_mode = StorageMode::kHostVisible; device_buffers.push_back(allocator->CreateBuffer(desc)); } @@ -91,6 +84,24 @@ std::tuple> HostBuffer::HostBufferState::Emplace(size_t length, size_t align, const EmplaceProc& cb) { + // If the requested allocation is bigger than the block size, create a one-off + // device buffer and write to that. + if (length > kAllocatorBlockSize) { + DeviceBufferDescriptor desc; + desc.size = kAllocatorBlockSize; + desc.storage_mode = StorageMode::kHostVisible; + auto device_buffer = allocator->CreateBuffer(desc); + if (!device_buffer) { + return {}; + } + if (cb) { + cb(GetCurrentBuffer()->OnGetContents()); + GetCurrentBuffer()->Flush(Range{0, length}); + } + return std::make_tuple(device_buffer->OnGetContents(), Range{0, length}, + device_buffer); + } + if (!cb) { return {}; } @@ -98,6 +109,7 @@ HostBuffer::HostBufferState::Emplace(size_t length, if (old_length + length > kAllocatorBlockSize) { MaybeCreateNewBuffer(length); } + old_length = GetLength(); cb(GetCurrentBuffer()->OnGetContents() + old_length); GetCurrentBuffer()->Flush(Range{old_length, length}); @@ -109,10 +121,31 @@ HostBuffer::HostBufferState::Emplace(size_t length, std::tuple> HostBuffer::HostBufferState::Emplace(const void* buffer, size_t length) { + // If the requested allocation is bigger than the block size, create a one-off + // device buffer and write to that. + if (length > kAllocatorBlockSize) { + DeviceBufferDescriptor desc; + desc.size = kAllocatorBlockSize; + desc.storage_mode = StorageMode::kHostVisible; + auto device_buffer = allocator->CreateBuffer(desc); + if (!device_buffer) { + return {}; + } + if (buffer) { + if (!device_buffer->CopyHostBuffer(static_cast(buffer), + Range{0, length})) { + return {}; + } + } + return std::make_tuple(device_buffer->OnGetContents(), Range{0, length}, + device_buffer); + } + auto old_length = GetLength(); if (old_length + length > kAllocatorBlockSize) { MaybeCreateNewBuffer(length); } + old_length = GetLength(); if (buffer) { ::memmove(GetCurrentBuffer()->OnGetContents() + old_length, buffer, length); diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h index 49fd28c994b01..a4a666cb0fa33 100644 --- a/impeller/core/host_buffer.h +++ b/impeller/core/host_buffer.h @@ -17,7 +17,11 @@ namespace impeller { -class HostBuffer final : public Buffer { +/// The host buffer class manages one more 1024 Kb blocks of device buffer +/// allocations. +/// +/// These are reset per-frame. +class HostBuffer { public: static std::shared_ptr Create( const std::shared_ptr& allocator); @@ -145,10 +149,6 @@ class HostBuffer final : public Buffer { std::shared_ptr state_ = std::make_shared(); - // |Buffer| - std::shared_ptr GetDeviceBuffer( - Allocator& allocator) const override; - [[nodiscard]] BufferView Emplace(const void* buffer, size_t length); explicit HostBuffer(const std::shared_ptr& allocator); diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index b56ccd7c136e6..5f51509d06bde 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -308,9 +308,6 @@ bool EntityPass::Render(ContentContext& renderer, renderer.GetLazyGlyphAtlas()->ResetTextFrames(); renderer.GetRenderTargetCache()->End(); renderer.GetTransientsBuffer().Reset(); -#if IMPELLER_ENABLE_3D - renderer.GetSceneContext()->GetTransientsBuffer().Reset(); -#endif // IMPELLER_ENABLE_3D }); auto root_render_target = render_target; diff --git a/impeller/renderer/backend/gles/buffer_bindings_gles.cc b/impeller/renderer/backend/gles/buffer_bindings_gles.cc index 899cbbb5b7224..168053efdbdd9 100644 --- a/impeller/renderer/backend/gles/buffer_bindings_gles.cc +++ b/impeller/renderer/backend/gles/buffer_bindings_gles.cc @@ -232,8 +232,7 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl, Allocator& transients_allocator, const BufferResource& buffer) { const auto* metadata = buffer.GetMetadata(); - auto device_buffer = - buffer.resource.buffer->GetDeviceBuffer(transients_allocator); + auto device_buffer = buffer.resource.buffer->GetDeviceBuffer(); if (!device_buffer) { VALIDATION_LOG << "Device buffer not found."; return false; diff --git a/impeller/renderer/backend/gles/context_gles.h b/impeller/renderer/backend/gles/context_gles.h index 295cba8bfb9a4..3b1d19870263d 100644 --- a/impeller/renderer/backend/gles/context_gles.h +++ b/impeller/renderer/backend/gles/context_gles.h @@ -5,11 +5,7 @@ #ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_CONTEXT_GLES_H_ #define FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_CONTEXT_GLES_H_ -#include -#include -#include "flutter/fml/macros.h" #include "impeller/base/backend_cast.h" -#include "impeller/core/host_buffer.h" #include "impeller/renderer/backend/gles/allocator_gles.h" #include "impeller/renderer/backend/gles/capabilities_gles.h" #include "impeller/renderer/backend/gles/gpu_tracer_gles.h" @@ -53,7 +49,6 @@ class ContextGLES final : public Context, std::shared_ptr sampler_library_; std::shared_ptr resource_allocator_; std::shared_ptr gpu_tracer_; - std::shared_ptr host_buffer_; // Note: This is stored separately from the ProcTableGLES CapabilitiesGLES // in order to satisfy the Context::GetCapabilities signature which returns diff --git a/impeller/renderer/backend/gles/device_buffer_gles.cc b/impeller/renderer/backend/gles/device_buffer_gles.cc index 0ba29c1b67e31..3cbc9ea5139d9 100644 --- a/impeller/renderer/backend/gles/device_buffer_gles.cc +++ b/impeller/renderer/backend/gles/device_buffer_gles.cc @@ -57,6 +57,10 @@ bool DeviceBufferGLES::OnCopyHostBuffer(const uint8_t* source, return true; } +void DeviceBufferGLES::Flush(std::optional range) const { + generation_++; +} + static GLenum ToTarget(DeviceBufferGLES::BindingType type) { switch (type) { case DeviceBufferGLES::BindingType::kArrayBuffer: diff --git a/impeller/renderer/backend/gles/device_buffer_gles.h b/impeller/renderer/backend/gles/device_buffer_gles.h index 8d884c608b7a8..932a2df69bef0 100644 --- a/impeller/renderer/backend/gles/device_buffer_gles.h +++ b/impeller/renderer/backend/gles/device_buffer_gles.h @@ -38,12 +38,14 @@ class DeviceBufferGLES final [[nodiscard]] bool BindAndUploadDataIfNecessary(BindingType type) const; + void Flush(std::optional range = std::nullopt) const override; + private: ReactorGLES::Ref reactor_; HandleGLES handle_; mutable std::shared_ptr backing_store_; - mutable int32_t generation_ = 0; - mutable int32_t upload_generation_ = -1; + mutable uint32_t generation_ = 0; + mutable uint32_t upload_generation_ = 0; // |DeviceBuffer| uint8_t* OnGetContents() const override; diff --git a/impeller/renderer/backend/gles/render_pass_gles.cc b/impeller/renderer/backend/gles/render_pass_gles.cc index 7209050f64b2b..c13dbb196f627 100644 --- a/impeller/renderer/backend/gles/render_pass_gles.cc +++ b/impeller/renderer/backend/gles/render_pass_gles.cc @@ -386,8 +386,7 @@ struct RenderPassData { return false; } - auto vertex_buffer = - vertex_buffer_view.buffer->GetDeviceBuffer(*transients_allocator); + auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer(); if (!vertex_buffer) { return false; @@ -446,8 +445,7 @@ struct RenderPassData { } else { // Bind the index buffer if necessary. auto index_buffer_view = command.vertex_buffer.index_buffer; - auto index_buffer = - index_buffer_view.buffer->GetDeviceBuffer(*transients_allocator); + auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer(); const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer); if (!index_buffer_gles.BindAndUploadDataIfNecessary( DeviceBufferGLES::BindingType::kElementArrayBuffer)) { diff --git a/impeller/renderer/backend/metal/compute_pass_mtl.mm b/impeller/renderer/backend/metal/compute_pass_mtl.mm index 0cbce56c48c31..3f3f7c3fd18e7 100644 --- a/impeller/renderer/backend/metal/compute_pass_mtl.mm +++ b/impeller/renderer/backend/metal/compute_pass_mtl.mm @@ -171,7 +171,7 @@ static bool Bind(ComputePassBindingsCache& pass, return false; } - auto device_buffer = view.buffer->GetDeviceBuffer(allocator); + auto device_buffer = view.buffer->GetDeviceBuffer(); if (!device_buffer) { return false; } diff --git a/impeller/renderer/backend/metal/context_mtl.h b/impeller/renderer/backend/metal/context_mtl.h index 9a761db5706ae..d7561f52c3f7d 100644 --- a/impeller/renderer/backend/metal/context_mtl.h +++ b/impeller/renderer/backend/metal/context_mtl.h @@ -129,7 +129,6 @@ class ContextMTL final : public Context, #endif // IMPELLER_DEBUG std::deque> tasks_awaiting_gpu_; std::unique_ptr sync_switch_observer_; - std::shared_ptr host_buffer_; bool is_valid_ = false; ContextMTL( diff --git a/impeller/renderer/backend/metal/render_pass_mtl.mm b/impeller/renderer/backend/metal/render_pass_mtl.mm index 3f414ad2a6ced..8b22881000def 100644 --- a/impeller/renderer/backend/metal/render_pass_mtl.mm +++ b/impeller/renderer/backend/metal/render_pass_mtl.mm @@ -364,7 +364,7 @@ static bool Bind(PassBindingsCache& pass, return false; } - auto device_buffer = view.buffer->GetDeviceBuffer(allocator); + auto device_buffer = view.buffer->GetDeviceBuffer(); if (!device_buffer) { return false; } @@ -508,7 +508,7 @@ static bool Bind(PassBindingsCache& pass, if (!index_buffer) { return false; } - auto device_buffer = index_buffer->GetDeviceBuffer(*allocator); + auto device_buffer = index_buffer->GetDeviceBuffer(); if (!device_buffer) { return false; } diff --git a/impeller/renderer/backend/vulkan/binding_helpers_vk.cc b/impeller/renderer/backend/vulkan/binding_helpers_vk.cc index 676980689ce65..6a96d0119c059 100644 --- a/impeller/renderer/backend/vulkan/binding_helpers_vk.cc +++ b/impeller/renderer/backend/vulkan/binding_helpers_vk.cc @@ -70,7 +70,7 @@ static bool BindBuffers(const Bindings& bindings, for (const BufferAndUniformSlot& data : bindings.buffers) { const auto& buffer_view = data.view.resource.buffer; - auto device_buffer = buffer_view->GetDeviceBuffer(allocator); + auto device_buffer = buffer_view->GetDeviceBuffer(); if (!device_buffer) { VALIDATION_LOG << "Failed to get device buffer for vertex binding"; return false; diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 336204108fed5..ee4df3534b180 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -158,9 +158,9 @@ void ContextVK::Setup(Settings settings) { // (It's possible 2 is overly conservative and we can simplify this) auto enable_validation = false; - #if defined(FML_OS_ANDROID) && !defined(NDEBUG) - enable_validation = true; - #endif +#if defined(FML_OS_ANDROID) && !defined(NDEBUG) + enable_validation = true; +#endif auto caps = std::shared_ptr(new CapabilitiesVK(enable_validation)); diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index efd6240b66ea3..ac059ebed237c 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -13,7 +13,6 @@ #include "fml/thread.h" #include "impeller/base/backend_cast.h" #include "impeller/core/formats.h" -#include "impeller/core/host_buffer.h" #include "impeller/renderer/backend/vulkan/command_pool_vk.h" #include "impeller/renderer/backend/vulkan/device_holder.h" #include "impeller/renderer/backend/vulkan/pipeline_library_vk.h" @@ -198,7 +197,6 @@ class ContextVK final : public Context, std::unique_ptr queue_submit_thread_; std::shared_ptr gpu_tracer_; std::shared_ptr descriptor_pool_recycler_; - std::shared_ptr host_buffer_; bool sync_presentation_ = false; const uint64_t hash_; diff --git a/impeller/renderer/backend/vulkan/device_buffer_vk.cc b/impeller/renderer/backend/vulkan/device_buffer_vk.cc index 9a8792b2dfeff..9aec90beb3038 100644 --- a/impeller/renderer/backend/vulkan/device_buffer_vk.cc +++ b/impeller/renderer/backend/vulkan/device_buffer_vk.cc @@ -6,6 +6,7 @@ #include "flutter/fml/trace_event.h" #include "impeller/renderer/backend/vulkan/context_vk.h" +#include "vulkan/vulkan_core.h" namespace impeller { diff --git a/impeller/renderer/backend/vulkan/render_pass_vk.cc b/impeller/renderer/backend/vulkan/render_pass_vk.cc index bf0a54e9cefa3..67066c0878d0c 100644 --- a/impeller/renderer/backend/vulkan/render_pass_vk.cc +++ b/impeller/renderer/backend/vulkan/render_pass_vk.cc @@ -410,7 +410,7 @@ static bool EncodeCommand(const Context& context, } auto& allocator = *context.GetResourceAllocator(); - auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer(allocator); + auto vertex_buffer = vertex_buffer_view.buffer->GetDeviceBuffer(); if (!vertex_buffer) { VALIDATION_LOG << "Failed to acquire device buffer" @@ -435,7 +435,7 @@ static bool EncodeCommand(const Context& context, return false; } - auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer(allocator); + auto index_buffer = index_buffer_view.buffer->GetDeviceBuffer(); if (!index_buffer) { VALIDATION_LOG << "Failed to acquire device buffer" << " for index buffer view"; diff --git a/impeller/scene/scene.cc b/impeller/scene/scene.cc index ca7202afb04b4..172e1c1e4a067 100644 --- a/impeller/scene/scene.cc +++ b/impeller/scene/scene.cc @@ -8,6 +8,7 @@ #include #include "flutter/fml/logging.h" +#include "fml/closure.h" #include "impeller/renderer/render_target.h" #include "impeller/scene/scene_context.h" #include "impeller/scene/scene_encoder.h" @@ -32,6 +33,9 @@ Node& Scene::GetRoot() { bool Scene::Render(const RenderTarget& render_target, const Matrix& camera_transform) { + fml::ScopedCleanupClosure reset_state( + [context = scene_context_]() { context->GetTransientsBuffer().Reset(); }); + // Collect the render commands from the scene. SceneEncoder encoder; if (!root_.Render(encoder, diff --git a/lib/gpu/render_pass.cc b/lib/gpu/render_pass.cc index 5ea10486a579c..2775818624f25 100644 --- a/lib/gpu/render_pass.cc +++ b/lib/gpu/render_pass.cc @@ -236,7 +236,7 @@ static void BindVertexBuffer(flutter::gpu::RenderPass* wrapper, int vertex_count) { auto& vertex_buffer = wrapper->GetVertexBuffer(); vertex_buffer.vertex_buffer = impeller::BufferView{ - .buffer = buffer->GetBuffer(), + .buffer = nullptr, .range = impeller::Range(offset_in_bytes, length_in_bytes), }; // If the index type is set, then the `vertex_count` becomes the index @@ -281,7 +281,7 @@ static void BindIndexBuffer(flutter::gpu::RenderPass* wrapper, int index_count) { auto& vertex_buffer = wrapper->GetVertexBuffer(); vertex_buffer.index_buffer = impeller::BufferView{ - .buffer = buffer->GetBuffer(), + .buffer = nullptr, .range = impeller::Range(offset_in_bytes, length_in_bytes), }; vertex_buffer.index_type = flutter::gpu::ToImpellerIndexType(index_type); @@ -331,7 +331,7 @@ static bool BindUniform(flutter::gpu::RenderPass* wrapper, return command.BindResource( shader->GetShaderStage(), uniform_struct->slot, uniform_struct->metadata, impeller::BufferView{ - .buffer = buffer->GetBuffer(), + .buffer = nullptr, .range = impeller::Range(offset_in_bytes, length_in_bytes), }); } From 65dda4bb9b538135b906a513a294589910c00473 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 09:55:22 -0800 Subject: [PATCH 12/21] fix const. --- impeller/core/device_buffer.cc | 2 +- impeller/core/device_buffer.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/impeller/core/device_buffer.cc b/impeller/core/device_buffer.cc index 9637b83108d4d..5c6ecf4077ed3 100644 --- a/impeller/core/device_buffer.cc +++ b/impeller/core/device_buffer.cc @@ -15,7 +15,7 @@ std::shared_ptr DeviceBuffer::GetDeviceBuffer() const { return shared_from_this(); } -void DeviceBuffer::Flush(std::optional range) {} +void DeviceBuffer::Flush(std::optional range) const {} BufferView DeviceBuffer::AsBufferView() const { BufferView view; diff --git a/impeller/core/device_buffer.h b/impeller/core/device_buffer.h index 5ab542d3d57a2..7f0cb99f3ba3f 100644 --- a/impeller/core/device_buffer.h +++ b/impeller/core/device_buffer.h @@ -47,11 +47,11 @@ class DeviceBuffer : public Buffer, /// Make any pending writes visible to the GPU. /// /// This method must be called if the device pointer provided by - /// [OnGetContents] is written to, and the host memory allocation is not host - /// coherent. + /// [OnGetContents] is written to without using [CopyHostBuffer]. On Devices + /// with coherent host memory, this method will not perform extra work. /// /// If the range is not provided, the entire buffer is flushed. - virtual void Flush(std::optional range = std::nullopt); + virtual void Flush(std::optional range = std::nullopt) const; protected: const DeviceBufferDescriptor desc_; From b0d6e59d90460539f1e7559878f4cbcafa217b2f Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 10:27:09 -0800 Subject: [PATCH 13/21] Add more unittests --- impeller/core/host_buffer.cc | 26 ++++++-- impeller/core/host_buffer.h | 19 +++++- .../entity/contents/host_buffer_unittests.cc | 66 +++++++++++++++++++ .../backend/metal/device_buffer_mtl.h | 3 + .../backend/metal/device_buffer_mtl.mm | 10 +++ 5 files changed, 115 insertions(+), 9 deletions(-) diff --git a/impeller/core/host_buffer.cc b/impeller/core/host_buffer.cc index c400f03ec28d3..bc66d2c3fe12a 100644 --- a/impeller/core/host_buffer.cc +++ b/impeller/core/host_buffer.cc @@ -27,7 +27,9 @@ HostBuffer::HostBuffer(const std::shared_ptr& allocator) { DeviceBufferDescriptor desc; desc.size = kAllocatorBlockSize; desc.storage_mode = StorageMode::kHostVisible; - state_->device_buffers.push_back(allocator->CreateBuffer(desc)); + for (auto i = 0u; i < kHostBufferArenaSize; i++) { + state_->device_buffers[i].push_back(allocator->CreateBuffer(desc)); + } } HostBuffer::~HostBuffer() = default; @@ -64,6 +66,14 @@ BufferView HostBuffer::Emplace(size_t length, return BufferView{std::move(device_buffer), data, range}; } +HostBuffer::TestStateQuery HostBuffer::GetStateForTest() { + return HostBuffer::TestStateQuery{ + .current_frame = state_->frame_index, + .current_buffer = state_->current_buffer, + .total_buffer_count = state_->device_buffers[state_->frame_index].size(), + }; +} + void HostBuffer::Reset() { state_->Reset(); } @@ -74,7 +84,7 @@ void HostBuffer::HostBufferState::MaybeCreateNewBuffer(size_t required_size) { DeviceBufferDescriptor desc; desc.size = kAllocatorBlockSize; desc.storage_mode = StorageMode::kHostVisible; - device_buffers.push_back(allocator->CreateBuffer(desc)); + device_buffers[frame_index].push_back(allocator->CreateBuffer(desc)); } current_buffer++; offset = 0; @@ -176,13 +186,15 @@ HostBuffer::HostBufferState::Emplace(const void* buffer, } void HostBuffer::HostBufferState::Reset() { + // When resetting the host buffer state at the end of the frame, check if + // there are any unused buffers and remove them. + while (device_buffers[frame_index].size() > current_buffer + 1) { + device_buffers[frame_index].pop_back(); + } + 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)); + frame_index = (frame_index + 1) % kHostBufferArenaSize; } } // namespace impeller diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h index a4a666cb0fa33..9ed0e56efdcee 100644 --- a/impeller/core/host_buffer.h +++ b/impeller/core/host_buffer.h @@ -17,6 +17,9 @@ namespace impeller { +/// Approximately the same size as the max frames in flight. +static const constexpr size_t kHostBufferArenaSize = 3u; + /// The host buffer class manages one more 1024 Kb blocks of device buffer /// allocations. /// @@ -119,6 +122,16 @@ class HostBuffer { /// reused. void Reset(); + /// Test only internal state. + struct TestStateQuery { + size_t current_frame; + size_t current_buffer; + size_t total_buffer_count; + }; + + /// @brief Retrieve internal buffer state for test expectations. + TestStateQuery GetStateForTest(); + private: struct HostBufferState { [[nodiscard]] std::tuple> @@ -137,13 +150,15 @@ class HostBuffer { void MaybeCreateNewBuffer(size_t required_size); std::shared_ptr GetCurrentBuffer() { - return device_buffers[current_buffer]; + return device_buffers[frame_index][current_buffer]; } std::shared_ptr allocator; - std::vector> device_buffers; + std::array>, kHostBufferArenaSize> + device_buffers; size_t current_buffer = 0u; size_t offset = 0u; + size_t frame_index = 0u; std::string label; }; diff --git a/impeller/entity/contents/host_buffer_unittests.cc b/impeller/entity/contents/host_buffer_unittests.cc index c73451ebbc59f..1d3f04849b516 100644 --- a/impeller/entity/contents/host_buffer_unittests.cc +++ b/impeller/entity/contents/host_buffer_unittests.cc @@ -67,5 +67,71 @@ TEST_P(HostBufferTest, CanEmplaceWithAlignment) { } } +TEST_P(HostBufferTest, HostBufferInitialState) { + auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); + + EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); + EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u); +} + +TEST_P(HostBufferTest, ResetIncrementsFrameCounter) { + auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); + + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); + + buffer->Reset(); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 1u); + + buffer->Reset(); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 2u); + + buffer->Reset(); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); +} + +TEST_P(HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer) { + auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); + + // Emplace an amount larger than the block size, to verify that the host + // buffer does not create a buffer. + auto buffer_view = buffer->Emplace(1024000 + 10, 0, [](uint8_t* data) {}); + + EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); + EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u); +} + +TEST_P(HostBufferTest, UnusedBuffersAreDiscardedWhenResetting) { + auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); + + // Emplace two large allocations to force the allocation of a second buffer. + auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {}); + auto buffer_view_b = buffer->Emplace(1020000, 0, [](uint8_t* data) {}); + + EXPECT_EQ(buffer->GetStateForTest().current_buffer, 1u); + EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); + + // Reset until we get back to this frame. + for (auto i = 0; i < 3; i++) { + buffer->Reset(); + } + + EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u); + EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 2u); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); + + // Now when we reset, the buffer should get dropped. + // Reset until we get back to this frame. + for (auto i = 0; i < 3; i++) { + buffer->Reset(); + } + + EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u); + EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); +} + } // namespace testing } // namespace impeller diff --git a/impeller/renderer/backend/metal/device_buffer_mtl.h b/impeller/renderer/backend/metal/device_buffer_mtl.h index 93e548895ef8c..936bc449e0a9c 100644 --- a/impeller/renderer/backend/metal/device_buffer_mtl.h +++ b/impeller/renderer/backend/metal/device_buffer_mtl.h @@ -52,6 +52,9 @@ class DeviceBufferMTL final : public DeviceBuffer, // |DeviceBuffer| bool SetLabel(const std::string& label, Range range) override; + // |DeviceBuffer| + void Flush(std::optional range) const override; + DeviceBufferMTL(const DeviceBufferMTL&) = delete; DeviceBufferMTL& operator=(const DeviceBufferMTL&) = delete; diff --git a/impeller/renderer/backend/metal/device_buffer_mtl.mm b/impeller/renderer/backend/metal/device_buffer_mtl.mm index 860e216264975..c2ea8d89ef731 100644 --- a/impeller/renderer/backend/metal/device_buffer_mtl.mm +++ b/impeller/renderer/backend/metal/device_buffer_mtl.mm @@ -78,6 +78,16 @@ return true; } +void DeviceBufferMTL::Flush(std::optional range) const { +#if !FML_OS_IOS + auto flush_range = range.value_or(Range{0, GetDeviceBufferDescriptor().size}); + if (storage_mode_ == MTLStorageModeManaged) { + [buffer_ + didModifyRange:NSMakeRange(flush_range.offset, flush_range.length)]; + } +#endif +} + bool DeviceBufferMTL::SetLabel(const std::string& label) { if (label.empty()) { return false; From ad16416b0bf2f785f7243f0f73cdf796d884b958 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 11:08:53 -0800 Subject: [PATCH 14/21] include array --- impeller/core/host_buffer.h | 1 + 1 file changed, 1 insertion(+) diff --git a/impeller/core/host_buffer.h b/impeller/core/host_buffer.h index 9ed0e56efdcee..9d50bc5051d64 100644 --- a/impeller/core/host_buffer.h +++ b/impeller/core/host_buffer.h @@ -6,6 +6,7 @@ #define FLUTTER_IMPELLER_CORE_HOST_BUFFER_H_ #include +#include #include #include #include From 9d4867e5787617b080350ac5b11bbd6c985af45c Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 11:29:01 -0800 Subject: [PATCH 15/21] fix flutter GPU. --- lib/gpu/device_buffer.h | 2 +- lib/gpu/host_buffer.cc | 13 +++++++++---- lib/gpu/host_buffer.h | 3 ++- lib/gpu/lib/src/buffer.dart | 8 ++++---- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/lib/gpu/device_buffer.h b/lib/gpu/device_buffer.h index 707d01f150ba4..a2b262b3795c9 100644 --- a/lib/gpu/device_buffer.h +++ b/lib/gpu/device_buffer.h @@ -8,7 +8,7 @@ #include "flutter/lib/gpu/context.h" #include "flutter/lib/gpu/export.h" #include "flutter/lib/ui/dart_wrapper.h" -#include "impeller/core/device_buffer_descriptor.h" + #include "third_party/tonic/typed_data/dart_byte_data.h" namespace flutter { diff --git a/lib/gpu/host_buffer.cc b/lib/gpu/host_buffer.cc index b03878d16c282..6d76464c6c787 100644 --- a/lib/gpu/host_buffer.cc +++ b/lib/gpu/host_buffer.cc @@ -4,6 +4,9 @@ #include "flutter/lib/gpu/host_buffer.h" +#include + +#include "dart_api.h" #include "impeller/core/host_buffer.h" #include "impeller/core/platform.h" #include "third_party/tonic/typed_data/dart_byte_data.h" @@ -13,8 +16,9 @@ namespace gpu { IMPLEMENT_WRAPPERTYPEINFO(flutter_gpu, HostBuffer); -HostBuffer::HostBuffer() - : host_buffer_(impeller::HostBuffer::Create(nullptr)) {} +HostBuffer::HostBuffer(Context* context) + : host_buffer_(impeller::HostBuffer::Create( + context->GetContext()->GetResourceAllocator())) {} HostBuffer::~HostBuffer() = default; @@ -43,8 +47,9 @@ std::optional HostBuffer::GetBufferViewForOffset( /// Exports /// -void InternalFlutterGpu_HostBuffer_Initialize(Dart_Handle wrapper) { - auto res = fml::MakeRefCounted(); +void InternalFlutterGpu_HostBuffer_Initialize(Dart_Handle wrapper, + flutter::gpu::Context* context) { + auto res = fml::MakeRefCounted(context); res->AssociateWithDartWrapper(wrapper); } diff --git a/lib/gpu/host_buffer.h b/lib/gpu/host_buffer.h index 7b25f5182c721..75d33c739ac39 100644 --- a/lib/gpu/host_buffer.h +++ b/lib/gpu/host_buffer.h @@ -9,6 +9,7 @@ #include "flutter/lib/ui/dart_wrapper.h" #include "impeller/core/buffer_view.h" #include "impeller/core/host_buffer.h" +#include "lib/gpu/context.h" #include "third_party/tonic/typed_data/dart_byte_data.h" namespace flutter { @@ -19,7 +20,7 @@ class HostBuffer : public RefCountedDartWrappable { FML_FRIEND_MAKE_REF_COUNTED(HostBuffer); public: - explicit HostBuffer(); + explicit HostBuffer(Context* context); ~HostBuffer() override; diff --git a/lib/gpu/lib/src/buffer.dart b/lib/gpu/lib/src/buffer.dart index 0e0edd7b50132..abed1a7a04949 100644 --- a/lib/gpu/lib/src/buffer.dart +++ b/lib/gpu/lib/src/buffer.dart @@ -135,8 +135,8 @@ base class DeviceBuffer extends NativeFieldWrapperClass1 with Buffer { /// and automatically inserts padding between emplaced data if necessary. base class HostBuffer extends NativeFieldWrapperClass1 with Buffer { /// Creates a new HostBuffer. - HostBuffer() { - _initialize(); + HostBuffer(GpuContext gpuContext) { + _initialize(gpuContext); } @override @@ -161,9 +161,9 @@ base class HostBuffer extends NativeFieldWrapperClass1 with Buffer { } /// Wrap with native counterpart. - @Native( + @Native( symbol: 'InternalFlutterGpu_HostBuffer_Initialize') - external void _initialize(); + external void _initialize(GpuContext gpuContext); /// Append byte data to the end of the [HostBuffer] and produce a [BufferView] /// that references the new data in the buffer. From b132dd7b251f013e570f6420c6bd6da3b1bc09da Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 12:34:20 -0800 Subject: [PATCH 16/21] fix fixtures. --- impeller/fixtures/dart_tests.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/impeller/fixtures/dart_tests.dart b/impeller/fixtures/dart_tests.dart index 19596fed70375..8105f04b2e5ce 100644 --- a/impeller/fixtures/dart_tests.dart +++ b/impeller/fixtures/dart_tests.dart @@ -21,7 +21,7 @@ void instantiateDefaultContext() { @pragma('vm:entry-point') void canEmplaceHostBuffer() { - final gpu.HostBuffer hostBuffer = gpu.HostBuffer(); + final gpu.HostBuffer hostBuffer = gpu.HostBuffer(gpu.gpuContext); final gpu.BufferView view0 = hostBuffer .emplace(Int8List.fromList([0, 1, 2, 3]).buffer.asByteData()); @@ -216,7 +216,7 @@ void uniformBindFailsForInvalidHostBufferOffset() { final gpu.RenderPipeline pipeline = createUnlitRenderPipeline(); encoder.bindPipeline(pipeline); - final gpu.HostBuffer transients = gpu.HostBuffer(); + final gpu.HostBuffer transients = gpu.HostBuffer(gpu.gpuContext); final gpu.BufferView vertInfoData = transients.emplace(float32([ 1, 0, 0, 0, // mvp 0, 1, 0, 0, // mvp @@ -262,7 +262,7 @@ void canCreateRenderPassAndSubmit() { encoder.setColorBlendEnable(true); encoder.setColorBlendEquation(gpu.ColorBlendEquation()); - final gpu.HostBuffer transients = gpu.HostBuffer(); + final gpu.HostBuffer transients = gpu.HostBuffer(gpu.gpuContext); final gpu.BufferView vertices = transients.emplace(float32([ -0.5, -0.5, // 0.5, 0.5, // From 5a553f1eb926b906777d4b4540ef930009f44df8 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 12:50:56 -0800 Subject: [PATCH 17/21] fix enable vk validations. --- impeller/renderer/backend/vulkan/context_vk.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index ee4df3534b180..6c1804dd74022 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -156,7 +156,7 @@ void ContextVK::Setup(Settings settings) { // 1. The user has explicitly enabled it. // 2. We are in a combination of debug mode, and running on Android. // (It's possible 2 is overly conservative and we can simplify this) - auto enable_validation = false; + auto enable_validation = settings.enable_validation; #if defined(FML_OS_ANDROID) && !defined(NDEBUG) enable_validation = true; From d4a32ede82ac50210e895910bdb6510f445dff20 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 15:16:25 -0800 Subject: [PATCH 18/21] fix tests and numerous off by ones. --- impeller/core/host_buffer.cc | 19 ++++++++++--------- .../entity/contents/host_buffer_unittests.cc | 15 ++++++++++++++- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/impeller/core/host_buffer.cc b/impeller/core/host_buffer.cc index bc66d2c3fe12a..fdfc30d2e26a0 100644 --- a/impeller/core/host_buffer.cc +++ b/impeller/core/host_buffer.cc @@ -79,14 +79,14 @@ void HostBuffer::Reset() { } void HostBuffer::HostBufferState::MaybeCreateNewBuffer(size_t required_size) { - if (current_buffer + 1 >= device_buffers.size()) { + current_buffer++; + if (current_buffer >= device_buffers[frame_index].size()) { FML_DCHECK(required_size <= kAllocatorBlockSize); DeviceBufferDescriptor desc; desc.size = kAllocatorBlockSize; desc.storage_mode = StorageMode::kHostVisible; device_buffers[frame_index].push_back(allocator->CreateBuffer(desc)); } - current_buffer++; offset = 0; } @@ -94,27 +94,28 @@ std::tuple> HostBuffer::HostBufferState::Emplace(size_t length, size_t align, const EmplaceProc& cb) { + if (!cb) { + return {}; + } + // If the requested allocation is bigger than the block size, create a one-off // device buffer and write to that. if (length > kAllocatorBlockSize) { DeviceBufferDescriptor desc; - desc.size = kAllocatorBlockSize; + desc.size = length; desc.storage_mode = StorageMode::kHostVisible; auto device_buffer = allocator->CreateBuffer(desc); if (!device_buffer) { return {}; } if (cb) { - cb(GetCurrentBuffer()->OnGetContents()); - GetCurrentBuffer()->Flush(Range{0, length}); + cb(device_buffer->OnGetContents()); + device_buffer->Flush(Range{0, length}); } return std::make_tuple(device_buffer->OnGetContents(), Range{0, length}, device_buffer); } - if (!cb) { - return {}; - } auto old_length = GetLength(); if (old_length + length > kAllocatorBlockSize) { MaybeCreateNewBuffer(length); @@ -135,7 +136,7 @@ HostBuffer::HostBufferState::Emplace(const void* buffer, size_t length) { // device buffer and write to that. if (length > kAllocatorBlockSize) { DeviceBufferDescriptor desc; - desc.size = kAllocatorBlockSize; + desc.size = length; desc.storage_mode = StorageMode::kHostVisible; auto device_buffer = allocator->CreateBuffer(desc); if (!device_buffer) { diff --git a/impeller/entity/contents/host_buffer_unittests.cc b/impeller/entity/contents/host_buffer_unittests.cc index 1d3f04849b516..3ae3c285e07c0 100644 --- a/impeller/entity/contents/host_buffer_unittests.cc +++ b/impeller/entity/contents/host_buffer_unittests.cc @@ -90,7 +90,8 @@ TEST_P(HostBufferTest, ResetIncrementsFrameCounter) { EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); } -TEST_P(HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer) { +TEST_P(HostBufferTest, + EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback) { auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); // Emplace an amount larger than the block size, to verify that the host @@ -102,6 +103,18 @@ TEST_P(HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer) { EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u); } +TEST_P(HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer) { + auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); + + // Emplace an amount larger than the block size, to verify that the host + // buffer does not create a buffer. + auto buffer_view = buffer->Emplace(nullptr, 1024000 + 10, 0); + + EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u); + EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u); + EXPECT_EQ(buffer->GetStateForTest().total_buffer_count, 1u); +} + TEST_P(HostBufferTest, UnusedBuffersAreDiscardedWhenResetting) { auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator()); From 2ccdb5902b314dc40db0a167823468e809d93392 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 16:38:14 -0800 Subject: [PATCH 19/21] attempt to reset only on render frames. --- impeller/entity/contents/content_context.cc | 4 ++++ impeller/entity/entity_pass.cc | 1 - impeller/renderer/context.h | 12 ++++++++++++ impeller/renderer/renderer.cc | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 51bb3f1e3f93a..1b8d937a2341a 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -189,6 +189,10 @@ ContentContext::ContentContext( if (!context_ || !context_->IsValid()) { return; } + // Register frame end callback to reset transient host buffer state. + context_->AddPerFrameCompleteTask( + [host_buffer = host_buffer_]() { host_buffer->Reset(); }); + auto options = ContentContextOptions{ .sample_count = SampleCount::kCount4, .color_attachment_pixel_format = diff --git a/impeller/entity/entity_pass.cc b/impeller/entity/entity_pass.cc index 5f51509d06bde..67e343de8a6d5 100644 --- a/impeller/entity/entity_pass.cc +++ b/impeller/entity/entity_pass.cc @@ -307,7 +307,6 @@ bool EntityPass::Render(ContentContext& renderer, fml::ScopedCleanupClosure reset_state([&renderer]() { renderer.GetLazyGlyphAtlas()->ResetTextFrames(); renderer.GetRenderTargetCache()->End(); - renderer.GetTransientsBuffer().Reset(); }); auto root_render_target = render_target; diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index 60ecbc5dbadb9..9d475efd84f62 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -180,6 +180,12 @@ class Context { /// pending work. virtual void SetSyncPresentation(bool value) {} + void OnFrameComplete() { + for (const auto& cb : per_frame_task_) { + cb(); + } + } + CaptureContext capture; /// Stores a task on the `ContextMTL` that is awaiting access for the GPU. @@ -195,9 +201,15 @@ class Context { FML_CHECK(false && "not supported in this context"); } + void AddPerFrameCompleteTask(const std::function& task) { + per_frame_task_.emplace_back(task); + } + protected: Context(); + std::vector> per_frame_task_; + private: Context(const Context&) = delete; diff --git a/impeller/renderer/renderer.cc b/impeller/renderer/renderer.cc index abc5dc2b7ce75..e4a9aacf0ac4d 100644 --- a/impeller/renderer/renderer.cc +++ b/impeller/renderer/renderer.cc @@ -54,6 +54,7 @@ bool Renderer::Render(std::unique_ptr surface, const auto present_result = surface->Present(); frames_in_flight_sema_->Signal(); + context_->OnFrameComplete(); return present_result; } From 809adf51692de8645474f0930afc41f87c9596d9 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 17:06:14 -0800 Subject: [PATCH 20/21] ++ --- impeller/aiks/aiks_context.cc | 1 + impeller/entity/contents/content_context.cc | 3 --- impeller/renderer/context.h | 10 ---------- impeller/renderer/renderer.cc | 1 - 4 files changed, 1 insertion(+), 14 deletions(-) diff --git a/impeller/aiks/aiks_context.cc b/impeller/aiks/aiks_context.cc index 86baab74d7953..64b7d440c8b24 100644 --- a/impeller/aiks/aiks_context.cc +++ b/impeller/aiks/aiks_context.cc @@ -48,6 +48,7 @@ bool AiksContext::Render(const Picture& picture, RenderTarget& render_target) { if (picture.pass) { return picture.pass->Render(*content_context_, render_target); } + content_context_->GetTransientsBuffer().Reset(); return true; } diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 1b8d937a2341a..17c194e64e022 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -189,9 +189,6 @@ ContentContext::ContentContext( if (!context_ || !context_->IsValid()) { return; } - // Register frame end callback to reset transient host buffer state. - context_->AddPerFrameCompleteTask( - [host_buffer = host_buffer_]() { host_buffer->Reset(); }); auto options = ContentContextOptions{ .sample_count = SampleCount::kCount4, diff --git a/impeller/renderer/context.h b/impeller/renderer/context.h index 9d475efd84f62..1f80c296e8fc4 100644 --- a/impeller/renderer/context.h +++ b/impeller/renderer/context.h @@ -180,12 +180,6 @@ class Context { /// pending work. virtual void SetSyncPresentation(bool value) {} - void OnFrameComplete() { - for (const auto& cb : per_frame_task_) { - cb(); - } - } - CaptureContext capture; /// Stores a task on the `ContextMTL` that is awaiting access for the GPU. @@ -201,10 +195,6 @@ class Context { FML_CHECK(false && "not supported in this context"); } - void AddPerFrameCompleteTask(const std::function& task) { - per_frame_task_.emplace_back(task); - } - protected: Context(); diff --git a/impeller/renderer/renderer.cc b/impeller/renderer/renderer.cc index e4a9aacf0ac4d..abc5dc2b7ce75 100644 --- a/impeller/renderer/renderer.cc +++ b/impeller/renderer/renderer.cc @@ -54,7 +54,6 @@ bool Renderer::Render(std::unique_ptr surface, const auto present_result = surface->Present(); frames_in_flight_sema_->Signal(); - context_->OnFrameComplete(); return present_result; } From ac120148b23cdb88815b5cd47a200cd1b5331236 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Tue, 9 Jan 2024 20:51:59 -0800 Subject: [PATCH 21/21] add flag to aiks_context::Render to conditionally reset host buffers. --- impeller/aiks/aiks_context.cc | 8 ++++++-- impeller/aiks/aiks_context.h | 4 +++- impeller/aiks/aiks_playground.cc | 2 +- impeller/aiks/picture.cc | 2 +- impeller/display_list/dl_playground.cc | 2 +- shell/gpu/gpu_surface_gl_impeller.cc | 3 ++- shell/gpu/gpu_surface_metal_impeller.mm | 14 +++++++------- shell/gpu/gpu_surface_vulkan_impeller.cc | 3 ++- shell/platform/embedder/embedder_external_view.cc | 2 +- 9 files changed, 24 insertions(+), 16 deletions(-) diff --git a/impeller/aiks/aiks_context.cc b/impeller/aiks/aiks_context.cc index 64b7d440c8b24..01da062362acd 100644 --- a/impeller/aiks/aiks_context.cc +++ b/impeller/aiks/aiks_context.cc @@ -40,7 +40,9 @@ ContentContext& AiksContext::GetContentContext() const { return *content_context_; } -bool AiksContext::Render(const Picture& picture, RenderTarget& render_target) { +bool AiksContext::Render(const Picture& picture, + RenderTarget& render_target, + bool reset_host_buffer) { if (!IsValid()) { return false; } @@ -48,7 +50,9 @@ bool AiksContext::Render(const Picture& picture, RenderTarget& render_target) { if (picture.pass) { return picture.pass->Render(*content_context_, render_target); } - content_context_->GetTransientsBuffer().Reset(); + if (reset_host_buffer) { + content_context_->GetTransientsBuffer().Reset(); + } return true; } diff --git a/impeller/aiks/aiks_context.h b/impeller/aiks/aiks_context.h index 650465d770dfc..ad8d6429c4d01 100644 --- a/impeller/aiks/aiks_context.h +++ b/impeller/aiks/aiks_context.h @@ -39,7 +39,9 @@ class AiksContext { ContentContext& GetContentContext() const; - bool Render(const Picture& picture, RenderTarget& render_target); + bool Render(const Picture& picture, + RenderTarget& render_target, + bool reset_host_buffer); private: std::shared_ptr context_; diff --git a/impeller/aiks/aiks_playground.cc b/impeller/aiks/aiks_playground.cc index b9ed2a828e7ae..8714b54697ac2 100644 --- a/impeller/aiks/aiks_playground.cc +++ b/impeller/aiks/aiks_playground.cc @@ -53,7 +53,7 @@ bool AiksPlayground::OpenPlaygroundHere(AiksPlaygroundCallback callback) { if (!picture.has_value()) { return false; } - return renderer.Render(*picture, render_target); + return renderer.Render(*picture, render_target, true); }); } diff --git a/impeller/aiks/picture.cc b/impeller/aiks/picture.cc index 907bbf6ca49ba..ea07dfd27a58c 100644 --- a/impeller/aiks/picture.cc +++ b/impeller/aiks/picture.cc @@ -84,7 +84,7 @@ std::shared_ptr Picture::RenderToTexture( return nullptr; } - if (!context.Render(*this, target)) { + if (!context.Render(*this, target, false)) { VALIDATION_LOG << "Could not render Picture to Texture."; return nullptr; } diff --git a/impeller/display_list/dl_playground.cc b/impeller/display_list/dl_playground.cc index ba94de2be370a..a9c510a076701 100644 --- a/impeller/display_list/dl_playground.cc +++ b/impeller/display_list/dl_playground.cc @@ -51,7 +51,7 @@ bool DlPlayground::OpenPlaygroundHere(DisplayListPlaygroundCallback callback) { list->Dispatch(dispatcher); auto picture = dispatcher.EndRecordingAsPicture(); - return context.Render(picture, render_target); + return context.Render(picture, render_target, true); }); } diff --git a/shell/gpu/gpu_surface_gl_impeller.cc b/shell/gpu/gpu_surface_gl_impeller.cc index 19e2669c997a2..53c457bdda6a4 100644 --- a/shell/gpu/gpu_surface_gl_impeller.cc +++ b/shell/gpu/gpu_surface_gl_impeller.cc @@ -122,7 +122,8 @@ std::unique_ptr GPUSurfaceGLImpeller::AcquireFrame( fml::MakeCopyable( [aiks_context, picture = std::move(picture)]( impeller::RenderTarget& render_target) -> bool { - return aiks_context->Render(picture, render_target); + return aiks_context->Render(picture, render_target, + /*reset_host_buffer=*/true); })); }); diff --git a/shell/gpu/gpu_surface_metal_impeller.mm b/shell/gpu/gpu_surface_metal_impeller.mm index 94302399c8481..e08587ef64461 100644 --- a/shell/gpu/gpu_surface_metal_impeller.mm +++ b/shell/gpu/gpu_surface_metal_impeller.mm @@ -163,7 +163,7 @@ std::move(surface), fml::MakeCopyable([aiks_context, picture = std::move(picture)]( impeller::RenderTarget& render_target) -> bool { - return aiks_context->Render(picture, render_target); + return aiks_context->Render(picture, render_target, /*reset_host_buffer=*/true); })); }); @@ -257,12 +257,12 @@ display_list->Dispatch(impeller_dispatcher, sk_cull_rect); auto picture = impeller_dispatcher.EndRecordingAsPicture(); - bool render_result = - renderer->Render(std::move(surface), - fml::MakeCopyable([aiks_context, picture = std::move(picture)]( - impeller::RenderTarget& render_target) -> bool { - return aiks_context->Render(picture, render_target); - })); + bool render_result = renderer->Render( + std::move(surface), + fml::MakeCopyable([aiks_context, picture = std::move(picture)]( + impeller::RenderTarget& render_target) -> bool { + return aiks_context->Render(picture, render_target, /*reset_host_buffer=*/true); + })); if (!render_result) { FML_LOG(ERROR) << "Failed to render Impeller frame"; return false; diff --git a/shell/gpu/gpu_surface_vulkan_impeller.cc b/shell/gpu/gpu_surface_vulkan_impeller.cc index 917b5f0e6e11d..cf2733baab5ea 100644 --- a/shell/gpu/gpu_surface_vulkan_impeller.cc +++ b/shell/gpu/gpu_surface_vulkan_impeller.cc @@ -94,7 +94,8 @@ std::unique_ptr GPUSurfaceVulkanImpeller::AcquireFrame( fml::MakeCopyable( [aiks_context, picture = std::move(picture)]( impeller::RenderTarget& render_target) -> bool { - return aiks_context->Render(picture, render_target); + return aiks_context->Render(picture, render_target, + /*reset_host_buffer=*/true); })); }); diff --git a/shell/platform/embedder/embedder_external_view.cc b/shell/platform/embedder/embedder_external_view.cc index 23ecd22415424..592b89f9fdba2 100644 --- a/shell/platform/embedder/embedder_external_view.cc +++ b/shell/platform/embedder/embedder_external_view.cc @@ -107,7 +107,7 @@ bool EmbedderExternalView::Render(const EmbedderRenderTarget& render_target, auto dispatcher = impeller::DlDispatcher(); dispatcher.drawDisplayList(dl_builder.Build(), 1); return aiks_context->Render(dispatcher.EndRecordingAsPicture(), - *impeller_target); + *impeller_target, /*reset_host_buffer=*/true); } #endif // IMPELLER_SUPPORTS_RENDERING