Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,38 @@ TEST_P(TextureGLESTest, CanSetSyncFence) {
ASSERT_FALSE(sync_fence.has_value());
}

TEST_P(TextureGLESTest, TextureDtorDeletesFence) {
ContextGLES& context_gles = ContextGLES::Cast(*GetContext());
if (!context_gles.GetReactor()
->GetProcTable()
.GetDescription()
->GetGlVersion()
.IsAtLeast(Version{3, 0, 0})) {
GTEST_SKIP() << "GL Version too low to test sync fence.";
}

TextureDescriptor desc;
desc.storage_mode = StorageMode::kDevicePrivate;
desc.size = {100, 100};
desc.format = PixelFormat::kR8G8B8A8UNormInt;

auto texture = GetContext()->GetResourceAllocator()->CreateTexture(desc);
ASSERT_TRUE(!!texture);

HandleGLES fence =
context_gles.GetReactor()->CreateHandle(HandleType::kFence);
bool fence_collected = false;
context_gles.GetReactor()->RegisterCleanupCallback(
fence, [&]() { fence_collected = true; });
TextureGLES::Cast(*texture).SetFence(fence);

texture.reset();
ASSERT_TRUE(context_gles.GetReactor()->AddOperation(
[](const ReactorGLES& reactor) {}));
ASSERT_TRUE(context_gles.GetReactor()->React());
EXPECT_TRUE(fence_collected);
}

