Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
1 change: 1 addition & 0 deletions impeller/renderer/backend/gles/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ impeller_component("gles_unittests") {
"test/reactor_unittests.cc",
"test/specialization_constants_unittests.cc",
"test/surface_gles_unittests.cc",
"test/texture_gles_unittests.cc",
]
deps = [
":gles",
Expand Down
5 changes: 5 additions & 0 deletions impeller/renderer/backend/gles/command_buffer_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ void CommandBufferGLES::OnWaitUntilCompleted() {
reactor_->GetProcTable().Finish();
}

// |CommandBuffer|
void CommandBufferGLES::OnWaitUntilScheduled() {
reactor_->GetProcTable().Flush();
}

// |CommandBuffer|
std::shared_ptr<RenderPass> CommandBufferGLES::OnCreateRenderPass(
RenderTarget target) {
Expand Down
3 changes: 3 additions & 0 deletions impeller/renderer/backend/gles/command_buffer_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class CommandBufferGLES final : public CommandBuffer {
// |CommandBuffer|
void OnWaitUntilCompleted() override;

// |CommandBuffer|
void OnWaitUntilScheduled() override;

// |CommandBuffer|
std::shared_ptr<RenderPass> OnCreateRenderPass(RenderTarget target) override;

Expand Down
13 changes: 13 additions & 0 deletions impeller/renderer/backend/gles/context_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include "impeller/base/validation.h"
#include "impeller/renderer/backend/gles/command_buffer_gles.h"
#include "impeller/renderer/backend/gles/gpu_tracer_gles.h"
#include "impeller/renderer/backend/gles/handle_gles.h"
#include "impeller/renderer/backend/gles/render_pass_gles.h"
#include "impeller/renderer/backend/gles/texture_gles.h"
#include "impeller/renderer/command_queue.h"

namespace impeller {
Expand Down Expand Up @@ -157,4 +159,15 @@ void ContextGLES::ResetThreadLocalState() const {
});
}

// |Context|
bool ContextGLES::AddTrackingFence(
const std::shared_ptr<Texture>& texture) const {
if (!reactor_->GetProcTable().FenceSync.IsAvailable()) {
return false;
}
HandleGLES fence = reactor_->CreateHandle(HandleType::kFence);
TextureGLES::Cast(*texture).SetFence(fence);
return true;
}

} // namespace impeller
3 changes: 3 additions & 0 deletions impeller/renderer/backend/gles/context_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ class ContextGLES final : public Context,
// |Context|
void Shutdown() override;

// |Context|
bool AddTrackingFence(const std::shared_ptr<Texture>& texture) const override;

// |Context|
void ResetThreadLocalState() const override;

Expand Down
2 changes: 2 additions & 0 deletions impeller/renderer/backend/gles/handle_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ std::string HandleTypeToString(HandleType type) {
return "RenderBuffer";
case HandleType::kFrameBuffer:
return "Framebuffer";
case HandleType::kFence:
return "Fence";
}
FML_UNREACHABLE();
}
Expand Down
1 change: 1 addition & 0 deletions impeller/renderer/backend/gles/handle_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ enum class HandleType {
kProgram,
kRenderBuffer,
kFrameBuffer,
kFence,
};

std::string HandleTypeToString(HandleType type);
Expand Down
4 changes: 4 additions & 0 deletions impeller/renderer/backend/gles/proc_table_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,8 @@ static std::optional<GLenum> ToDebugIdentifier(DebugResourceType type) {
return GL_RENDERBUFFER;
case DebugResourceType::kFrameBuffer:
return GL_FRAMEBUFFER;
case DebugResourceType::kFence:
return GL_SYNC_FENCE;
}
FML_UNREACHABLE();
}
Expand All @@ -354,6 +356,8 @@ static bool ResourceIsLive(const ProcTableGLES& gl,
return gl.IsRenderbuffer(name);
case DebugResourceType::kFrameBuffer:
return gl.IsFramebuffer(name);
case DebugResourceType::kFence:
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GLES3 has a glIsSync API that can be used here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only used for debug labeling which I don't believe can be done to the sync fence APIs

}
FML_UNREACHABLE();
}
Expand Down
7 changes: 6 additions & 1 deletion impeller/renderer/backend/gles/proc_table_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,11 @@ void(glDepthRange)(GLdouble n, GLdouble f);
PROC(ClearDepth); \
PROC(DepthRange);

