blob: 73493e7641c8513cbf1f7eee6a8e6b8f35be9eb4 [file] [log] [blame]
// 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 <memory>
#include "flutter/testing/testing.h"
#include "impeller/base/validation.h"
#include "impeller/core/allocator.h"
#include "impeller/core/texture_descriptor.h"
#include "impeller/entity/entity_playground.h"
#include "impeller/entity/render_target_cache.h"
#include "impeller/playground/playground_test.h"
#include "impeller/renderer/testing/mocks.h"
namespace impeller {
namespace testing {
using RenderTargetCacheTest = EntityPlayground;
INSTANTIATE_PLAYGROUND_SUITE(RenderTargetCacheTest);
class TestAllocator : public Allocator {
public:
TestAllocator() = default;
~TestAllocator() = default;
ISize GetMaxTextureSizeSupported() const override {
return ISize(1024, 1024);
};
std::shared_ptr<DeviceBuffer> OnCreateBuffer(
const DeviceBufferDescriptor& desc) override {
if (should_fail) {
return nullptr;
}
return std::make_shared<MockDeviceBuffer>(desc);
};
virtual std::shared_ptr<Texture> OnCreateTexture(
const TextureDescriptor& desc) override {
if (should_fail) {
return nullptr;
}
return std::make_shared<MockTexture>(desc);
};
bool should_fail = false;
};
TEST_P(RenderTargetCacheTest, CachesUsedTexturesAcrossFrames) {
auto render_target_cache =
RenderTargetCache(GetContext()->GetResourceAllocator());
render_target_cache.Start();
// Create two render targets of the same exact size/shape. Both should be
// marked as used this frame, so the cached data set will contain two.
render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
render_target_cache.End();
render_target_cache.Start();
// Next frame, only create one texture. The set will still contain two,
// but one will be removed at the end of the frame.
render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
EXPECT_EQ(render_target_cache.CachedTextureCount(), 2u);
render_target_cache.End();
EXPECT_EQ(render_target_cache.CachedTextureCount(), 1u);
}
TEST_P(RenderTargetCacheTest, DoesNotPersistFailedAllocations) {
ScopedValidationDisable disable;
auto allocator = std::make_shared<TestAllocator>();
auto render_target_cache = RenderTargetCache(allocator);
render_target_cache.Start();
allocator->should_fail = true;
auto render_target =
render_target_cache.CreateOffscreen(*GetContext(), {100, 100}, 1);
EXPECT_FALSE(render_target.IsValid());
EXPECT_EQ(render_target_cache.CachedTextureCount(), 0u);
}
TEST_P(RenderTargetCacheTest, CachedTextureGetsNewAttachmentConfig) {
auto render_target_cache =
RenderTargetCache(GetContext()->GetResourceAllocator());
render_target_cache.Start();
RenderTarget::AttachmentConfig color_attachment_config =
RenderTarget::kDefaultColorAttachmentConfig;
RenderTarget target1 = render_target_cache.CreateOffscreen(
*GetContext(), {100, 100}, 1, "Offscreen1", color_attachment_config);
render_target_cache.End();
render_target_cache.Start();
color_attachment_config.clear_color = Color::Red();
RenderTarget target2 = render_target_cache.CreateOffscreen(
*GetContext(), {100, 100}, 1, "Offscreen2", color_attachment_config);
render_target_cache.End();
auto color1 = target1.GetColorAttachments().find(0)->second;
auto color2 = target2.GetColorAttachments().find(0)->second;
// The second color attachment should reuse the first attachment's texture
// but with attributes from the second AttachmentConfig.
EXPECT_EQ(color2.texture, color1.texture);
EXPECT_EQ(color2.clear_color, Color::Red());
}
TEST_P(RenderTargetCacheTest, CreateWithEmptySize) {
auto render_target_cache =
RenderTargetCache(GetContext()->GetResourceAllocator());
render_target_cache.Start();
RenderTarget empty_target =
render_target_cache.CreateOffscreen(*GetContext(), {100, 0}, 1);
RenderTarget empty_target_msaa =
render_target_cache.CreateOffscreenMSAA(*GetContext(), {0, 0}, 1);
render_target_cache.End();
{
ScopedValidationDisable disable_validation;
EXPECT_FALSE(empty_target.IsValid());
EXPECT_FALSE(empty_target_msaa.IsValid());
}
}
} // namespace testing
} // namespace impeller