Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit c1b0e18

Browse files
[Impeller] use sync fence for image uploads. (#56609)
Fixes flutter/flutter#158963 If the GLES version is at least 3, then we can attach a sync fence to the texture gles object. If this operation succeeds, then we can use gl.Flush instad of gl.Finish. Then, when binding the texture - if a sync fence is present we wait and then remove the fence.
1 parent 10dc07b commit c1b0e18

24 files changed

+252
-28
lines changed

impeller/renderer/backend/gles/BUILD.gn

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ impeller_component("gles_unittests") {
2525
"test/reactor_unittests.cc",
2626
"test/specialization_constants_unittests.cc",
2727
"test/surface_gles_unittests.cc",
28+
"test/texture_gles_unittests.cc",
2829
]
2930
deps = [
3031
":gles",

impeller/renderer/backend/gles/command_buffer_gles.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ void CommandBufferGLES::OnWaitUntilCompleted() {
4343
reactor_->GetProcTable().Finish();
4444
}
4545

46+
// |CommandBuffer|
47+
void CommandBufferGLES::OnWaitUntilScheduled() {
48+
reactor_->GetProcTable().Flush();
49+
}
50+
4651
// |CommandBuffer|
4752
std::shared_ptr<RenderPass> CommandBufferGLES::OnCreateRenderPass(
4853
RenderTarget target) {

impeller/renderer/backend/gles/command_buffer_gles.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ class CommandBufferGLES final : public CommandBuffer {
3737
// |CommandBuffer|
3838
void OnWaitUntilCompleted() override;
3939

40+
// |CommandBuffer|
41+
void OnWaitUntilScheduled() override;
42+
4043
// |CommandBuffer|
4144
std::shared_ptr<RenderPass> OnCreateRenderPass(RenderTarget target) override;
4245

impeller/renderer/backend/gles/context_gles.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
#include "impeller/base/validation.h"
1010
#include "impeller/renderer/backend/gles/command_buffer_gles.h"
1111
#include "impeller/renderer/backend/gles/gpu_tracer_gles.h"
12+
#include "impeller/renderer/backend/gles/handle_gles.h"
1213
#include "impeller/renderer/backend/gles/render_pass_gles.h"
14+
#include "impeller/renderer/backend/gles/texture_gles.h"
1315
#include "impeller/renderer/command_queue.h"
1416

1517
namespace impeller {
@@ -157,4 +159,15 @@ void ContextGLES::ResetThreadLocalState() const {
157159
});
158160
}
159161

162+
// |Context|
163+
bool ContextGLES::AddTrackingFence(
164+
const std::shared_ptr<Texture>& texture) const {
165+
if (!reactor_->GetProcTable().FenceSync.IsAvailable()) {
166+
return false;
167+
}
168+
HandleGLES fence = reactor_->CreateHandle(HandleType::kFence);
169+
TextureGLES::Cast(*texture).SetFence(fence);
170+
return true;
171+
}
172+
160173
} // namespace impeller

impeller/renderer/backend/gles/context_gles.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,9 @@ class ContextGLES final : public Context,
9393
// |Context|
9494
void Shutdown() override;
9595

96+
// |Context|
97+
bool AddTrackingFence(const std::shared_ptr<Texture>& texture) const override;
98+
9699
// |Context|
97100
void ResetThreadLocalState() const override;
98101

impeller/renderer/backend/gles/handle_gles.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ std::string HandleTypeToString(HandleType type) {
2222
return "RenderBuffer";
2323
case HandleType::kFrameBuffer:
2424
return "Framebuffer";
25+
case HandleType::kFence:
26+
return "Fence";
2527
}
2628
FML_UNREACHABLE();
2729
}

impeller/renderer/backend/gles/handle_gles.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ enum class HandleType {
2222
kProgram,
2323
kRenderBuffer,
2424
kFrameBuffer,
25+
kFence,
2526
};
2627

2728
std::string HandleTypeToString(HandleType type);

impeller/renderer/backend/gles/proc_table_gles.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,8 @@ static std::optional<GLenum> ToDebugIdentifier(DebugResourceType type) {
334334
return GL_RENDERBUFFER;
335335
case DebugResourceType::kFrameBuffer:
336336
return GL_FRAMEBUFFER;
337+
case DebugResourceType::kFence:
338+
return GL_SYNC_FENCE;
337339
}
338340
FML_UNREACHABLE();
339341
}
@@ -354,6 +356,8 @@ static bool ResourceIsLive(const ProcTableGLES& gl,
354356
return gl.IsRenderbuffer(name);
355357
case DebugResourceType::kFrameBuffer:
356358
return gl.IsFramebuffer(name);
359+
case DebugResourceType::kFence:
360+
return true;
357361
}
358362
FML_UNREACHABLE();
359363
}

impeller/renderer/backend/gles/proc_table_gles.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,11 @@ void(glDepthRange)(GLdouble n, GLdouble f);
258258
PROC(ClearDepth); \
259259
PROC(DepthRange);
260260