TEST_P(TextureGLESTest, Binds2DTexture) {
TextureDescriptor desc;
desc.storage_mode = StorageMode::kDevicePrivate;
Expand Down
50 changes: 22 additions & 28 deletions engine/src/flutter/impeller/renderer/backend/gles/texture_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,13 @@ TextureGLES::TextureGLES(std::shared_ptr<ReactorGLES> reactor,
type_(GetTextureTypeFromDescriptor(
GetTextureDescriptor(),
reactor_->GetProcTable().GetCapabilities())),
handle_(external_handle.has_value()
? external_handle.value()
: (threadsafe ? reactor_->CreateHandle(ToHandleType(type_))
: reactor_->CreateUntrackedHandle(
ToHandleType(type_)))),
handle_(
external_handle.has_value()
? UniqueHandleGLES(reactor_, external_handle.value())
: (threadsafe
? UniqueHandleGLES(reactor_, ToHandleType(type_))
: UniqueHandleGLES::MakeUntracked(reactor_,
ToHandleType(type_)))),
is_wrapped_(fbo.has_value() || external_handle.has_value()),
wrapped_fbo_(fbo) {
// Ensure the texture descriptor itself is valid.
Expand All @@ -174,16 +176,8 @@ TextureGLES::TextureGLES(std::shared_ptr<ReactorGLES> reactor,
is_valid_ = true;
}

// |Texture|
TextureGLES::~TextureGLES() {
reactor_->CollectHandle(handle_);
if (!cached_fbo_.IsDead()) {
reactor_->CollectHandle(cached_fbo_);
}
}

void TextureGLES::Leak() {
handle_ = HandleGLES::DeadHandle();
handle_.Release();
}

// |Texture|
Expand All @@ -194,15 +188,16 @@ bool TextureGLES::IsValid() const {
// |Texture|
void TextureGLES::SetLabel(std::string_view label) {
#ifdef IMPELLER_DEBUG
reactor_->SetDebugLabel(handle_, label);
reactor_->SetDebugLabel(handle_.Get(), label);
#endif // IMPELLER_DEBUG
}

// |Texture|
void TextureGLES::SetLabel(std::string_view label, std::string_view trailing) {
#ifdef IMPELLER_DEBUG
if (reactor_->CanSetDebugLabels()) {
reactor_->SetDebugLabel(handle_, std::format("{} {}", label, trailing));
reactor_->SetDebugLabel(handle_.Get(),
std::format("{} {}", label, trailing));
}
#endif // IMPELLER_DEBUG
}
Expand Down Expand Up @@ -283,7 +278,7 @@ bool TextureGLES::OnSetContents(std::shared_ptr<const fml::Mapping> mapping,
}

ReactorGLES::Operation texture_upload =
[handle = handle_, //
[handle = handle_.Get(), //
mapping, //
format = gles_format.value(), //
size = tex_descriptor.size, //
Expand Down Expand Up @@ -418,7 +413,7 @@ void TextureGLES::InitializeContentsIfNecessary() {
}

const auto& gl = reactor_->GetProcTable();
std::optional<GLuint> handle = reactor_->GetGLHandle(handle_);
std::optional<GLuint> handle = reactor_->GetGLHandle(handle_.Get());
if (!handle.has_value()) {
VALIDATION_LOG << "Could not initialize the contents of texture.";
return;
Expand Down Expand Up @@ -531,7 +526,7 @@ std::optional<GLuint> TextureGLES::GetGLHandle() const {
if (!IsValid()) {
return std::nullopt;
}
return reactor_->GetGLHandle(handle_);
return reactor_->GetGLHandle(handle_.Get());
}

bool TextureGLES::Bind() {
Expand All @@ -541,13 +536,12 @@ bool TextureGLES::Bind() {
}
const auto& gl = reactor_->GetProcTable();

if (fence_.has_value()) {
std::optional<GLsync> fence = reactor_->GetGLFence(fence_.value());
if (fence_.IsValid()) {
std::optional<GLsync> fence = reactor_->GetGLFence(fence_.Get());
if (fence.has_value()) {
gl.WaitSync(fence.value(), 0, GL_TIMEOUT_IGNORED);
}
reactor_->CollectHandle(fence_.value());
fence_ = std::nullopt;
fence_.Reset();
}

switch (type_) {
Expand Down Expand Up @@ -711,21 +705,21 @@ std::optional<GLuint> TextureGLES::GetFBO() const {
}

void TextureGLES::SetFence(HandleGLES fence) {
FML_DCHECK(!fence_.has_value());
fence_ = fence;
FML_DCHECK(!fence_.IsValid());
fence_ = UniqueHandleGLES(reactor_, fence);
}

// Visible for testing.
std::optional<HandleGLES> TextureGLES::GetSyncFence() const {
return fence_;
return fence_.IsValid() ? std::optional(fence_.Get()) : std::nullopt;
}

void TextureGLES::SetCachedFBO(HandleGLES fbo) {
cached_fbo_ = fbo;
cached_fbo_ = UniqueHandleGLES(reactor_, fbo);
}

const HandleGLES& TextureGLES::GetCachedFBO() const {
return cached_fbo_;
return cached_fbo_.Get();
}

} // namespace impeller
10 changes: 4 additions & 6 deletions engine/src/flutter/impeller/renderer/backend/gles/texture_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include "impeller/core/texture.h"
#include "impeller/renderer/backend/gles/handle_gles.h"
#include "impeller/renderer/backend/gles/reactor_gles.h"
#include "impeller/renderer/backend/gles/unique_handle_gles.h"

namespace impeller {

Expand Down Expand Up @@ -80,9 +81,6 @@ class TextureGLES final : public Texture,
TextureDescriptor desc,
bool threadsafe = false);

// |Texture|
~TextureGLES() override;

// |Texture|
bool IsValid() const override;

Expand Down Expand Up @@ -173,8 +171,8 @@ class TextureGLES final : public Texture,
private:
std::shared_ptr<ReactorGLES> reactor_;
const Type type_;
HandleGLES handle_;
std::optional<HandleGLES> fence_ = std::nullopt;
UniqueHandleGLES handle_;
UniqueHandleGLES fence_;
// Tracks which `(slice, mip_level)` pairs have had their storage allocated
// by a `glTexImage2D` call. Allocation is performed lazily on first write
// to a level so the only-renders-then-mipmaps path (Impeller's snapshot
Expand All @@ -187,7 +185,7 @@ class TextureGLES final : public Texture,
std::array<std::bitset<kMaxTrackedMipLevels>, 6> slice_mip_initialized_ = {};
const bool is_wrapped_;
const std::optional<GLuint> wrapped_fbo_;
HandleGLES cached_fbo_ = HandleGLES::DeadHandle();
UniqueHandleGLES cached_fbo_;
bool is_valid_ = false;

TextureGLES(std::shared_ptr<ReactorGLES> reactor,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ UniqueHandleGLES::UniqueHandleGLES(std::shared_ptr<ReactorGLES> reactor,
: reactor_(std::move(reactor)), handle_(handle) {}

UniqueHandleGLES::~UniqueHandleGLES() {
CollectHandle();
}

void UniqueHandleGLES::CollectHandle() {
if (!handle_.IsDead() && reactor_) {
reactor_->CollectHandle(handle_);
}
Expand All @@ -43,9 +47,31 @@ bool UniqueHandleGLES::IsValid() const {
return !handle_.IsDead();
}

void UniqueHandleGLES::Reset() {
CollectHandle();
reactor_.reset();
handle_ = HandleGLES::DeadHandle();
}

HandleGLES UniqueHandleGLES::Release() {
reactor_.reset();
HandleGLES old_handle = handle_;
handle_ = HandleGLES::DeadHandle();
return old_handle;
}

UniqueHandleGLES::UniqueHandleGLES(UniqueHandleGLES&& other) {
std::swap(reactor_, other.reactor_);
std::swap(handle_, other.handle_);
}

UniqueHandleGLES& UniqueHandleGLES::operator=(UniqueHandleGLES&& other) {
Comment thread
jason-simmons marked this conversation as resolved.
if (this != &other) {
Reset();
std::swap(reactor_, other.reactor_);
std::swap(handle_, other.handle_);
}
return *this;
}
Comment thread
jason-simmons marked this conversation as resolved.

} // namespace impeller
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace impeller {
///
class UniqueHandleGLES {
public:
UniqueHandleGLES() = default;

UniqueHandleGLES(std::shared_ptr<ReactorGLES> reactor, HandleType type);

static UniqueHandleGLES MakeUntracked(std::shared_ptr<ReactorGLES> reactor,
Expand All @@ -27,18 +29,26 @@ class UniqueHandleGLES {
~UniqueHandleGLES();

UniqueHandleGLES(UniqueHandleGLES&&);
UniqueHandleGLES& operator=(UniqueHandleGLES&&);
Comment thread
jason-simmons marked this conversation as resolved.

UniqueHandleGLES(const UniqueHandleGLES&) = delete;

UniqueHandleGLES& operator=(const UniqueHandleGLES&) = delete;

const HandleGLES& Get() const;

bool IsValid() const;

/// Collect the managed handle and replace it with a dead handle.
void Reset();

/// Release ownership of the handle.
HandleGLES Release();

private:
std::shared_ptr<ReactorGLES> reactor_ = nullptr;
HandleGLES handle_ = HandleGLES::DeadHandle();

void CollectHandle();
};

} // namespace impeller
Expand Down
Loading