Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1ab4750
Re-prioritize pipeline compile jobs and perform them eagerly instead …
chinmaygarde Jan 9, 2026
f4efdc4
Add io task runner to pipeline library gles.
xiaowei-guan Mar 13, 2026
1986ea4
Implement pipeline compile queue for gles
xiaowei-guan Mar 13, 2026
95d6d8b
Fix build error
xiaowei-guan Mar 16, 2026
efbbef4
Add pipeline_compile_queue_vulkan.h
xiaowei-guan Mar 16, 2026
9d6b92a
Update GetPipeline method when sync == true
xiaowei-guan Mar 16, 2026
0f55c1e
Make link program after schedule frame on IO thread
xiaowei-guan Mar 27, 2026
a6b3245
Fix codereview issues
xiaowei-guan Apr 29, 2026
91820f3
Execute the compile job one by one; do not push all the tasks into th…
xiaowei-guan May 14, 2026
5c339ba
When executing an OpenGL job, you must wait for the previous job to f…
xiaowei-guan May 15, 2026
1755b06
Remove empty line
xiaowei-guan May 15, 2026
84cbe84
Add a robust mutex-based synchronization pattern
xiaowei-guan May 21, 2026
edc184c
Fix code review issues
xiaowei-guan May 21, 2026
13d3be6
Fix code review issues
xiaowei-guan May 21, 2026
1765732
Fix code review issues
xiaowei-guan May 22, 2026
96d3473
Add check when creating PipelineCompileQueueGLES
xiaowei-guan May 25, 2026
e7a28a9
Fix format issue
xiaowei-guan May 25, 2026
f55d4bc
Add UT test
xiaowei-guan May 29, 2026
8a970fc
Fix unit test issue
xiaowei-guan Jun 1, 2026
989eea4
Add android part
xiaowei-guan Jun 1, 2026
8db046a
io task runner maybe null when call ContextGLES::Create
xiaowei-guan Jun 3, 2026
091429f
Remove not used comments
xiaowei-guan Jun 4, 2026
dc29c6f
Make PipelineCompileQueueVulkan PipelineCompileQueueGles constructor
xiaowei-guan Jun 4, 2026
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
3 changes: 0 additions & 3 deletions engine/src/flutter/impeller/base/flags.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@