261-
#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) PROC(BlitFramebuffer);
261+
#define FOR_EACH_IMPELLER_GLES3_PROC(PROC) \
262+
PROC(FenceSync); \
263+
PROC(DeleteSync); \
264+
PROC(WaitSync); \
265+
PROC(BlitFramebuffer);
262266

263267
#define FOR_EACH_IMPELLER_EXT_PROC(PROC) \
264268
PROC(DebugMessageControlKHR); \
@@ -282,6 +286,7 @@ enum class DebugResourceType {
282286
kShader,
283287
kRenderBuffer,
284288
kFrameBuffer,
289+
kFence,
285290
};
286291

287292
class ProcTableGLES {

impeller/renderer/backend/gles/reactor_gles.cc

Lines changed: 58 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,51 +13,59 @@
1313

1414
namespace impeller {
1515

16-
static std::optional<GLuint> CreateGLHandle(const ProcTableGLES& gl,
17-
HandleType type) {
18-
GLuint handle = GL_NONE;
16+
// static
17+
std::optional<ReactorGLES::GLStorage> ReactorGLES::CreateGLHandle(
18+
const ProcTableGLES& gl,
19+
HandleType type) {
20+
GLStorage handle = GLStorage{.handle = GL_NONE};
1921
switch (type) {
2022
case HandleType::kUnknown:
2123
return std::nullopt;
2224
case HandleType::kTexture:
23-
gl.GenTextures(1u, &handle);
25+
gl.GenTextures(1u, &handle.handle);
2426
return handle;
2527
case HandleType::kBuffer:
26-
gl.GenBuffers(1u, &handle);
28+
gl.GenBuffers(1u, &handle.handle);
2729
return handle;
2830
case HandleType::kProgram:
29-
return gl.CreateProgram();
31+
return GLStorage{.handle = gl.CreateProgram()};
3032
case HandleType::kRenderBuffer:
31-
gl.GenRenderbuffers(1u, &handle);
33+
gl.GenRenderbuffers(1u, &handle.handle);
3234
return handle;
3335
case HandleType::kFrameBuffer:
34-
gl.GenFramebuffers(1u, &handle);
36+
gl.GenFramebuffers(1u, &handle.handle);
3537
return handle;
38+
case HandleType::kFence:
39+
return GLStorage{.sync = gl.FenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0)};
3640
}
3741
return std::nullopt;
3842
}
3943

40-
static bool CollectGLHandle(const ProcTableGLES& gl,
41-
HandleType type,
42-
GLuint handle) {
44+
// static
45+
bool ReactorGLES::CollectGLHandle(const ProcTableGLES& gl,
46+
HandleType type,
47+
ReactorGLES::GLStorage handle) {
4348
switch (type) {
4449
case HandleType::kUnknown:
4550
return false;
4651
case HandleType::kTexture:
47-
gl.DeleteTextures(1u, &handle);
52+
gl.DeleteTextures(1u, &handle.handle);
4853
return true;
4954
case HandleType::kBuffer:
50-
gl.DeleteBuffers(1u, &handle);
55+
gl.DeleteBuffers(1u, &handle.handle);
5156
return true;
5257
case HandleType::kProgram:
53-
gl.DeleteProgram(handle);
58+
gl.DeleteProgram(handle.handle);
5459
return true;
5560
case HandleType::kRenderBuffer:
56-
gl.DeleteRenderbuffers(1u, &handle);
61+
gl.DeleteRenderbuffers(1u, &handle.handle);
5762
return true;
5863
case HandleType::kFrameBuffer:
59-
gl.DeleteFramebuffers(1u, &handle);
64+
gl.DeleteFramebuffers(1u, &handle.handle);
6065
return true;
66+
case HandleType::kFence:
67+
gl.DeleteSync(handle.sync);
68+
break;
6169
}
6270
return false;
6371
}
@@ -116,24 +124,48 @@ const ProcTableGLES& ReactorGLES::GetProcTable() const {
116124
return *proc_table_;
117125
}
118126

119-
std::optional<GLuint> ReactorGLES::GetGLHandle(const HandleGLES& handle) const {
127+
std::optional<ReactorGLES::GLStorage> ReactorGLES::GetHandle(
128+
const HandleGLES& handle) const {
120129
ReaderLock handles_lock(handles_mutex_);
121130
if (auto found = handles_.find(handle); found != handles_.end()) {
122131
if (found->second.pending_collection) {
123132
VALIDATION_LOG
124133
<< "Attempted to acquire a handle that was pending collection.";
125134
return std::nullopt;
126135
}
127-
if (!found->second.name.has_value()) {
136+
std::optional<ReactorGLES::GLStorage> name = found->second.name;
137+
if (!name.has_value()) {
128138
VALIDATION_LOG << "Attempt to acquire a handle outside of an operation.";
129139
return std::nullopt;
130140
}
131-
return found->second.name;
141+
return name;
132142
}
133143
VALIDATION_LOG << "Attempted to acquire an invalid GL handle.";
134144
return std::nullopt;
135145
}
136146

147+
std::optional<GLuint> ReactorGLES::GetGLHandle(const HandleGLES& handle) const {
148+
if (handle.type == HandleType::kFence) {
149+
return std::nullopt;
150+
}
151+
std::optional<ReactorGLES::GLStorage> gl_handle = GetHandle(handle);
152+
if (gl_handle.has_value()) {
153+
return gl_handle->handle;
154+
}
155+
return std::nullopt;
156+
}
157+
158+
std::optional<GLsync> ReactorGLES::GetGLFence(const HandleGLES& handle) const {
159+
if (handle.type != HandleType::kFence) {
160+
return std::nullopt;
161+
}
162+
std::optional<ReactorGLES::GLStorage> gl_handle = GetHandle(handle);
163+
if (gl_handle.has_value()) {
164+
return gl_handle->sync;
165+
}
166+
return std::nullopt;
167+
}
168+
137169
bool ReactorGLES::AddOperation(Operation operation) {
138170
if (!operation) {
139171
return false;
@@ -171,9 +203,9 @@ HandleGLES ReactorGLES::CreateHandle(HandleType type, GLuint external_handle) {
171203
}
172204
WriterLock handles_lock(handles_mutex_);
173205

174-
std::optional<GLuint> gl_handle;
206+
std::optional<ReactorGLES::GLStorage> gl_handle;
175207
if (external_handle != GL_NONE) {
176-
gl_handle = external_handle;
208+
gl_handle = ReactorGLES::GLStorage{.handle = external_handle};
177209
} else if (CanReactOnCurrentThread()) {
178210
gl_handle = CreateGLHandle(GetProcTable(), type);
179211
}
@@ -215,6 +247,8 @@ static DebugResourceType ToDebugResourceType(HandleType type) {
215247
return DebugResourceType::kRenderBuffer;
216248
case HandleType::kFrameBuffer:
217249
return DebugResourceType::kFrameBuffer;
250+
case HandleType::kFence:
251+
return DebugResourceType::kFence;
218252
}
219253
FML_UNREACHABLE();
220254
}
@@ -253,9 +287,10 @@ bool ReactorGLES::ConsolidateHandles() {
253287
handle.second.name = gl_handle;
254288
}
255289
// Set pending debug labels.
256-
if (handle.second.pending_debug_label.has_value()) {
290+
if (handle.second.pending_debug_label.has_value() &&
291+
handle.first.type != HandleType::kFence) {
257292
if (gl.SetDebugLabel(ToDebugResourceType(handle.first.type),
258-
handle.second.name.value(),
293+
handle.second.name.value().handle,
259294
handle.second.pending_debug_label.value())) {
260295
handle.second.pending_debug_label = std::nullopt;
261296
}

impeller/renderer/backend/gles/reactor_gles.h

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ class ReactorGLES {
158158
///
159159
std::optional<GLuint> GetGLHandle(const HandleGLES& handle) const;
160160

161+
std::optional<GLsync> GetGLFence(const HandleGLES& handle) const;
162+
161163
//----------------------------------------------------------------------------
162164
/// @brief Create a reactor handle.
163165
///
@@ -245,15 +247,23 @@ class ReactorGLES {
245247
[[nodiscard]] bool React();
246248

247249
private:
250+
/// @brief Storage for either a GL handle or sync fence.
251+
struct GLStorage {
252+
union {
253+
GLuint handle;
254+
GLsync sync;
255+
};
256+
};
257+
248258
struct LiveHandle {
249-
std::optional<GLuint> name;
259+
std::optional<GLStorage> name;
250260
std::optional<std::string> pending_debug_label;
251261
bool pending_collection = false;
252262
fml::ScopedCleanupClosure callback = {};
253263

254264
LiveHandle() = default;
255265

256-
explicit LiveHandle(std::optional<GLuint> p_name) : name(p_name) {}
266+
explicit LiveHandle(std::optional<GLStorage> p_name) : name(p_name) {}
257267

258268
constexpr bool IsLive() const { return name.has_value(); }
259269
};
@@ -292,6 +302,15 @@ class ReactorGLES {
292302

293303
void SetupDebugGroups();
294304

305+
std::optional<GLStorage> GetHandle(const HandleGLES& handle) const;
306+
307+
static std::optional<GLStorage> CreateGLHandle(const ProcTableGLES& gl,
308+
HandleType type);
309+
310+
static bool CollectGLHandle(const ProcTableGLES& gl,
311+
HandleType type,
312+
GLStorage handle);
313+
295314
ReactorGLES(const ReactorGLES&) = delete;
296315

297316
ReactorGLES& operator=(const ReactorGLES&) = delete;

0 commit comments

Comments
 (0)