Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Prev Previous commit
Next Next commit
move caching to entity layer
  • Loading branch information
jonahwilliams committed Aug 15, 2023
commit 6acb7514979510bbea0c41efb88b6d7f66c6737d
6 changes: 6 additions & 0 deletions impeller/aiks/picture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,15 @@ std::shared_ptr<Texture> Picture::RenderToTexture(
// This texture isn't host visible, but we might want to add host visible
// features to Image someday.
auto impeller_context = context.GetContext();
// Do not use the render target cache as the lifecycle of this texture
// will outlive a particular frame.
RenderTargetAllocator render_target_allocator =
RenderTargetAllocator(impeller_context->GetResourceAllocator());
RenderTarget target;
if (impeller_context->GetCapabilities()->SupportsOffscreenMSAA()) {
target = RenderTarget::CreateOffscreenMSAA(
*impeller_context, // context
render_target_allocator, // allocator
size, // size
"Picture Snapshot MSAA", // label
RenderTarget::
Expand All @@ -70,6 +75,7 @@ std::shared_ptr<Texture> Picture::RenderToTexture(
} else {
target = RenderTarget::CreateOffscreen(
*impeller_context, // context
render_target_allocator, // allocator
size, // size
"Picture Snapshot", // label
RenderTarget::kDefaultColorAttachmentConfig // color_attachment_config
Expand Down
4 changes: 0 additions & 4 deletions impeller/aiks/testing/context_mock.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,6 @@ class ContextMock : public Context {

MOCK_CONST_METHOD0(GetPipelineLibrary, std::shared_ptr<PipelineLibrary>());

MOCK_CONST_METHOD0(DidAcquireSurfaceFrame, void());

MOCK_CONST_METHOD0(DidFinishSurfaceFrame, void());

MOCK_CONST_METHOD0(CreateCommandBuffer, std::shared_ptr<CommandBuffer>());

MOCK_METHOD0(Shutdown, void());
Expand Down
40 changes: 2 additions & 38 deletions impeller/core/allocator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,6 @@ std::shared_ptr<DeviceBuffer> Allocator::CreateBufferWithCopy(
return new_buffer;
}

void Allocator::DidAcquireSurfaceFrame() {
for (auto& td : data_to_recycle_) {
td.used_this_frame = false;
}
}

void Allocator::DidFinishSurfaceFrame() {
std::vector<TextureData> retain;

for (auto td : data_to_recycle_) {
if (td.used_this_frame) {
retain.push_back(td);
}
}
data_to_recycle_.clear();
data_to_recycle_.insert(data_to_recycle_.end(), retain.begin(), retain.end());
}

void Allocator::SetEnableRenderTargetTextureCache(bool value) {
enable_render_target_texture_cache_ = value;
}

std::shared_ptr<DeviceBuffer> Allocator::CreateBufferWithCopy(
const fml::Mapping& mapping) {
return CreateBufferWithCopy(mapping.GetMapping(), mapping.GetSize());
Expand All @@ -77,25 +55,11 @@ std::shared_ptr<Texture> Allocator::CreateTexture(
return nullptr;
}

if (enable_render_target_texture_cache_ && !desc.ignore_cache &&
desc.storage_mode != StorageMode::kHostVisible &&
(desc.usage &
static_cast<TextureUsageMask>(TextureUsage::kRenderTarget))) {
for (auto& td : data_to_recycle_) {
const auto other_desc = td.texture->GetTextureDescriptor();
if (!td.used_this_frame && desc.IsCompatibleWith(other_desc)) {
td.used_this_frame = true;
return td.texture;
}
}
auto result = OnCreateTexture(desc);
data_to_recycle_.push_back({.used_this_frame = true, .texture = result});
return result;
}

return OnCreateTexture(desc);
}

void Allocator::DidAcquireSurfaceFrame() { }

uint16_t Allocator::MinimumBytesPerRow(PixelFormat format) const {
return BytesPerPixelForPixelFormat(format);
}
Expand Down
13 changes: 0 additions & 13 deletions impeller/core/allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ class Allocator {

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

void SetEnableRenderTargetTextureCache(bool value);

//------------------------------------------------------------------------------
/// @brief Minimum value for `row_bytes` on a Texture. The row
/// bytes parameter of that method must be aligned to this value.
Expand All @@ -53,27 +51,16 @@ class Allocator {
/// allocation pools.
virtual void DidAcquireSurfaceFrame();

virtual void DidFinishSurfaceFrame();

protected:
Allocator();

struct TextureData {
bool used_this_frame;
std::shared_ptr<Texture> texture;
};

std::vector<TextureData> data_to_recycle_;

virtual std::shared_ptr<DeviceBuffer> OnCreateBuffer(
const DeviceBufferDescriptor& desc) = 0;

virtual std::shared_ptr<Texture> OnCreateTexture(
const TextureDescriptor& desc) = 0;

private:
bool enable_render_target_texture_cache_ = false;

FML_DISALLOW_COPY_AND_ASSIGN(Allocator);
};

Expand Down
264 changes: 132 additions & 132 deletions impeller/core/allocator_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,138 +13,138 @@
namespace impeller {
namespace testing {

class TestAllocator : public Allocator {
public:
TestAllocator() = default;

~TestAllocator() = default;

std::vector<Allocator::TextureData> GetCachedData() {
return data_to_recycle_;
};

ISize GetMaxTextureSizeSupported() const override {
return ISize(1024, 1024);
};

std::shared_ptr<DeviceBuffer> OnCreateBuffer(
const DeviceBufferDescriptor& desc) override {
return std::make_shared<MockDeviceBuffer>(desc);
};

virtual std::shared_ptr<Texture> OnCreateTexture(
const TextureDescriptor& desc) override {
return std::make_shared<MockTexture>(desc);
};
};

TEST(AllocatorTest, TextureDescriptorCompatibility) {
// Size.
{
TextureDescriptor desc_a = {.size = ISize(100, 100)};
TextureDescriptor desc_b = {.size = ISize(100, 100)};
TextureDescriptor desc_c = {.size = ISize(101, 100)};

ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
}
// Storage Mode.
{
TextureDescriptor desc_a = {.storage_mode = StorageMode::kDevicePrivate};
TextureDescriptor desc_b = {.storage_mode = StorageMode::kDevicePrivate};
TextureDescriptor desc_c = {.storage_mode = StorageMode::kHostVisible};

ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
}
// Format.
{
TextureDescriptor desc_a = {.format = PixelFormat::kR8G8B8A8UNormInt};
TextureDescriptor desc_b = {.format = PixelFormat::kR8G8B8A8UNormInt};
TextureDescriptor desc_c = {.format = PixelFormat::kB10G10R10A10XR};

ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
}
// Sample Count.
{
TextureDescriptor desc_a = {.sample_count = SampleCount::kCount4};
TextureDescriptor desc_b = {.sample_count = SampleCount::kCount4};
TextureDescriptor desc_c = {.sample_count = SampleCount::kCount1};

ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
}
// Sample Count.
{
TextureDescriptor desc_a = {.type = TextureType::kTexture2DMultisample};
TextureDescriptor desc_b = {.type = TextureType::kTexture2DMultisample};
TextureDescriptor desc_c = {.type = TextureType::kTexture2D};

ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
}
}

TEST(AllocatorTest, CachesTexturesWhenEnabled) {
auto allocator = std::make_shared<TestAllocator>();
auto desc = TextureDescriptor{
.format = PixelFormat::kR8G8B8A8UNormInt,
.size = ISize(100, 100),
.usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};

allocator->DidAcquireSurfaceFrame();
allocator->CreateTexture(desc);

ASSERT_TRUE(allocator->GetCachedData().size() == 0);

allocator->SetEnableRenderTargetTextureCache(true);
allocator->CreateTexture(desc);

ASSERT_TRUE(allocator->GetCachedData().size() == 1);
}

TEST(AllocatorTest, DoesNotCacheNonRenderTargetTextures) {
auto allocator = std::make_shared<TestAllocator>();
auto desc = TextureDescriptor{
.format = PixelFormat::kR8G8B8A8UNormInt,
.size = ISize(100, 100),
.usage = static_cast<TextureUsageMask>(TextureUsage::kShaderRead)};

allocator->SetEnableRenderTargetTextureCache(true);
allocator->DidAcquireSurfaceFrame();
allocator->CreateTexture(desc);

ASSERT_TRUE(allocator->GetCachedData().size() == 0);
}

TEST(AllocatorTest, CachesUsedTexturesAcrossFrames) {
auto allocator = std::make_shared<TestAllocator>();
auto desc = TextureDescriptor{
.format = PixelFormat::kR8G8B8A8UNormInt,
.size = ISize(100, 100),
.usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};

allocator->DidAcquireSurfaceFrame();
allocator->SetEnableRenderTargetTextureCache(true);
// Create two textures of the same exact size/shape. Both should be marked as
// used this frame, so the cached data set will contain two.
allocator->CreateTexture(desc);
allocator->CreateTexture(desc);

ASSERT_TRUE(allocator->GetCachedData().size() == 2);

allocator->DidFinishSurfaceFrame();
allocator->DidAcquireSurfaceFrame();

// Next frame, only create one texture. The set will still contain two,
// but one will be removed at the end of the frame.
allocator->CreateTexture(desc);
ASSERT_TRUE(allocator->GetCachedData().size() == 2);

allocator->DidFinishSurfaceFrame();
ASSERT_TRUE(allocator->GetCachedData().size() == 1);
}
// class TestAllocator : public Allocator {
// public:
// TestAllocator() = default;

// ~TestAllocator() = default;

// std::vector<Allocator::TextureData> GetCachedData() {
// return data_to_recycle_;
// };

// ISize GetMaxTextureSizeSupported() const override {
// return ISize(1024, 1024);
// };

// std::shared_ptr<DeviceBuffer> OnCreateBuffer(
// const DeviceBufferDescriptor& desc) override {
// return std::make_shared<MockDeviceBuffer>(desc);
// };

// virtual std::shared_ptr<Texture> OnCreateTexture(
// const TextureDescriptor& desc) override {
// return std::make_shared<MockTexture>(desc);
// };
// };

// TEST(AllocatorTest, TextureDescriptorCompatibility) {
// // Size.
// {
// TextureDescriptor desc_a = {.size = ISize(100, 100)};
// TextureDescriptor desc_b = {.size = ISize(100, 100)};
// TextureDescriptor desc_c = {.size = ISize(101, 100)};

// ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
// ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
// }
// // Storage Mode.
// {
// TextureDescriptor desc_a = {.storage_mode = StorageMode::kDevicePrivate};
// TextureDescriptor desc_b = {.storage_mode = StorageMode::kDevicePrivate};
// TextureDescriptor desc_c = {.storage_mode = StorageMode::kHostVisible};

// ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
// ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
// }
// // Format.
// {
// TextureDescriptor desc_a = {.format = PixelFormat::kR8G8B8A8UNormInt};
// TextureDescriptor desc_b = {.format = PixelFormat::kR8G8B8A8UNormInt};
// TextureDescriptor desc_c = {.format = PixelFormat::kB10G10R10A10XR};

// ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
// ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
// }
// // Sample Count.
// {
// TextureDescriptor desc_a = {.sample_count = SampleCount::kCount4};
// TextureDescriptor desc_b = {.sample_count = SampleCount::kCount4};
// TextureDescriptor desc_c = {.sample_count = SampleCount::kCount1};

// ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
// ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
// }
// // Sample Count.
// {
// TextureDescriptor desc_a = {.type = TextureType::kTexture2DMultisample};
// TextureDescriptor desc_b = {.type = TextureType::kTexture2DMultisample};
// TextureDescriptor desc_c = {.type = TextureType::kTexture2D};

// ASSERT_TRUE(desc_a.IsCompatibleWith(desc_b));
// ASSERT_FALSE(desc_a.IsCompatibleWith(desc_c));
// }
// }

// TEST(AllocatorTest, CachesTexturesWhenEnabled) {
// auto allocator = std::make_shared<TestAllocator>();
// auto desc = TextureDescriptor{
// .format = PixelFormat::kR8G8B8A8UNormInt,
// .size = ISize(100, 100),
// .usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};

// allocator->DidAcquireSurfaceFrame();
// allocator->CreateTexture(desc);

// ASSERT_TRUE(allocator->GetCachedData().size() == 0);

// allocator->SetEnableRenderTargetTextureCache(true);
// allocator->CreateTexture(desc);

// ASSERT_TRUE(allocator->GetCachedData().size() == 1);
// }

// TEST(AllocatorTest, DoesNotCacheNonRenderTargetTextures) {
// auto allocator = std::make_shared<TestAllocator>();
// auto desc = TextureDescriptor{
// .format = PixelFormat::kR8G8B8A8UNormInt,
// .size = ISize(100, 100),
// .usage = static_cast<TextureUsageMask>(TextureUsage::kShaderRead)};

// allocator->SetEnableRenderTargetTextureCache(true);
// allocator->DidAcquireSurfaceFrame();
// allocator->CreateTexture(desc);

// ASSERT_TRUE(allocator->GetCachedData().size() == 0);
// }

// TEST(AllocatorTest, CachesUsedTexturesAcrossFrames) {
// auto allocator = std::make_shared<TestAllocator>();
// auto desc = TextureDescriptor{
// .format = PixelFormat::kR8G8B8A8UNormInt,
// .size = ISize(100, 100),
// .usage = static_cast<TextureUsageMask>(TextureUsage::kRenderTarget)};

// allocator->DidAcquireSurfaceFrame();
// allocator->SetEnableRenderTargetTextureCache(true);
// // Create two textures of the same exact size/shape. Both should be marked as
// // used this frame, so the cached data set will contain two.
// allocator->CreateTexture(desc);
// allocator->CreateTexture(desc);

// ASSERT_TRUE(allocator->GetCachedData().size() == 2);

// allocator->DidFinishSurfaceFrame();
// allocator->DidAcquireSurfaceFrame();

// // Next frame, only create one texture. The set will still contain two,
// // but one will be removed at the end of the frame.
// allocator->CreateTexture(desc);
// ASSERT_TRUE(allocator->GetCachedData().size() == 2);

// allocator->DidFinishSurfaceFrame();
// ASSERT_TRUE(allocator->GetCachedData().size() == 1);
// }

} // namespace testing
} // namespace impeller
Loading