#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) PROC(BlitFramebuffer);
#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) \
PROC(FenceSync); \
PROC(DeleteSync); \
PROC(WaitSync); \
PROC(BlitFramebuffer);

#define FOR_EACH_IMPELLER_EXT_PROC(PROC) \
PROC(DebugMessageControlKHR); \
Expand All @@ -282,6 +286,7 @@ enum class DebugResourceType {
kShader,
kRenderBuffer,
kFrameBuffer,
kFence,
};

class ProcTableGLES {
Expand Down
81 changes: 58 additions & 23 deletions impeller/renderer/backend/gles/reactor_gles.cc
Original file line number Diff line number Diff line change
Expand Up @@ -13,51 +13,59 @@

namespace impeller {

static std::optional<GLuint> CreateGLHandle(const ProcTableGLES& gl,
HandleType type) {
GLuint handle = GL_NONE;
// static
std::optional<ReactorGLES::GLStorage> ReactorGLES::CreateGLHandle(
const ProcTableGLES& gl,
HandleType type) {
GLStorage handle = GLStorage{.handle = GL_NONE};
switch (type) {
case HandleType::kUnknown:
return std::nullopt;
case HandleType::kTexture:
gl.GenTextures(1u, &handle);
gl.GenTextures(1u, &handle.handle);
return handle;
case HandleType::kBuffer:
gl.GenBuffers(1u, &handle);
gl.GenBuffers(1u, &handle.handle);
return handle;
case HandleType::kProgram:
return gl.CreateProgram();
return GLStorage{.handle = gl.CreateProgram()};
case HandleType::kRenderBuffer:
gl.GenRenderbuffers(1u, &handle);
gl.GenRenderbuffers(1u, &handle.handle);
return handle;
case HandleType::kFrameBuffer:
gl.GenFramebuffers(1u, &handle);
gl.GenFramebuffers(1u, &handle.handle);
return handle;
case HandleType::kFence:
return GLStorage{.sync = gl.FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)};
}
return std::nullopt;
}

static bool CollectGLHandle(const ProcTableGLES& gl,
HandleType type,
GLuint handle) {
// static
bool ReactorGLES::CollectGLHandle(const ProcTableGLES& gl,
HandleType type,
ReactorGLES::GLStorage handle) {
switch (type) {
case HandleType::kUnknown:
return false;
case HandleType::kTexture:
gl.DeleteTextures(1u, &handle);
gl.DeleteTextures(1u, &handle.handle);
return true;
case HandleType::kBuffer:
gl.DeleteBuffers(1u, &handle);
gl.DeleteBuffers(1u, &handle.handle);
return true;
case HandleType::kProgram:
gl.DeleteProgram(handle);
gl.DeleteProgram(handle.handle);
return true;
case HandleType::kRenderBuffer:
gl.DeleteRenderbuffers(1u, &handle);
gl.DeleteRenderbuffers(1u, &handle.handle);
return true;
case HandleType::kFrameBuffer:
gl.DeleteFramebuffers(1u, &handle);
gl.DeleteFramebuffers(1u, &handle.handle);
return true;
case HandleType::kFence:
gl.DeleteSync(handle.sync);
break;
}
return false;
}
Expand Down Expand Up @@ -116,24 +124,48 @@ const ProcTableGLES& ReactorGLES::GetProcTable() const {
return *proc_table_;
}

std::optional<GLuint> ReactorGLES::GetGLHandle(const HandleGLES& handle) const {
std::optional<ReactorGLES::GLStorage> ReactorGLES::GetHandle(
const HandleGLES& handle) const {
ReaderLock handles_lock(handles_mutex_);
if (auto found = handles_.find(handle); found != handles_.end()) {
if (found->second.pending_collection) {
VALIDATION_LOG
<< "Attempted to acquire a handle that was pending collection.";
return std::nullopt;
}
if (!found->second.name.has_value()) {
std::optional<ReactorGLES::GLStorage> name = found->second.name;
if (!name.has_value()) {
VALIDATION_LOG << "Attempt to acquire a handle outside of an operation.";
return std::nullopt;
}
return found->second.name;
return name;
}
VALIDATION_LOG << "Attempted to acquire an invalid GL handle.";
return std::nullopt;
}

std::optional<GLuint> ReactorGLES::GetGLHandle(const HandleGLES& handle) const {
if (handle.type == HandleType::kFence) {
return std::nullopt;
}
std::optional<ReactorGLES::GLStorage> gl_handle = GetHandle(handle);
if (gl_handle.has_value()) {
return gl_handle->handle;
}
return std::nullopt;
}

std::optional<GLsync> ReactorGLES::GetGLFence(const HandleGLES& handle) const {
if (handle.type != HandleType::kFence) {
return std::nullopt;
}
std::optional<ReactorGLES::GLStorage> gl_handle = GetHandle(handle);
if (gl_handle.has_value()) {
return gl_handle->sync;
}
return std::nullopt;
}

bool ReactorGLES::AddOperation(Operation operation) {
if (!operation) {
return false;
Expand Down Expand Up @@ -171,9 +203,9 @@ HandleGLES ReactorGLES::CreateHandle(HandleType type, GLuint external_handle) {
}
WriterLock handles_lock(handles_mutex_);

std::optional<GLuint> gl_handle;
std::optional<ReactorGLES::GLStorage> gl_handle;
if (external_handle != GL_NONE) {
gl_handle = external_handle;
gl_handle = ReactorGLES::GLStorage{.handle = external_handle};
} else if (CanReactOnCurrentThread()) {
gl_handle = CreateGLHandle(GetProcTable(), type);
}
Expand Down Expand Up @@ -215,6 +247,8 @@ static DebugResourceType ToDebugResourceType(HandleType type) {
return DebugResourceType::kRenderBuffer;
case HandleType::kFrameBuffer:
return DebugResourceType::kFrameBuffer;
case HandleType::kFence:
return DebugResourceType::kFence;
}
FML_UNREACHABLE();
}
Expand Down Expand Up @@ -253,9 +287,10 @@ bool ReactorGLES::ConsolidateHandles() {
handle.second.name = gl_handle;
}
// Set pending debug labels.
if (handle.second.pending_debug_label.has_value()) {
if (handle.second.pending_debug_label.has_value() &&
handle.first.type != HandleType::kFence) {
if (gl.SetDebugLabel(ToDebugResourceType(handle.first.type),
handle.second.name.value(),
handle.second.name.value().handle,
handle.second.pending_debug_label.value())) {
handle.second.pending_debug_label = std::nullopt;
}
Expand Down
23 changes: 21 additions & 2 deletions impeller/renderer/backend/gles/reactor_gles.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,8 @@ class ReactorGLES {
///
std::optional<GLuint> GetGLHandle(const HandleGLES& handle) const;

std::optional<GLsync> GetGLFence(const HandleGLES& handle) const;

//----------------------------------------------------------------------------
/// @brief Create a reactor handle.
///
Expand Down Expand Up @@ -245,15 +247,23 @@ class ReactorGLES {
[[nodiscard]] bool React();

private:
/// @brief Storage for either a GL handle or sync fence.
struct GLStorage {
union {
GLuint handle;
GLsync sync;
};
};

struct LiveHandle {
std::optional<GLuint> name;
std::optional<GLStorage> name;
std::optional<std::string> pending_debug_label;
bool pending_collection = false;
fml::ScopedCleanupClosure callback = {};

LiveHandle() = default;

explicit LiveHandle(std::optional<GLuint> p_name) : name(p_name) {}
explicit LiveHandle(std::optional<GLStorage> p_name) : name(p_name) {}

constexpr bool IsLive() const { return name.has_value(); }
};
Expand Down Expand Up @@ -292,6 +302,15 @@ class ReactorGLES {

void SetupDebugGroups();

std::optional<GLStorage> GetHandle(const HandleGLES& handle) const;

static std::optional<GLStorage> CreateGLHandle(const ProcTableGLES& gl,
HandleType type);

static bool CollectGLHandle(const ProcTableGLES& gl,
HandleType type,
GLStorage handle);

ReactorGLES(const ReactorGLES&) = delete;

ReactorGLES& operator=(const ReactorGLES&) = delete;
Expand Down
Loading