reland: Allow BufferViews to have non-owning references to DeviceBuffers (flutter/engine#56286)

relands https://github.com/flutter/engine/pull/56224

[C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
This commit is contained in:
gaaclarke 2024-10-31 16:46:55 -07:00 committed by GitHub
parent bad046bd6e
commit f81ed55e63
41 changed files with 415 additions and 198 deletions

View File

@ -136,6 +136,7 @@
../../../flutter/impeller/compiler/shader_bundle_unittests.cc
../../../flutter/impeller/compiler/switches_unittests.cc
../../../flutter/impeller/core/allocator_unittests.cc
../../../flutter/impeller/core/buffer_view_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_atlas_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_basic_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_blend_unittests.cc

View File

@ -42900,6 +42900,7 @@ ORIGIN: ../../../flutter/impeller/core/formats.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/core/formats.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/core/host_buffer.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/core/host_buffer.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/core/idle_waiter.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/core/platform.cc + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/core/platform.h + ../../../flutter/LICENSE
ORIGIN: ../../../flutter/impeller/core/range.cc + ../../../flutter/LICENSE
@ -45761,6 +45762,7 @@ FILE: ../../../flutter/impeller/core/formats.cc
FILE: ../../../flutter/impeller/core/formats.h
FILE: ../../../flutter/impeller/core/host_buffer.cc
FILE: ../../../flutter/impeller/core/host_buffer.h
FILE: ../../../flutter/impeller/core/idle_waiter.h
FILE: ../../../flutter/impeller/core/platform.cc
FILE: ../../../flutter/impeller/core/platform.h
FILE: ../../../flutter/impeller/core/range.cc

View File

@ -18,6 +18,7 @@ impeller_component("core") {
"formats.h",
"host_buffer.cc",
"host_buffer.h",
"idle_waiter.h",
"platform.cc",
"platform.h",
"range.cc",
@ -50,7 +51,10 @@ impeller_component("core") {
impeller_component("allocator_unittests") {
testonly = true
sources = [ "allocator_unittests.cc" ]
sources = [
"allocator_unittests.cc",
"buffer_view_unittests.cc",
]
deps = [
":core",

View File

@ -8,6 +8,7 @@
#include "flutter/fml/mapping.h"
#include "impeller/base/allocation_size.h"
#include "impeller/core/device_buffer_descriptor.h"
#include "impeller/core/idle_waiter.h"
#include "impeller/core/texture.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/geometry/size.h"

View File

@ -6,6 +6,29 @@
namespace impeller {
//
BufferView::BufferView() : buffer_(nullptr), raw_buffer_(nullptr), range_({}) {}
BufferView::BufferView(DeviceBuffer* buffer, Range range)
: buffer_(), raw_buffer_(buffer), range_(range) {}
BufferView::BufferView(std::shared_ptr<const DeviceBuffer> buffer, Range range)
: buffer_(std::move(buffer)), raw_buffer_(nullptr), range_(range) {}
const DeviceBuffer* BufferView::GetBuffer() const {
return raw_buffer_ ? raw_buffer_ : buffer_.get();
}
std::shared_ptr<const DeviceBuffer> BufferView::TakeBuffer() {
if (buffer_) {
raw_buffer_ = buffer_.get();
return std::move(buffer_);
} else {
return nullptr;
}
}
BufferView::operator bool() const {
return buffer_ || raw_buffer_;
}
} // namespace impeller

View File

@ -12,11 +12,34 @@ namespace impeller {
class DeviceBuffer;
/// A specific range in a DeviceBuffer.
///
/// BufferView can maintain ownership over the DeviceBuffer or not depending on
/// if it is created with a std::shared_ptr or a raw pointer.
struct BufferView {
std::shared_ptr<const DeviceBuffer> buffer;
Range range;
public:
BufferView();
constexpr explicit operator bool() const { return static_cast<bool>(buffer); }
BufferView(DeviceBuffer* buffer, Range range);
BufferView(std::shared_ptr<const DeviceBuffer> buffer, Range range);
Range GetRange() const { return range_; }
const DeviceBuffer* GetBuffer() const;
std::shared_ptr<const DeviceBuffer> TakeBuffer();
explicit operator bool() const;
private:
std::shared_ptr<const DeviceBuffer> buffer_;
/// This is a non-owned DeviceBuffer. Steps should be taken to make sure this
/// lives for the duration of the BufferView's life. Usually this is done
/// automatically by the graphics API or in the case of Vulkan the HostBuffer
/// or TrackedObjectsVK keeps it alive.
const DeviceBuffer* raw_buffer_;
Range range_;
};
} // namespace impeller

View File

@ -0,0 +1,26 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "flutter/testing/testing.h"
#include "impeller/core/buffer_view.h"
namespace impeller {
namespace testing {
TEST(BufferViewTest, Empty) {
BufferView buffer_view;
EXPECT_FALSE(buffer_view);
}
TEST(BufferViewTest, TakeRaw) {
DeviceBuffer* buffer = reinterpret_cast<DeviceBuffer*>(0xcafebabe);
BufferView buffer_view(buffer, {0, 123});
EXPECT_TRUE(buffer_view);
std::shared_ptr<const DeviceBuffer> taken = buffer_view.TakeBuffer();
EXPECT_FALSE(taken);
EXPECT_EQ(buffer_view.GetBuffer(), buffer);
}
} // namespace testing
} // namespace impeller

View File

@ -16,10 +16,8 @@ void DeviceBuffer::Invalidate(std::optional<Range> range) const {}
// static
BufferView DeviceBuffer::AsBufferView(std::shared_ptr<DeviceBuffer> buffer) {
BufferView view;
view.buffer = std::move(buffer);
view.range = {0u, view.buffer->desc_.size};
return view;
Range range = {0u, buffer->desc_.size};
return BufferView(std::move(buffer), range);
}
const DeviceBufferDescriptor& DeviceBuffer::GetDeviceBufferDescriptor() const {

View File

@ -19,12 +19,14 @@ namespace impeller {
constexpr size_t kAllocatorBlockSize = 1024000; // 1024 Kb.
std::shared_ptr<HostBuffer> HostBuffer::Create(
const std::shared_ptr<Allocator>& allocator) {
return std::shared_ptr<HostBuffer>(new HostBuffer(allocator));
const std::shared_ptr<Allocator>& allocator,
const std::shared_ptr<const IdleWaiter>& idle_waiter) {
return std::shared_ptr<HostBuffer>(new HostBuffer(allocator, idle_waiter));
}
HostBuffer::HostBuffer(const std::shared_ptr<Allocator>& allocator)
: allocator_(allocator) {
HostBuffer::HostBuffer(const std::shared_ptr<Allocator>& allocator,
const std::shared_ptr<const IdleWaiter>& idle_waiter)
: allocator_(allocator), idle_waiter_(idle_waiter) {
DeviceBufferDescriptor desc;
desc.size = kAllocatorBlockSize;
desc.storage_mode = StorageMode::kHostVisible;
@ -35,34 +37,52 @@ HostBuffer::HostBuffer(const std::shared_ptr<Allocator>& allocator)
}
}
HostBuffer::~HostBuffer() = default;
HostBuffer::~HostBuffer() {
if (idle_waiter_) {
// Since we hold on to DeviceBuffers we should make sure they aren't being
// used while we are deleting the HostBuffer.
idle_waiter_->WaitIdle();
}
};
BufferView HostBuffer::Emplace(const void* buffer,
size_t length,
size_t align) {
auto [range, device_buffer] = EmplaceInternal(buffer, length, align);
if (!device_buffer) {
auto [range, device_buffer, raw_device_buffer] =
EmplaceInternal(buffer, length, align);
if (device_buffer) {
return BufferView(std::move(device_buffer), range);
} else if (raw_device_buffer) {
return BufferView(raw_device_buffer, range);
} else {
return {};
}
return BufferView{std::move(device_buffer), range};
}
BufferView HostBuffer::Emplace(const void* buffer, size_t length) {
auto [range, device_buffer] = EmplaceInternal(buffer, length);
if (!device_buffer) {
auto [range, device_buffer, raw_device_buffer] =
EmplaceInternal(buffer, length);
if (device_buffer) {
return BufferView(std::move(device_buffer), range);
} else if (raw_device_buffer) {
return BufferView(raw_device_buffer, range);
} else {
return {};
}
return BufferView{std::move(device_buffer), range};
}
BufferView HostBuffer::Emplace(size_t length,
size_t align,
const EmplaceProc& cb) {
auto [range, device_buffer] = EmplaceInternal(length, align, cb);
if (!device_buffer) {
auto [range, device_buffer, raw_device_buffer] =
EmplaceInternal(length, align, cb);
if (device_buffer) {
return BufferView(std::move(device_buffer), range);
} else if (raw_device_buffer) {
return BufferView(raw_device_buffer, range);
} else {
return {};
}
return BufferView{std::move(device_buffer), range};
}
HostBuffer::TestStateQuery HostBuffer::GetStateForTest() {
@ -90,10 +110,10 @@ bool HostBuffer::MaybeCreateNewBuffer() {
return true;
}
std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
size_t length,
size_t align,
const EmplaceProc& cb) {
std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
HostBuffer::EmplaceInternal(size_t length,
size_t align,
const EmplaceProc& cb) {
if (!cb) {
return {};
}
@ -113,7 +133,7 @@ std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
cb(device_buffer->OnGetContents());
device_buffer->Flush(Range{0, length});
}
return std::make_tuple(Range{0, length}, std::move(device_buffer));
return std::make_tuple(Range{0, length}, std::move(device_buffer), nullptr);
}
size_t padding = 0;
@ -135,12 +155,11 @@ std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
current_buffer->Flush(output_range);
offset_ += length;
return std::make_tuple(output_range, current_buffer);
return std::make_tuple(output_range, nullptr, current_buffer.get());
}
std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
const void* buffer,
size_t length) {
std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
HostBuffer::EmplaceInternal(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) {
@ -158,7 +177,7 @@ std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
return {};
}
}
return std::make_tuple(Range{0, length}, std::move(device_buffer));
return std::make_tuple(Range{0, length}, std::move(device_buffer), nullptr);
}
auto old_length = GetLength();
@ -176,10 +195,11 @@ std::tuple<Range, std::shared_ptr<DeviceBuffer>> HostBuffer::EmplaceInternal(
current_buffer->Flush(Range{old_length, length});
}
offset_ += length;
return std::make_tuple(Range{old_length, length}, current_buffer);
return std::make_tuple(Range{old_length, length}, nullptr,
current_buffer.get());
}
std::tuple<Range, std::shared_ptr<DeviceBuffer>>
std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
HostBuffer::EmplaceInternal(const void* buffer, size_t length, size_t align) {
if (align == 0 || (GetLength() % align) == 0) {
return EmplaceInternal(buffer, length);

View File

@ -28,7 +28,8 @@ static const constexpr size_t kHostBufferArenaSize = 4u;
class HostBuffer {
public:
static std::shared_ptr<HostBuffer> Create(
const std::shared_ptr<Allocator>& allocator);
const std::shared_ptr<Allocator>& allocator,
const std::shared_ptr<const IdleWaiter>& idle_waiter);
~HostBuffer();
@ -133,13 +134,13 @@ class HostBuffer {
TestStateQuery GetStateForTest();
private:
[[nodiscard]] std::tuple<Range, std::shared_ptr<DeviceBuffer>>
[[nodiscard]] std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
EmplaceInternal(const void* buffer, size_t length);
std::tuple<Range, std::shared_ptr<DeviceBuffer>>
std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
EmplaceInternal(size_t length, size_t align, const EmplaceProc& cb);
std::tuple<Range, std::shared_ptr<DeviceBuffer>>
std::tuple<Range, std::shared_ptr<DeviceBuffer>, DeviceBuffer*>
EmplaceInternal(const void* buffer, size_t length, size_t align);
size_t GetLength() const { return offset_; }
@ -154,13 +155,15 @@ class HostBuffer {
[[nodiscard]] BufferView Emplace(const void* buffer, size_t length);
explicit HostBuffer(const std::shared_ptr<Allocator>& allocator);
explicit HostBuffer(const std::shared_ptr<Allocator>& allocator,
const std::shared_ptr<const IdleWaiter>& idle_waiter);
HostBuffer(const HostBuffer&) = delete;
HostBuffer& operator=(const HostBuffer&) = delete;
std::shared_ptr<Allocator> allocator_;
std::shared_ptr<const IdleWaiter> idle_waiter_;
std::array<std::vector<std::shared_ptr<DeviceBuffer>>, kHostBufferArenaSize>
device_buffers_;
size_t current_buffer_ = 0u;

View File

@ -0,0 +1,25 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FLUTTER_IMPELLER_CORE_IDLE_WAITER_H_
#define FLUTTER_IMPELLER_CORE_IDLE_WAITER_H_
namespace impeller {
/// Abstraction over waiting for the GPU to be idle.
///
/// This is important for platforms like Vulkan where we need to make sure
/// we aren't deleting resources while the GPU is using them.
class IdleWaiter {
public:
virtual ~IdleWaiter() = default;
/// Wait for the GPU tasks to finish.
/// This is a noop on some platforms, it's important for Vulkan.
virtual void WaitIdle() const = 0;
};
} // namespace impeller
#endif // FLUTTER_IMPELLER_CORE_IDLE_WAITER_H_

View File

@ -250,7 +250,8 @@ ContentContext::ContentContext(
? std::make_shared<RenderTargetCache>(
context_->GetResourceAllocator())
: std::move(render_target_allocator)),
host_buffer_(HostBuffer::Create(context_->GetResourceAllocator())) {
host_buffer_(HostBuffer::Create(context_->GetResourceAllocator(),
context_->GetIdleWaiter())) {
if (!context_ || !context_->IsValid()) {
return;
}

View File

@ -54,8 +54,8 @@ TEST_P(BlendFilterContentsTest, AdvancedBlendColorAlignsColorTo4) {
uint8_t byte = 0xff;
BufferView buffer_view =
renderer->GetTransientsBuffer().Emplace(&byte, /*length=*/1, /*align=*/1);
EXPECT_EQ(buffer_view.range.offset, 4u);
EXPECT_EQ(buffer_view.range.length, 1u);
EXPECT_EQ(buffer_view.GetRange().offset, 4u);
EXPECT_EQ(buffer_view.GetRange().length, 1u);
Entity entity;
std::optional<Entity> result = filter_contents.GetEntity(

View File

@ -4,30 +4,48 @@
#include <limits>
#include <utility>
#include "flutter/testing/testing.h"
#include "gmock/gmock.h"
#include "impeller/base/validation.h"
#include "impeller/core/allocator.h"
#include "impeller/core/host_buffer.h"
#include "impeller/core/idle_waiter.h"
#include "impeller/entity/entity_playground.h"
namespace impeller {
namespace testing {
class MockIdleWaiter : public IdleWaiter {
public:
MOCK_METHOD(void, WaitIdle, (), (const, override));
};
using HostBufferTest = EntityPlayground;
INSTANTIATE_PLAYGROUND_SUITE(HostBufferTest);
TEST_P(HostBufferTest, IdleWaiter) {
auto mock_idle_waiter = std::make_shared<MockIdleWaiter>();
{
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
mock_idle_waiter);
EXPECT_CALL(*mock_idle_waiter, WaitIdle());
}
}
TEST_P(HostBufferTest, CanEmplace) {
struct Length2 {
uint8_t pad[2];
};
static_assert(sizeof(Length2) == 2u);
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
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));
ASSERT_EQ(view.GetRange(), Range(i * sizeof(Length2), 2u));
}
}
@ -42,37 +60,39 @@ TEST_P(HostBufferTest, CanEmplaceWithAlignment) {
static_assert(alignof(Align16) == 16);
static_assert(sizeof(Align16) == 16);
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
ASSERT_TRUE(buffer);
{
auto view = buffer->Emplace(Length2{});
ASSERT_TRUE(view);
ASSERT_EQ(view.range, Range(0u, 2u));
ASSERT_EQ(view.GetRange(), 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(view.GetRange().offset, 16u);
ASSERT_EQ(view.GetRange().length, 16u);
}
{
auto view = buffer->Emplace(Length2{});
ASSERT_TRUE(view);
ASSERT_EQ(view.range, Range(32u, 2u));
ASSERT_EQ(view.GetRange(), 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(view.GetRange().offset, 48u);
ASSERT_EQ(view.GetRange().length, 16u);
}
}
TEST_P(HostBufferTest, HostBufferInitialState) {
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
EXPECT_EQ(buffer->GetStateForTest().current_buffer, 0u);
EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
@ -80,7 +100,8 @@ TEST_P(HostBufferTest, HostBufferInitialState) {
}
TEST_P(HostBufferTest, ResetIncrementsFrameCounter) {
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
EXPECT_EQ(buffer->GetStateForTest().current_frame, 0u);
@ -99,7 +120,8 @@ TEST_P(HostBufferTest, ResetIncrementsFrameCounter) {
TEST_P(HostBufferTest,
EmplacingLargerThanBlockSizeCreatesOneOffBufferCallback) {
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
// Emplace an amount larger than the block size, to verify that the host
// buffer does not create a buffer.
@ -111,7 +133,8 @@ TEST_P(HostBufferTest,
}
TEST_P(HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer) {
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
// Emplace an amount larger than the block size, to verify that the host
// buffer does not create a buffer.
@ -123,7 +146,8 @@ TEST_P(HostBufferTest, EmplacingLargerThanBlockSizeCreatesOneOffBuffer) {
}
TEST_P(HostBufferTest, UnusedBuffersAreDiscardedWhenResetting) {
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
// Emplace two large allocations to force the allocation of a second buffer.
auto buffer_view_a = buffer->Emplace(1020000, 0, [](uint8_t* data) {});
@ -154,13 +178,14 @@ TEST_P(HostBufferTest, UnusedBuffersAreDiscardedWhenResetting) {
}
TEST_P(HostBufferTest, EmplaceWithProcIsAligned) {
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
BufferView view = buffer->Emplace(std::array<char, 21>());
EXPECT_EQ(view.range, Range(0, 21));
EXPECT_EQ(view.GetRange(), Range(0, 21));
view = buffer->Emplace(64, 16, [](uint8_t*) {});
EXPECT_EQ(view.range, Range(32, 64));
EXPECT_EQ(view.GetRange(), Range(32, 64));
}
static constexpr const size_t kMagicFailingAllocation = 1024000 * 2;
@ -197,13 +222,13 @@ TEST_P(HostBufferTest, EmplaceWithFailingAllocationDoesntCrash) {
ScopedValidationDisable disable;
std::shared_ptr<FailingAllocator> allocator =
std::make_shared<FailingAllocator>(GetContext()->GetResourceAllocator());
auto buffer = HostBuffer::Create(allocator);
auto buffer = HostBuffer::Create(allocator, GetContext()->GetIdleWaiter());
auto view = buffer->Emplace(nullptr, kMagicFailingAllocation, 0);
EXPECT_EQ(view.buffer, nullptr);
EXPECT_EQ(view.range.offset, 0u);
EXPECT_EQ(view.range.length, 0u);
EXPECT_EQ(view.GetBuffer(), nullptr);
EXPECT_EQ(view.GetRange().offset, 0u);
EXPECT_EQ(view.GetRange().length, 0u);
}
} // namespace testing

View File

@ -1863,8 +1863,9 @@ TEST_P(EntityTest, RuntimeEffectSetsRightSizeWhenUniformIsStruct) {
// 8 bytes for iResolution
// 4 bytes for iTime
// 4 bytes padding
EXPECT_EQ(command.fragment_bindings.buffers[0].view.resource.range.length,
16u);
EXPECT_EQ(
command.fragment_bindings.buffers[0].view.resource.GetRange().length,
16u);
}
TEST_P(EntityTest, ColorFilterWithForegroundColorAdvancedBlend) {

View File

@ -143,7 +143,8 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data,
return; // Nothing to render.
}
auto host_buffer = impeller::HostBuffer::Create(
render_pass.GetContext()->GetResourceAllocator());
render_pass.GetContext()->GetResourceAllocator(),
render_pass.GetContext()->GetIdleWaiter());
using VS = impeller::ImguiRasterVertexShader;
using FS = impeller::ImguiRasterFragmentShader;
@ -265,14 +266,12 @@ void ImGui_ImplImpeller_RenderDrawData(ImDrawData* draw_data,
vertex_buffer_offset + pcmd->VtxOffset * sizeof(ImDrawVert);
impeller::VertexBuffer vertex_buffer;
vertex_buffer.vertex_buffer = impeller::BufferView{
.buffer = buffer,
.range = impeller::Range(vb_start, draw_list_vtx_bytes - vb_start)};
vertex_buffer.index_buffer = {
.buffer = buffer,
.range = impeller::Range(
index_buffer_offset + pcmd->IdxOffset * sizeof(ImDrawIdx),
pcmd->ElemCount * sizeof(ImDrawIdx))};
vertex_buffer.vertex_buffer = impeller::BufferView(
buffer, impeller::Range(vb_start, draw_list_vtx_bytes - vb_start));
vertex_buffer.index_buffer = impeller::BufferView(
buffer, impeller::Range(index_buffer_offset +
pcmd->IdxOffset * sizeof(ImDrawIdx),
pcmd->ElemCount * sizeof(ImDrawIdx)));
vertex_buffer.vertex_count = pcmd->ElemCount;
vertex_buffer.index_type = impeller::IndexType::k16bit;
render_pass.SetVertexBuffer(std::move(vertex_buffer));

View File

@ -220,7 +220,7 @@ bool BlitCopyBufferToTextureCommandGLES::Encode(
}
if (!tex_descriptor.IsValid() ||
source.range.length !=
source.GetRange().length !=
BytesPerPixelForPixelFormat(tex_descriptor.format) *
destination_region.Area()) {
return false;
@ -263,8 +263,8 @@ bool BlitCopyBufferToTextureCommandGLES::Encode(
}
const auto& gl = reactor.GetProcTable();
gl.BindTexture(texture_type, gl_handle.value());
const GLvoid* tex_data =
data.buffer_view.buffer->OnGetContents() + data.buffer_view.range.offset;
const GLvoid* tex_data = data.buffer_view.GetBuffer()->OnGetContents() +
data.buffer_view.GetRange().offset;
// GL_INVALID_OPERATION if the texture array has not been
// defined by a previous glTexImage2D operation.

View File

@ -276,14 +276,14 @@ bool BufferBindingsGLES::BindUniformBuffer(const ProcTableGLES& gl,
Allocator& transients_allocator,
const BufferResource& buffer) {
const auto* metadata = buffer.GetMetadata();
auto device_buffer = buffer.resource.buffer;
auto device_buffer = buffer.resource.GetBuffer();
if (!device_buffer) {
VALIDATION_LOG << "Device buffer not found.";
return false;
}
const auto& device_buffer_gles = DeviceBufferGLES::Cast(*device_buffer);
const uint8_t* buffer_ptr =
device_buffer_gles.GetBufferData() + buffer.resource.range.offset;
device_buffer_gles.GetBufferData() + buffer.resource.GetRange().offset;
if (metadata->members.empty()) {
VALIDATION_LOG << "Uniform buffer had no members. This is currently "

View File

@ -149,7 +149,7 @@ static bool BindVertexBuffer(const ProcTableGLES& gl,
return false;
}
auto vertex_buffer = vertex_buffer_view.buffer;
const DeviceBuffer* vertex_buffer = vertex_buffer_view.GetBuffer();
if (!vertex_buffer) {
return false;
@ -165,7 +165,7 @@ static bool BindVertexBuffer(const ProcTableGLES& gl,
/// Bind the vertex attributes associated with vertex buffer.
///
if (!vertex_desc_gles->BindVertexAttributes(
gl, buffer_index, vertex_buffer_view.range.offset)) {
gl, buffer_index, vertex_buffer_view.GetRange().offset)) {
return false;
}
@ -459,7 +459,7 @@ static bool BindVertexBuffer(const ProcTableGLES& gl,
} else {
// Bind the index buffer if necessary.
auto index_buffer_view = command.index_buffer;
auto index_buffer = index_buffer_view.buffer;
const DeviceBuffer* index_buffer = index_buffer_view.GetBuffer();
const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer);
if (!index_buffer_gles.BindAndUploadDataIfNecessary(
DeviceBufferGLES::BindingType::kElementArrayBuffer)) {
@ -469,7 +469,7 @@ static bool BindVertexBuffer(const ProcTableGLES& gl,
command.element_count, // count
ToIndexType(command.index_type), // type
reinterpret_cast<const GLvoid*>(static_cast<GLsizei>(
index_buffer_view.range.offset)) // indices
index_buffer_view.GetRange().offset)) // indices
);
}

View File

@ -194,7 +194,7 @@ bool BlitPassMTL::OnCopyBufferToTextureCommand(
uint32_t mip_level,
uint32_t slice,
bool convert_to_read) {
auto source_mtl = DeviceBufferMTL::Cast(*source.buffer).GetMTLBuffer();
auto source_mtl = DeviceBufferMTL::Cast(*source.GetBuffer()).GetMTLBuffer();
if (!source_mtl) {
return false;
}
@ -221,7 +221,7 @@ bool BlitPassMTL::OnCopyBufferToTextureCommand(
#endif // IMPELLER_DEBUG
[encoder_
copyFromBuffer:source_mtl
sourceOffset:source.range.offset
sourceOffset:source.GetRange().offset
sourceBytesPerRow:source_bytes_per_row
sourceBytesPerImage:
0 // 0 for 2D textures according to

View File

@ -84,11 +84,11 @@ bool ComputePassMTL::BindResource(ShaderStage stage,
const ShaderUniformSlot& slot,
const ShaderMetadata& metadata,
BufferView view) {
if (!view.buffer) {
if (!view.GetBuffer()) {
return false;
}
const std::shared_ptr<const DeviceBuffer>& device_buffer = view.buffer;
const DeviceBuffer* device_buffer = view.GetBuffer();
if (!device_buffer) {
return false;
}
@ -99,7 +99,8 @@ bool ComputePassMTL::BindResource(ShaderStage stage,
return false;
}
pass_bindings_cache_.SetBuffer(slot.ext_res_0, view.range.offset, buffer);
pass_bindings_cache_.SetBuffer(slot.ext_res_0, view.GetRange().offset,
buffer);
return true;
}

View File

@ -189,11 +189,11 @@ static bool Bind(PassBindingsCacheMTL& pass,
ShaderStage stage,
size_t bind_index,
const BufferView& view) {
if (!view.buffer) {
if (!view.GetBuffer()) {
return false;
}
auto device_buffer = view.buffer;
const DeviceBuffer* device_buffer = view.GetBuffer();
if (!device_buffer) {
return false;
}
@ -204,7 +204,7 @@ static bool Bind(PassBindingsCacheMTL& pass,
return false;
}
return pass.SetBuffer(stage, bind_index, view.range.offset, buffer);
return pass.SetBuffer(stage, bind_index, view.GetRange().offset, buffer);
}
static bool Bind(PassBindingsCacheMTL& pass,
@ -346,13 +346,13 @@ fml::Status RenderPassMTL::Draw() {
}
} else {
id<MTLBuffer> mtl_index_buffer =
DeviceBufferMTL::Cast(*index_buffer_.buffer).GetMTLBuffer();
DeviceBufferMTL::Cast(*index_buffer_.GetBuffer()).GetMTLBuffer();
if (instance_count_ != 1u) {
[encoder_ drawIndexedPrimitives:ToMTLPrimitiveType(primitive_type_)
indexCount:vertex_count_
indexType:index_type_
indexBuffer:mtl_index_buffer
indexBufferOffset:index_buffer_.range.offset
indexBufferOffset:index_buffer_.GetRange().offset
instanceCount:instance_count_
baseVertex:base_vertex_
baseInstance:0u];
@ -361,7 +361,7 @@ fml::Status RenderPassMTL::Draw() {
indexCount:vertex_count_
indexType:index_type_
indexBuffer:mtl_index_buffer
indexBufferOffset:index_buffer_.range.offset];
indexBufferOffset:index_buffer_.GetRange().offset];
}
}

View File

@ -248,9 +248,10 @@ bool BlitPassVK::OnCopyBufferToTextureCommand(
// cast destination to TextureVK
const auto& dst = TextureVK::Cast(*destination);
const auto& src = DeviceBufferVK::Cast(*source.buffer);
const auto& src = DeviceBufferVK::Cast(*source.GetBuffer());
if (!command_buffer_->Track(source.buffer) ||
std::shared_ptr<const DeviceBuffer> source_buffer = source.TakeBuffer();
if ((source_buffer && !command_buffer_->Track(source_buffer)) ||
!command_buffer_->Track(destination)) {
return false;
}
@ -266,7 +267,7 @@ bool BlitPassVK::OnCopyBufferToTextureCommand(
vk::PipelineStageFlagBits::eTransfer;
vk::BufferImageCopy image_copy;
image_copy.setBufferOffset(source.range.offset);
image_copy.setBufferOffset(source.GetRange().offset);
image_copy.setBufferRowLength(0);
image_copy.setBufferImageHeight(0);
image_copy.setImageSubresource(vk::ImageSubresourceLayers(

View File

@ -178,27 +178,27 @@ bool ComputePassVK::BindResource(
bool ComputePassVK::BindResource(size_t binding,
DescriptorType type,
const BufferView& view) {
BufferView view) {
if (bound_buffer_offset_ >= kMaxBindings) {
return false;
}
const std::shared_ptr<const DeviceBuffer>& device_buffer = view.buffer;
auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer();
auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
if (!buffer) {
return false;
}
if (!command_buffer_->Track(device_buffer)) {
std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
if (device_buffer && !command_buffer_->Track(device_buffer)) {
return false;
}
uint32_t offset = view.range.offset;
uint32_t offset = view.GetRange().offset;
vk::DescriptorBufferInfo buffer_info;
buffer_info.buffer = buffer;
buffer_info.offset = offset;
buffer_info.range = view.range.length;
buffer_info.range = view.GetRange().length;
buffer_workspace_[bound_buffer_offset_++] = buffer_info;
vk::WriteDescriptorSet write_set;

View File

@ -82,9 +82,7 @@ class ComputePassVK final : public ComputePass {
std::shared_ptr<const Texture> texture,
const std::unique_ptr<const Sampler>& sampler) override;
bool BindResource(size_t binding,
DescriptorType type,
const BufferView& view);
bool BindResource(size_t binding, DescriptorType type, BufferView view);
};
} // namespace impeller

View File

@ -456,6 +456,7 @@ void ContextVK::Setup(Settings settings) {
/// All done!
///
device_holder_ = std::move(device_holder);
idle_waiter_vk_ = std::make_shared<IdleWaiterVK>(device_holder_);
driver_info_ =
std::make_unique<DriverInfoVK>(device_holder_->physical_device);
debug_report_ = std::move(debug_report);

View File

@ -41,6 +41,24 @@ class DescriptorPoolRecyclerVK;
class CommandQueueVK;
class DescriptorPoolVK;
class IdleWaiterVK : public IdleWaiter {
public:
explicit IdleWaiterVK(std::weak_ptr<DeviceHolderVK> device_holder)
: device_holder_(std::move(device_holder)) {}
void WaitIdle() const override {
std::shared_ptr<DeviceHolderVK> strong_device_holder_ =
device_holder_.lock();
if (strong_device_holder_ && strong_device_holder_->GetDevice()) {
[[maybe_unused]] auto result =
strong_device_holder_->GetDevice().waitIdle();
}
}
private:
std::weak_ptr<DeviceHolderVK> device_holder_;
};
class ContextVK final : public Context,
public BackendCast<ContextVK, Context>,
public std::enable_shared_from_this<ContextVK> {
@ -211,6 +229,10 @@ class ContextVK final : public Context,
// | Context |
bool FlushCommandBuffers() override;
std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override {
return idle_waiter_vk_;
}
private:
struct DeviceHolderImpl : public DeviceHolderVK {
// |DeviceHolder|
@ -251,6 +273,7 @@ class ContextVK final : public Context,
std::shared_ptr<fml::ConcurrentMessageLoop> raster_message_loop_;
std::shared_ptr<GPUTracerVK> gpu_tracer_;
std::shared_ptr<CommandQueue> command_queue_vk_;
std::shared_ptr<const IdleWaiter> idle_waiter_vk_;
using DescriptorPoolMap =
std::unordered_map<std::thread::id, std::shared_ptr<DescriptorPoolVK>>;

View File

@ -377,9 +377,14 @@ bool RenderPassVK::SetVertexBuffer(BufferView vertex_buffers[],
vk::Buffer buffers[kMaxVertexBuffers];
vk::DeviceSize vertex_buffer_offsets[kMaxVertexBuffers];
for (size_t i = 0; i < vertex_buffer_count; i++) {
buffers[i] = DeviceBufferVK::Cast(*vertex_buffers[i].buffer).GetBuffer();
vertex_buffer_offsets[i] = vertex_buffers[i].range.offset;
command_buffer_->Track(vertex_buffers[i].buffer);
buffers[i] =
DeviceBufferVK::Cast(*vertex_buffers[i].GetBuffer()).GetBuffer();
vertex_buffer_offsets[i] = vertex_buffers[i].GetRange().offset;
std::shared_ptr<const DeviceBuffer> device_buffer =
vertex_buffers[i].TakeBuffer();
if (device_buffer) {
command_buffer_->Track(device_buffer);
}
}
// Bind the vertex buffers.
@ -399,27 +404,27 @@ bool RenderPassVK::SetIndexBuffer(BufferView index_buffer,
if (index_type != IndexType::kNone) {
has_index_buffer_ = true;
const BufferView& index_buffer_view = index_buffer;
BufferView index_buffer_view = std::move(index_buffer);
if (!index_buffer_view) {
return false;
}
const std::shared_ptr<const DeviceBuffer>& index_buffer =
index_buffer_view.buffer;
if (!index_buffer) {
if (!index_buffer_view.GetBuffer()) {
VALIDATION_LOG << "Failed to acquire device buffer"
<< " for index buffer view";
return false;
}
if (!command_buffer_->Track(index_buffer)) {
std::shared_ptr<const DeviceBuffer> index_buffer =
index_buffer_view.TakeBuffer();
if (index_buffer && !command_buffer_->Track(index_buffer)) {
return false;
}
vk::Buffer index_buffer_handle =
DeviceBufferVK::Cast(*index_buffer).GetBuffer();
DeviceBufferVK::Cast(*index_buffer_view.GetBuffer()).GetBuffer();
command_buffer_vk_.bindIndexBuffer(index_buffer_handle,
index_buffer_view.range.offset,
index_buffer_view.GetRange().offset,
ToVKIndexType(index_type));
} else {
has_index_buffer_ = false;
@ -555,27 +560,27 @@ bool RenderPassVK::BindResource(
bool RenderPassVK::BindResource(size_t binding,
DescriptorType type,
const BufferView& view) {
BufferView view) {
if (bound_buffer_offset_ >= kMaxBindings) {
return false;
}
const std::shared_ptr<const DeviceBuffer>& device_buffer = view.buffer;
auto buffer = DeviceBufferVK::Cast(*device_buffer).GetBuffer();
auto buffer = DeviceBufferVK::Cast(*view.GetBuffer()).GetBuffer();
if (!buffer) {
return false;
}
if (!command_buffer_->Track(device_buffer)) {
std::shared_ptr<const DeviceBuffer> device_buffer = view.TakeBuffer();
if (device_buffer && !command_buffer_->Track(device_buffer)) {
return false;
}
uint32_t offset = view.range.offset;
uint32_t offset = view.GetRange().offset;
vk::DescriptorBufferInfo buffer_info;
buffer_info.buffer = buffer;
buffer_info.offset = offset;
buffer_info.range = view.range.length;
buffer_info.range = view.GetRange().length;
buffer_workspace_[bound_buffer_offset_++] = buffer_info;
vk::WriteDescriptorSet write_set;

View File

@ -117,9 +117,7 @@ class RenderPassVK final : public RenderPass {
std::shared_ptr<const Texture> texture,
const std::unique_ptr<const Sampler>& sampler) override;
bool BindResource(size_t binding,
DescriptorType type,
const BufferView& view);
bool BindResource(size_t binding, DescriptorType type, BufferView view);
// |RenderPass|
bool IsValid() const override;

View File

@ -58,6 +58,10 @@ const std::shared_ptr<const Capabilities>& SurfaceContextVK::GetCapabilities()
return parent_->GetCapabilities();
}
std::shared_ptr<const IdleWaiter> SurfaceContextVK::GetIdleWaiter() const {
return parent_->GetIdleWaiter();
}
void SurfaceContextVK::Shutdown() {
parent_->Shutdown();
}

View File

@ -66,6 +66,8 @@ class SurfaceContextVK : public Context,
// |Context|
std::shared_ptr<CommandQueue> GetCommandQueue() const override;
std::shared_ptr<const IdleWaiter> GetIdleWaiter() const override;
// |Context|
void Shutdown() override;

View File

@ -146,7 +146,7 @@ bool BlitPass::AddCopy(BufferView source,
BytesPerPixelForPixelFormat(destination->GetTextureDescriptor().format);
auto bytes_per_region = destination_region_value.Area() * bytes_per_pixel;
if (source.range.length != bytes_per_region) {
if (source.GetRange().length != bytes_per_region) {
VALIDATION_LOG
<< "Attempted to add a texture blit with out of bounds access.";
return false;

View File

@ -30,7 +30,8 @@ TEST_P(ComputeTest, CapabilitiesReportSupport) {
TEST_P(ComputeTest, CanCreateComputePass) {
using CS = SampleComputeShader;
auto context = GetContext();
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
ASSERT_TRUE(context);
ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
@ -84,7 +85,7 @@ TEST_P(ComputeTest, CanCreateComputePass) {
EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
auto view = DeviceBuffer::AsBufferView(output_buffer);
EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
CS::Output<kCount>* output =
reinterpret_cast<CS::Output<kCount>*>(
@ -109,7 +110,8 @@ TEST_P(ComputeTest, CanCreateComputePass) {
TEST_P(ComputeTest, CanComputePrefixSum) {
using CS = PrefixSumTestComputeShader;
auto context = GetContext();
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
ASSERT_TRUE(context);
ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
@ -152,7 +154,7 @@ TEST_P(ComputeTest, CanComputePrefixSum) {
EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
auto view = DeviceBuffer::AsBufferView(output_buffer);
EXPECT_EQ(view.range.length,
EXPECT_EQ(view.GetRange().length,
sizeof(CS::OutputData<kCount>));
CS::OutputData<kCount>* output =
@ -210,7 +212,7 @@ TEST_P(ComputeTest, 1DThreadgroupSizingIsCorrect) {
EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
auto view = DeviceBuffer::AsBufferView(output_buffer);
EXPECT_EQ(view.range.length,
EXPECT_EQ(view.GetRange().length,
sizeof(CS::OutputData<kCount>));
CS::OutputData<kCount>* output =
@ -229,7 +231,8 @@ TEST_P(ComputeTest, CanComputePrefixSumLargeInteractive) {
using CS = PrefixSumTestComputeShader;
auto context = GetContext();
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
ASSERT_TRUE(context);
ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
@ -275,7 +278,8 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) {
using Stage2PipelineBuilder = ComputePipelineBuilder<CS2>;
auto context = GetContext();
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
ASSERT_TRUE(context);
ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
@ -373,7 +377,8 @@ TEST_P(ComputeTest, MultiStageInputAndOutput) {
TEST_P(ComputeTest, CanCompute1DimensionalData) {
using CS = SampleComputeShader;
auto context = GetContext();
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
ASSERT_TRUE(context);
ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());
@ -427,7 +432,7 @@ TEST_P(ComputeTest, CanCompute1DimensionalData) {
EXPECT_EQ(status, CommandBuffer::Status::kCompleted);
auto view = DeviceBuffer::AsBufferView(output_buffer);
EXPECT_EQ(view.range.length, sizeof(CS::Output<kCount>));
EXPECT_EQ(view.GetRange().length, sizeof(CS::Output<kCount>));
CS::Output<kCount>* output =
reinterpret_cast<CS::Output<kCount>*>(
@ -452,7 +457,8 @@ TEST_P(ComputeTest, CanCompute1DimensionalData) {
TEST_P(ComputeTest, ReturnsEarlyWhenAnyGridDimensionIsZero) {
using CS = SampleComputeShader;
auto context = GetContext();
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
ASSERT_TRUE(context);
ASSERT_TRUE(context->GetCapabilities()->SupportsCompute());

View File

@ -222,6 +222,10 @@ class Context {
/// rendering a 2D workload.
[[nodiscard]] virtual bool FlushCommandBuffers();
virtual std::shared_ptr<const IdleWaiter> GetIdleWaiter() const {
return nullptr;
}
protected:
Context();

View File

@ -224,7 +224,8 @@ class RendererDartTest : public PlaygroundTest,
return false;
}
auto buffer = HostBuffer::Create(context->GetResourceAllocator());
auto buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
pass.SetVertexBuffer(texture_vtx_builder.CreateVertexBuffer(
*context->GetResourceAllocator()));

View File

@ -80,7 +80,8 @@ TEST_P(RendererTest, CanCreateBoxPrimitive) {
context->GetSamplerLibrary()->GetSampler({});
ASSERT_TRUE(sampler);
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
SinglePassCallback callback = [&](RenderPass& pass) {
ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
static bool wireframe;
@ -145,7 +146,8 @@ TEST_P(RendererTest, BabysFirstTriangle) {
auto pipeline = context->GetPipelineLibrary()->GetPipeline(desc).Get();
// Create a host side buffer to build the vertex and uniform information.
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
// Specify the vertex buffer information.
VertexBufferBuilder<VS::PerVertexData> vertex_buffer_builder;
@ -165,7 +167,8 @@ TEST_P(RendererTest, BabysFirstTriangle) {
FS::FragInfo frag_info;
frag_info.time = fml::TimePoint::Now().ToEpochDelta().ToSecondsF();
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
FS::BindFragInfo(pass, host_buffer->EmplaceUniform(frag_info));
return pass.Draw().ok();
@ -241,7 +244,8 @@ TEST_P(RendererTest, CanRenderPerspectiveCube) {
ASSERT_TRUE(sampler);
Vector3 euler_angles;
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
SinglePassCallback callback = [&](RenderPass& pass) {
static Degrees fov_y(60);
static Scalar distance = 10;
@ -255,17 +259,14 @@ TEST_P(RendererTest, CanRenderPerspectiveCube) {
pass.SetPipeline(pipeline);
std::array<BufferView, 2> vertex_buffers = {
BufferView{
.buffer = device_buffer,
.range = Range(offsetof(Cube, positions), sizeof(Cube::positions))},
BufferView{
.buffer = device_buffer,
.range = Range(offsetof(Cube, colors), sizeof(Cube::colors))},
BufferView(device_buffer,
Range(offsetof(Cube, positions), sizeof(Cube::positions))),
BufferView(device_buffer,
Range(offsetof(Cube, colors), sizeof(Cube::colors))),
};
BufferView index_buffer = {
.buffer = device_buffer,
.range = Range(offsetof(Cube, indices), sizeof(Cube::indices))};
BufferView index_buffer(
device_buffer, Range(offsetof(Cube, indices), sizeof(Cube::indices)));
pass.SetVertexBuffer(vertex_buffers.data(), vertex_buffers.size());
pass.SetElementCount(36);
pass.SetIndexBuffer(index_buffer, IndexType::k16bit);
@ -324,7 +325,8 @@ TEST_P(RendererTest, CanRenderMultiplePrimitives) {
context->GetSamplerLibrary()->GetSampler({});
ASSERT_TRUE(sampler);
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
SinglePassCallback callback = [&](RenderPass& pass) {
for (size_t i = 0; i < 1; i++) {
for (size_t j = 0; j < 1; j++) {
@ -377,7 +379,8 @@ TEST_P(RendererTest, CanRenderToTexture) {
auto box_pipeline =
context->GetPipelineLibrary()->GetPipeline(pipeline_desc).Get();
ASSERT_TRUE(box_pipeline);
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
VertexBufferBuilder<VS::PerVertexData> vertex_builder;
vertex_builder.SetLabel("Box");
@ -499,7 +502,8 @@ TEST_P(RendererTest, CanRenderInstanced) {
instances.colors[i] = Color::Random();
}
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
ASSERT_TRUE(OpenPlaygroundHere([&](RenderPass& pass) -> bool {
pass.SetPipeline(pipeline);
pass.SetCommandLabel("InstancedDraw");
@ -570,7 +574,8 @@ TEST_P(RendererTest, CanBlitTextureToTexture) {
vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
ASSERT_TRUE(vertex_buffer);
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
Playground::RenderCallback callback = [&](RenderTarget& render_target) {
auto buffer = context->CreateCommandBuffer();
if (!buffer) {
@ -690,7 +695,8 @@ TEST_P(RendererTest, CanBlitTextureToBuffer) {
vertex_builder.CreateVertexBuffer(*context->GetResourceAllocator());
ASSERT_TRUE(vertex_buffer);
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
Playground::RenderCallback callback = [&](RenderTarget& render_target) {
{
auto buffer = context->CreateCommandBuffer();
@ -751,7 +757,7 @@ TEST_P(RendererTest, CanBlitTextureToBuffer) {
auto texture =
context->GetResourceAllocator()->CreateTexture(texture_desc);
if (!texture->SetContents(device_buffer->OnGetContents(),
buffer_view.range.length)) {
buffer_view.GetRange().length)) {
VALIDATION_LOG << "Could not upload texture to device memory";
return false;
}
@ -807,7 +813,8 @@ TEST_P(RendererTest, CanGenerateMipmaps) {
ASSERT_TRUE(vertex_buffer);
bool first_frame = true;
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
Playground::RenderCallback callback = [&](RenderTarget& render_target) {
const char* mip_filter_names[] = {"Base", "Nearest", "Linear"};
const MipFilter mip_filters[] = {MipFilter::kBase, MipFilter::kNearest,
@ -919,7 +926,8 @@ TEST_P(RendererTest, TheImpeller) {
"table_mountain_pz.png", "table_mountain_nz.png"});
const std::unique_ptr<const Sampler>& cube_map_sampler =
context->GetSamplerLibrary()->GetSampler({});
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
SinglePassCallback callback = [&](RenderPass& pass) {
auto size = pass.GetRenderTargetSize();
@ -968,7 +976,8 @@ TEST_P(RendererTest, Planet) {
context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
ASSERT_TRUE(pipeline && pipeline->IsValid());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
SinglePassCallback callback = [&](RenderPass& pass) {
static Scalar speed = 0.1;
@ -1034,7 +1043,8 @@ TEST_P(RendererTest, ArrayUniforms) {
context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
ASSERT_TRUE(pipeline && pipeline->IsValid());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
SinglePassCallback callback = [&](RenderPass& pass) {
auto size = pass.GetRenderTargetSize();
@ -1091,7 +1101,8 @@ TEST_P(RendererTest, InactiveUniforms) {
context->GetPipelineLibrary()->GetPipeline(pipeline_descriptor).Get();
ASSERT_TRUE(pipeline && pipeline->IsValid());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
SinglePassCallback callback = [&](RenderPass& pass) {
auto size = pass.GetRenderTargetSize();
@ -1256,7 +1267,8 @@ TEST_P(RendererTest, StencilMask) {
static int current_back_compare =
CompareFunctionUI().IndexOf(CompareFunction::kLessEqual);
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
Playground::RenderCallback callback = [&](RenderTarget& render_target) {
auto buffer = context->CreateCommandBuffer();
if (!buffer) {
@ -1469,7 +1481,8 @@ TEST_P(RendererTest, CanSepiaToneWithSubpasses) {
ASSERT_TRUE(sampler);
SinglePassCallback callback = [&](RenderPass& pass) {
auto buffer = HostBuffer::Create(context->GetResourceAllocator());
auto buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
// Draw the texture.
{
@ -1562,7 +1575,8 @@ TEST_P(RendererTest, CanSepiaToneThenSwizzleWithSubpasses) {
ASSERT_TRUE(sampler);
SinglePassCallback callback = [&](RenderPass& pass) {
auto buffer = HostBuffer::Create(context->GetResourceAllocator());
auto buffer = HostBuffer::Create(context->GetResourceAllocator(),
context->GetIdleWaiter());
// Draw the texture.
{

View File

@ -138,7 +138,7 @@ class VertexBufferBuilder {
if (!label_.empty()) {
buffer->SetLabel(SPrintF("%s Vertices", label_.c_str()));
}
return DeviceBuffer::AsBufferView(buffer);
return DeviceBuffer::AsBufferView(std::move(buffer));
}
std::vector<IndexType> CreateIndexBuffer() const { return indices_; }
@ -167,7 +167,7 @@ class VertexBufferBuilder {
if (!label_.empty()) {
buffer->SetLabel(SPrintF("%s Indices", label_.c_str()));
}
return DeviceBuffer::AsBufferView(buffer);
return DeviceBuffer::AsBufferView(std::move(buffer));
}
};

View File

@ -47,10 +47,11 @@ VertexBuffer Tessellator::TessellateConvex(const Path& path,
if (supports_triangle_fan) {
FanVertexWriter writer(
reinterpret_cast<Point*>(point_buffer.buffer->OnGetContents() +
point_buffer.range.offset),
reinterpret_cast<uint16_t*>(index_buffer.buffer->OnGetContents() +
index_buffer.range.offset));
reinterpret_cast<Point*>(point_buffer.GetBuffer()->OnGetContents() +
point_buffer.GetRange().offset),
reinterpret_cast<uint16_t*>(
index_buffer.GetBuffer()->OnGetContents() +
index_buffer.GetRange().offset));
path.WritePolyline(tolerance, writer);
return VertexBuffer{
@ -61,10 +62,11 @@ VertexBuffer Tessellator::TessellateConvex(const Path& path,
};
} else {
StripVertexWriter writer(
reinterpret_cast<Point*>(point_buffer.buffer->OnGetContents() +
point_buffer.range.offset),
reinterpret_cast<uint16_t*>(index_buffer.buffer->OnGetContents() +
index_buffer.range.offset));
reinterpret_cast<Point*>(point_buffer.GetBuffer()->OnGetContents() +
point_buffer.GetRange().offset),
reinterpret_cast<uint16_t*>(
index_buffer.GetBuffer()->OnGetContents() +
index_buffer.GetRange().offset));
path.WritePolyline(tolerance, writer);
return VertexBuffer{

View File

@ -81,7 +81,8 @@ TEST_P(TypographerTest, CanCreateGlyphAtlas) {
auto context = TypographerContextSkia::Make();
auto atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
auto blob = SkTextBlob::MakeFromString("hello", sk_font);
@ -116,7 +117,8 @@ TEST_P(TypographerTest, CanCreateGlyphAtlas) {
}
TEST_P(TypographerTest, LazyAtlasTracksColor) {
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
#if FML_OS_MACOSX
auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
#else
@ -158,7 +160,8 @@ TEST_P(TypographerTest, GlyphAtlasWithOddUniqueGlyphSize) {
auto context = TypographerContextSkia::Make();
auto atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
auto blob = SkTextBlob::MakeFromString("AGH", sk_font);
@ -178,7 +181,8 @@ TEST_P(TypographerTest, GlyphAtlasIsRecycledIfUnchanged) {
auto context = TypographerContextSkia::Make();
auto atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
ASSERT_TRUE(context && context->IsValid());
SkFont sk_font = flutter::testing::CreateTestFontOfSize(12);
auto blob = SkTextBlob::MakeFromString("spooky skellingtons", sk_font);
@ -202,7 +206,8 @@ TEST_P(TypographerTest, GlyphAtlasIsRecycledIfUnchanged) {
}
TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
auto context = TypographerContextSkia::Make();
auto atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
@ -249,7 +254,8 @@ TEST_P(TypographerTest, GlyphAtlasWithLotsOfdUniqueGlyphSize) {
}
TEST_P(TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged) {
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
auto context = TypographerContextSkia::Make();
auto atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
@ -286,7 +292,8 @@ TEST_P(TypographerTest, GlyphAtlasTextureIsRecycledIfUnchanged) {
}
TEST_P(TypographerTest, GlyphColorIsPartOfCacheKey) {
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
#if FML_OS_MACOSX
auto mapping = flutter::testing::OpenFixtureAsSkData("Apple Color Emoji.ttc");
#else
@ -320,7 +327,8 @@ TEST_P(TypographerTest, GlyphColorIsPartOfCacheKey) {
}
TEST_P(TypographerTest, GlyphColorIsIgnoredForNonEmojiFonts) {
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
sk_sp<SkFontMgr> font_mgr = txt::GetDefaultFontManager();
sk_sp<SkTypeface> typeface =
font_mgr->matchFamilyStyle("Arial", SkFontStyle::Normal());
@ -419,7 +427,8 @@ TEST_P(TypographerTest, GlyphAtlasTextureWillGrowTilMaxTextureSize) {
GTEST_SKIP() << "Atlas growth isn't supported for OpenGLES currently.";
}
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
auto context = TypographerContextSkia::Make();
auto atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
@ -495,7 +504,8 @@ TEST_P(TypographerTest, TextFrameInitialBoundsArePlaceholder) {
auto context = TypographerContextSkia::Make();
auto atlas_context =
context->CreateGlyphAtlasContext(GlyphAtlas::Type::kAlphaBitmap);
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator());
auto host_buffer = HostBuffer::Create(GetContext()->GetResourceAllocator(),
GetContext()->GetIdleWaiter());
auto atlas = CreateGlyphAtlas(*GetContext(), context.get(), *host_buffer,
GlyphAtlas::Type::kAlphaBitmap, 1.0f,

View File

@ -312,10 +312,8 @@ static void BindVertexBuffer(
int offset_in_bytes,
int length_in_bytes,
int vertex_count) {
wrapper->vertex_buffer = impeller::BufferView{
.buffer = buffer,
.range = impeller::Range(offset_in_bytes, length_in_bytes),
};
wrapper->vertex_buffer = impeller::BufferView(
buffer, impeller::Range(offset_in_bytes, length_in_bytes));
// If the index type is set, then the `vertex_count` becomes the index
// count... So don't overwrite the count if it's already been set when binding
@ -348,10 +346,8 @@ static void BindIndexBuffer(
int index_type,
int index_count) {
impeller::IndexType type = flutter::gpu::ToImpellerIndexType(index_type);
wrapper->index_buffer = impeller::BufferView{
.buffer = buffer,
.range = impeller::Range(offset_in_bytes, length_in_bytes),
};
wrapper->index_buffer = impeller::BufferView(
buffer, impeller::Range(offset_in_bytes, length_in_bytes));
wrapper->index_buffer_type = type;
bool setting_index_buffer = type != impeller::IndexType::kNone;
@ -412,10 +408,8 @@ static bool BindUniform(
.slot = uniform_struct->slot,
.view = impeller::BufferResource{
&uniform_struct->metadata,
impeller::BufferView{
.buffer = buffer,
.range = impeller::Range(offset_in_bytes, length_in_bytes),
},
impeller::BufferView(
buffer, impeller::Range(offset_in_bytes, length_in_bytes)),
}});
return true;
}

View File

@ -130,8 +130,9 @@ def run_cmd( # pylint: disable=too-many-arguments
for forbidden_string in forbidden_output:
if forbidden_string in output:
matches = [x.group(0) for x in re.findall(f'^.*{forbidden_string}.*$', output)]
raise RuntimeError(
'command "%s" contained forbidden string "%s"' % (command_string, forbidden_string)
f'command "{command_string}" contained forbidden string "{forbidden_string}": {matches}'
)
print_divider('<')