namespace impeller {
struct Flags {
/// Whether to defer PSO construction until first use. Usage Will introduce
/// raster jank.
bool lazy_shader_mode = false;
/// When turned on DrawLine will use the experimental antialiased path.
bool antialiased_lines = false;
};
Expand Down
34 changes: 13 additions & 21 deletions engine/src/flutter/impeller/entity/contents/content_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,8 @@ class Variants : public GenericVariants {
context.GetPipelineLibrary()->LogPipelineCreation(*desc);
options.ApplyToPipelineDescriptor(*desc);
desc_ = desc;
if (context.GetFlags().lazy_shader_mode) {
SetDefault(options, nullptr);
} else {
SetDefault(options, std::make_unique<PipelineHandleT>(context, desc_,
/*async=*/true));
}
SetDefault(options, std::make_unique<PipelineHandleT>(context, desc_,
/*async=*/true));
}

PipelineHandleT* Get(const ContentContextOptions& options) const {
Expand Down Expand Up @@ -164,7 +160,8 @@ template <class RenderPipelineHandleT>
RenderPipelineHandleT* CreateIfNeeded(
const ContentContext* context,
Variants<RenderPipelineHandleT>& container,
ContentContextOptions opts) {
ContentContextOptions opts,
PipelineCompileQueue* compile_queue) {
if (!context->IsValid()) {
return nullptr;
}
Expand All @@ -183,7 +180,7 @@ RenderPipelineHandleT* CreateIfNeeded(
FML_CHECK(default_handle != nullptr);

const std::shared_ptr<Pipeline<PipelineDescriptor>>& pipeline =
default_handle->WaitAndGet();
default_handle->WaitAndGet(compile_queue);
if (!pipeline) {
return nullptr;
}
Expand All @@ -204,11 +201,14 @@ template <class TypedPipeline>
PipelineRef GetPipeline(const ContentContext* context,
Variants<TypedPipeline>& container,
ContentContextOptions opts) {
TypedPipeline* pipeline = CreateIfNeeded(context, container, opts);
auto compile_queue =
context->GetContext()->GetPipelineLibrary()->GetPipelineCompileQueue();
TypedPipeline* pipeline =
CreateIfNeeded(context, container, opts, compile_queue);
if (!pipeline) {
return raw_ptr<Pipeline<PipelineDescriptor>>();
}
return raw_ptr(pipeline->WaitAndGet());
return raw_ptr(pipeline->WaitAndGet(compile_queue));
}

} // namespace
Expand Down Expand Up @@ -692,14 +692,9 @@ ContentContext::ContentContext(
}
clip_pipeline_descriptor->SetColorAttachmentDescriptors(
std::move(clip_color_attachments));
if (GetContext()->GetFlags().lazy_shader_mode) {
pipelines_->clip.SetDefaultDescriptor(clip_pipeline_descriptor);
pipelines_->clip.SetDefault(options, nullptr);
} else {
pipelines_->clip.SetDefault(
options,
std::make_unique<ClipPipeline>(*context_, clip_pipeline_descriptor));
}
pipelines_->clip.SetDefault(
options,
std::make_unique<ClipPipeline>(*context_, clip_pipeline_descriptor));
pipelines_->texture_downsample.CreateDefault(
*context_, options_no_msaa_no_depth_stencil);
pipelines_->texture_downsample_bounded.CreateDefault(
Expand Down Expand Up @@ -1018,9 +1013,6 @@ void ContentContext::ResetTransientsBuffers() {
}

void ContentContext::InitializeCommonlyUsedShadersIfNeeded() const {
if (GetContext()->GetFlags().lazy_shader_mode) {
return;
}
GetContext()->InitializeCommonlyUsedShadersIfNeeded();
}

Expand Down
3 changes: 3 additions & 0 deletions engine/src/flutter/impeller/renderer/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ impeller_component("renderer") {
"pipeline.h",
"pipeline_builder.cc",
"pipeline_builder.h",
"pipeline_compile_queue.cc",
"pipeline_compile_queue.h",
"pipeline_descriptor.cc",
"pipeline_descriptor.h",
"pipeline_library.cc",
Expand Down Expand Up @@ -102,6 +104,7 @@ template("renderer_unittests_component") {
"blit_pass_unittests.cc",
"capabilities_unittests.cc",
"device_buffer_unittests.cc",
"pipeline_compile_queue_unittests.cc",
"pipeline_descriptor_unittests.cc",
"pipeline_library_unittests.cc",
"pool_unittests.cc",
Expand Down
4 changes: 4 additions & 0 deletions engine/src/flutter/impeller/renderer/backend/gles/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ impeller_component("gles_unittests") {
"test/mock_gles.cc",
"test/mock_gles.h",
"test/mock_gles_unittests.cc",
"test/pipeline_compile_queue_gles_unittests.cc",
"test/pipeline_library_gles_unittests.cc",
"test/proc_table_gles_unittests.cc",
"test/reactor_unittests.cc",
Expand All @@ -34,6 +35,7 @@ impeller_component("gles_unittests") {
]
deps = [
":gles",
"//flutter/fml",
"//flutter/impeller/playground:playground_test",
"//flutter/testing:testing_lib",
]
Expand Down Expand Up @@ -68,6 +70,8 @@ impeller_component("gles") {
"gpu_tracer_gles.h",
"handle_gles.cc",
"handle_gles.h",
"pipeline_compile_queue_gles.cc",
"pipeline_compile_queue_gles.h",
"pipeline_gles.cc",
"pipeline_gles.h",
"pipeline_library_gles.cc",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ std::shared_ptr<ContextGLES> ContextGLES::Create(
const Flags& flags,
std::unique_ptr<ProcTableGLES> gl,
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries,
bool enable_gpu_tracing) {
return std::shared_ptr<ContextGLES>(new ContextGLES(
flags, std::move(gl), shader_libraries, enable_gpu_tracing));
bool enable_gpu_tracing,
fml::RefPtr<fml::TaskRunner> io_task_runner) {
return std::shared_ptr<ContextGLES>(
new ContextGLES(flags, std::move(gl), shader_libraries,
enable_gpu_tracing, std::move(io_task_runner)));
}

ContextGLES::ContextGLES(
const Flags& flags,
std::unique_ptr<ProcTableGLES> gl,
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries_mappings,
bool enable_gpu_tracing)
bool enable_gpu_tracing,
fml::RefPtr<fml::TaskRunner> io_task_runner)
: Context(flags) {
reactor_ = std::make_shared<ReactorGLES>(std::move(gl));
if (!reactor_->IsValid()) {
Expand All @@ -52,8 +55,8 @@ ContextGLES::ContextGLES(

// Create the pipeline library.
{
pipeline_library_ =
std::shared_ptr<PipelineLibraryGLES>(new PipelineLibraryGLES(reactor_));
pipeline_library_ = std::shared_ptr<PipelineLibraryGLES>(
new PipelineLibraryGLES(reactor_, std::move(io_task_runner)));
}

// Create allocators.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ class ContextGLES final : public Context,
const Flags& flags,
std::unique_ptr<ProcTableGLES> gl,
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries,
bool enable_gpu_tracing);
bool enable_gpu_tracing,
fml::RefPtr<fml::TaskRunner> io_task_runner = nullptr);

// |Context|
~ContextGLES() override;
Expand Down Expand Up @@ -64,7 +65,8 @@ class ContextGLES final : public Context,
const Flags& flags,
std::unique_ptr<ProcTableGLES> gl,
const std::vector<std::shared_ptr<fml::Mapping>>& shader_libraries,
bool enable_gpu_tracing);
bool enable_gpu_tracing,
fml::RefPtr<fml::TaskRunner> io_task_runner = nullptr);

// |Context|
std::string DescribeGpuModel() const override;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// 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 "impeller/renderer/backend/gles/pipeline_compile_queue_gles.h"

#include "flutter/fml/logging.h"
#include "flutter/fml/trace_event.h"
#include "impeller/base/validation.h"

namespace impeller {

std::shared_ptr<PipelineCompileQueueGLES> PipelineCompileQueueGLES::Create(
fml::RefPtr<fml::TaskRunner> worker_task_runner) {
if (!worker_task_runner) {
return nullptr;
}
return std::shared_ptr<PipelineCompileQueueGLES>(
new PipelineCompileQueueGLES(std::move(worker_task_runner)));
}

PipelineCompileQueueGLES::PipelineCompileQueueGLES(
fml::RefPtr<fml::TaskRunner> worker_task_runner)
: worker_task_runner_(std::move(worker_task_runner)) {}

PipelineCompileQueueGLES::~PipelineCompileQueueGLES() = default;

void PipelineCompileQueueGLES::OnJobAdded() {
Lock lock(processing_mutex_);
if (!is_processing_) {
is_processing_ = true;
DrainPendingJobs();
}
}
Comment thread
xiaowei-guan marked this conversation as resolved.

void PipelineCompileQueueGLES::PostJob(const fml::closure& job) {
if (!job) {
return;
}

worker_task_runner_->PostTask(job);
}

void PipelineCompileQueueGLES::DrainPendingJobs() {
PostJob([weak_queue = weak_from_this()]() {
if (auto queue = std::static_pointer_cast<PipelineCompileQueueGLES>(
weak_queue.lock())) {
queue->DoOneJob();
{
Lock lock(queue->processing_mutex_);
if (!queue->HasPendingJobs()) {
queue->is_processing_ = false;
return;
}
}
queue->DrainPendingJobs();
}
});
}

} // namespace impeller
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// 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.

#ifndef FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_PIPELINE_COMPILE_QUEUE_GLES_H_
#define FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_PIPELINE_COMPILE_QUEUE_GLES_H_

#include "flutter/fml/closure.h"
#include "flutter/fml/task_runner.h"
#include "impeller/base/thread.h"
#include "impeller/renderer/pipeline_compile_queue.h"

namespace impeller {

class PipelineCompileQueueGLES : public PipelineCompileQueue {
public:
static std::shared_ptr<PipelineCompileQueueGLES> Create(
fml::RefPtr<fml::TaskRunner> worker_task_runner);

~PipelineCompileQueueGLES() override;

PipelineCompileQueueGLES(const PipelineCompileQueueGLES&) = delete;

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

void PostJob(const fml::closure& job) override;

void OnJobAdded() override;

private:
explicit PipelineCompileQueueGLES(
fml::RefPtr<fml::TaskRunner> worker_task_runner);
void DrainPendingJobs();

fml::RefPtr<fml::TaskRunner> worker_task_runner_;
Mutex processing_mutex_;
bool is_processing_ IPLR_GUARDED_BY(processing_mutex_) = false;
};

} // namespace impeller

#endif // FLUTTER_IMPELLER_RENDERER_BACKEND_GLES_PIPELINE_COMPILE_QUEUE_GLES_H_
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,12 @@

namespace impeller {

PipelineLibraryGLES::PipelineLibraryGLES(std::shared_ptr<ReactorGLES> reactor)
: reactor_(std::move(reactor)) {}
PipelineLibraryGLES::PipelineLibraryGLES(
std::shared_ptr<ReactorGLES> reactor,
fml::RefPtr<fml::TaskRunner> io_task_runner)
: reactor_(std::move(reactor)),
compile_queue_(
PipelineCompileQueueGLES::Create(std::move(io_task_runner))) {}

static std::string GetShaderInfoLog(const ProcTableGLES& gl, GLuint shader) {
GLint log_length = 0;
Expand Down Expand Up @@ -296,17 +300,34 @@ PipelineFuture<PipelineDescriptor> PipelineLibraryGLES::GetPipeline(
PipelineFuture<PipelineDescriptor>{descriptor, promise->get_future()};
pipelines_[descriptor] = pipeline_future;

const auto result = reactor_->AddOperation([promise, //
weak_this = weak_from_this(), //
descriptor, //
vert_function, //
frag_function, //
threadsafe //
](const ReactorGLES& reactor) {
promise->set_value(CreatePipeline(weak_this, descriptor, vert_function,
frag_function, threadsafe));
});
FML_CHECK(result);
auto weak_this = weak_from_this();
auto reactor = reactor_;
auto generation_task = [promise, weak_this, descriptor, vert_function,
frag_function, threadsafe, reactor]() {
auto thiz = weak_this.lock();
if (!thiz) {
promise->set_value(nullptr);
return;
}
const auto result = reactor->AddOperation([promise, //
weak_this, //
descriptor, //
vert_function, //
frag_function, //
threadsafe //
](const ReactorGLES& reactor) {
promise->set_value(CreatePipeline(weak_this, descriptor, vert_function,
frag_function, threadsafe));
});
FML_CHECK(result);
};
Comment thread
xiaowei-guan marked this conversation as resolved.

if (async && compile_queue_) {
compile_queue_->PostJobForDescriptor(descriptor,
std::move(generation_task));
} else {
generation_task();
}

return pipeline_future;
}
Expand Down Expand Up @@ -373,4 +394,8 @@ void PipelineLibraryGLES::SetProgramForKey(
programs_[key] = std::move(program);
}

PipelineCompileQueue* PipelineLibraryGLES::GetPipelineCompileQueue() const {
return compile_queue_.get();
}

} // namespace impeller
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
#include <vector>

#include "flutter/fml/hash_combine.h"
#include "flutter/fml/task_runner.h"
#include "impeller/base/thread.h"
#include "impeller/renderer/backend/gles/pipeline_compile_queue_gles.h"
#include "impeller/renderer/backend/gles/reactor_gles.h"
#include "impeller/renderer/backend/gles/unique_handle_gles.h"
#include "impeller/renderer/pipeline_library.h"
Expand Down Expand Up @@ -91,8 +93,10 @@ class PipelineLibraryGLES final
PipelineMap pipelines_;
Mutex programs_mutex_;
ProgramMap programs_ IPLR_GUARDED_BY(programs_mutex_);
std::shared_ptr<PipelineCompileQueueGLES> compile_queue_;

explicit PipelineLibraryGLES(std::shared_ptr<ReactorGLES> reactor);
explicit PipelineLibraryGLES(std::shared_ptr<ReactorGLES> reactor,
fml::RefPtr<fml::TaskRunner> io_task_runner);

// |PipelineLibrary|
bool IsValid() const override;
Expand Down Expand Up @@ -127,6 +131,8 @@ class PipelineLibraryGLES final

void SetProgramForKey(const ProgramKey& key,
std::shared_ptr<UniqueHandleGLES> program);
// |PipelineLibrary|
PipelineCompileQueue* GetPipelineCompileQueue() const override;
};

} // namespace impeller
Expand Down
Loading
Loading