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 @@ -125,6 +125,7 @@ class Variants : public GenericVariants {
VALIDATION_LOG << "Failed to create default pipeline.";
return;
}
context.GetPipelineLibrary()->LogPipelineCreation(*desc);
options.ApplyToPipelineDescriptor(*desc);
desc_ = desc;
if (context.GetFlags().lazy_shader_mode) {
Expand Down
2 changes: 2 additions & 0 deletions engine/src/flutter/impeller/renderer/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ template("renderer_unittests_component") {
"capabilities_unittests.cc",
"device_buffer_unittests.cc",
"pipeline_descriptor_unittests.cc",
"pipeline_library_unittests.cc",
"pool_unittests.cc",
"renderer_unittests.cc",
]
Expand All @@ -124,6 +125,7 @@ template("renderer_unittests_component") {
"../fixtures",
"../playground:playground_test",
"../tessellator:tessellator_libtess",
"testing:mocks",
"//flutter/impeller/display_list",
"//flutter/testing:testing_lib",
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,8 @@ void RenderPassGLES::ResetGLState(const ProcTableGLES& gl) {
const std::vector<BufferView>& vertex_buffers,
const std::vector<TextureAndSampler>& bound_textures,
const std::vector<BufferResource>& bound_buffers,
const std::shared_ptr<GPUTracerGLES>& tracer) {
const std::shared_ptr<GPUTracerGLES>& tracer,
const std::shared_ptr<const Context>& impeller_context) {
TRACE_EVENT0("impeller", "RenderPassGLES::EncodeCommandsInReactor");

const auto& gl = reactor.GetProcTable();
Expand Down Expand Up @@ -335,9 +336,9 @@ void RenderPassGLES::ResetGLState(const ProcTableGLES& gl) {
pop_cmd_debug_marker.Release();
}
#endif // IMPELLER_DEBUG

const auto& pipeline = PipelineGLES::Cast(*command.pipeline);

impeller_context->GetPipelineLibrary()->LogPipelineUsage(
pipeline.GetDescriptor());
const auto* color_attachment =
pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
if (!color_attachment) {
Expand Down Expand Up @@ -686,8 +687,8 @@ bool RenderPassGLES::OnEncodeCommands(const Context& context) const {
/*vertex_buffers=*/render_pass->vertex_buffers_, //
/*bound_textures=*/render_pass->bound_textures_, //
/*bound_buffers=*/render_pass->bound_buffers_, //
/*tracer=*/tracer //
);
/*tracer=*/tracer, //
/*impeller_context=*/render_pass->context_);
FML_CHECK(result)
<< "Must be able to encode GL commands without error.";
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include "impeller/renderer/backend/metal/sampler_mtl.h"
#include "impeller/renderer/backend/metal/texture_mtl.h"
#include "impeller/renderer/command.h"
#include "impeller/renderer/pipeline_descriptor.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/vertex_descriptor.h"

namespace impeller {
Expand Down Expand Up @@ -235,6 +237,7 @@ static bool Bind(PassBindingsCacheMTL& pass,
// |RenderPass|
void RenderPassMTL::SetPipeline(PipelineRef pipeline) {
const PipelineDescriptor& pipeline_desc = pipeline->GetDescriptor();
context_->GetPipelineLibrary()->LogPipelineUsage(pipeline_desc);
primitive_type_ = pipeline_desc.GetPrimitiveType();
pass_bindings_.SetRenderPipelineState(
PipelineMTL::Cast(*pipeline).GetMTLRenderPipelineState());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,7 @@ void RenderPassVK::SetPipeline(PipelineRef pipeline) {
if (!pipeline_) {
return;
}
context_->GetPipelineLibrary()->LogPipelineUsage(pipeline->GetDescriptor());

pipeline_uses_input_attachments_ =
pipeline_->GetDescriptor().GetVertexDescriptor()->UsesInputAttacments();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "impeller/renderer/pipeline_descriptor.h"

#include <memory>
#include <utility>

#include "impeller/base/comparable.h"
Expand Down
40 changes: 40 additions & 0 deletions engine/src/flutter/impeller/renderer/pipeline_library.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
// found in the LICENSE file.

#include "impeller/renderer/pipeline_library.h"
#include <unordered_map>

#include "impeller/base/thread.h"
#include "impeller/renderer/pipeline_descriptor.h"

namespace impeller {

Expand Down Expand Up @@ -34,4 +38,40 @@ PipelineFuture<ComputePipelineDescriptor> PipelineLibrary::GetPipeline(
return {descriptor, promise->get_future()};
}

void PipelineLibrary::LogPipelineCreation(const PipelineDescriptor& p) {
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
WriterLock lock(pipeline_use_counts_mutex_);
if (!pipeline_use_counts_.contains(p)) {
pipeline_use_counts_[p] = 0;
}
#endif
}

void PipelineLibrary::LogPipelineUsage(const PipelineDescriptor& p) {
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
WriterLock lock(pipeline_use_counts_mutex_);
++pipeline_use_counts_[p];
#endif
}

std::unordered_map<PipelineDescriptor,
int,
ComparableHash<PipelineDescriptor>,
ComparableEqual<PipelineDescriptor>>
PipelineLibrary::GetPipelineUseCounts() const {
std::unordered_map<PipelineDescriptor, int,
ComparableHash<PipelineDescriptor>,
ComparableEqual<PipelineDescriptor>>
counts;

#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
ReaderLock lock(pipeline_use_counts_mutex_);
counts = pipeline_use_counts_;
#endif
return counts;
}

} // namespace impeller
23 changes: 23 additions & 0 deletions engine/src/flutter/impeller/renderer/pipeline_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include <unordered_map>

#include "compute_pipeline_descriptor.h"
#include "impeller/base/thread.h"
#include "impeller/base/thread_safety.h"
#include "impeller/renderer/pipeline.h"
#include "impeller/renderer/pipeline_descriptor.h"

Expand Down Expand Up @@ -74,13 +76,34 @@ class PipelineLibrary : public std::enable_shared_from_this<PipelineLibrary> {
virtual void RemovePipelinesWithEntryPoint(
std::shared_ptr<const ShaderFunction> function) = 0;

void LogPipelineUsage(const PipelineDescriptor& p);

void LogPipelineCreation(const PipelineDescriptor& p);

std::unordered_map<PipelineDescriptor,
int,
ComparableHash<PipelineDescriptor>,
ComparableEqual<PipelineDescriptor>>
GetPipelineUseCounts() const;

protected:
PipelineLibrary();

private:
PipelineLibrary(const PipelineLibrary&) = delete;

PipelineLibrary& operator=(const PipelineLibrary&) = delete;
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
mutable RWMutex pipeline_use_counts_mutex_;

std::unordered_map<PipelineDescriptor,
int,
ComparableHash<PipelineDescriptor>,
ComparableEqual<PipelineDescriptor>>
pipeline_use_counts_ IPLR_GUARDED_BY(pipeline_use_counts_mutex_);

#endif
};

} // namespace impeller
Expand Down
54 changes: 54 additions & 0 deletions engine/src/flutter/impeller/renderer/pipeline_library_unittests.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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/testing/mocks.h"

namespace impeller {
namespace testing {

TEST(MockPipelineLibrary, LogAndGetPipelineUsageSinglePipeline) {
MockPipelineLibrary pipeline_library;

PipelineDescriptor pipeline_desc;
pipeline_desc.SetLabel("pipeline");

pipeline_library.LogPipelineUsage(pipeline_desc);
pipeline_library.LogPipelineUsage(pipeline_desc);

auto usage_counts = pipeline_library.GetPipelineUseCounts();
#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
EXPECT_EQ(usage_counts[pipeline_desc], 2);
#else
EXPECT_EQ(usage_counts[pipeline_desc], 0);
#endif
}

TEST(MockPipelineLibrary, LogAndGetPipelineUsageMultiplePipelines) {
MockPipelineLibrary pipeline_library;

PipelineDescriptor pipeline_a;
pipeline_a.SetLabel("pipeline_a");

PipelineDescriptor pipeline_b;
pipeline_b.SetLabel("pipeline_b");

pipeline_library.LogPipelineUsage(pipeline_a);
pipeline_library.LogPipelineUsage(pipeline_a);
pipeline_library.LogPipelineUsage(pipeline_b);

auto usage_counts = pipeline_library.GetPipelineUseCounts();

#if FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_DEBUG || \
FLUTTER_RUNTIME_MODE == FLUTTER_RUNTIME_MODE_PROFILE
EXPECT_EQ(usage_counts[pipeline_a], 2);
EXPECT_EQ(usage_counts[pipeline_b], 1);
#else
EXPECT_EQ(usage_counts[pipeline_a], 0);
EXPECT_EQ(usage_counts[pipeline_b], 0);
#endif
}

} // namespace testing
} // namespace impeller
23 changes: 23 additions & 0 deletions engine/src/flutter/impeller/renderer/testing/mocks.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
#include "impeller/renderer/command_buffer.h"
#include "impeller/renderer/command_queue.h"
#include "impeller/renderer/context.h"
#include "impeller/renderer/pipeline.h"
#include "impeller/renderer/pipeline_library.h"
#include "impeller/renderer/render_pass.h"
#include "impeller/renderer/render_target.h"
#include "impeller/renderer/sampler_library.h"
Expand Down Expand Up @@ -115,6 +117,27 @@ class MockRenderPass : public RenderPass {
MOCK_METHOD(void, OnSetLabel, (std::string_view label), (override));
};

class MockPipelineLibrary : public PipelineLibrary {
public:
MOCK_METHOD(bool, IsValid, (), (const, override));
MOCK_METHOD(PipelineFuture<PipelineDescriptor>,
GetPipeline,
(PipelineDescriptor descriptor, bool async, bool threadsafe),
(override));
MOCK_METHOD(PipelineFuture<ComputePipelineDescriptor>,
GetPipeline,
(ComputePipelineDescriptor descriptor, bool async),
(override));
MOCK_METHOD(bool,
HasPipeline,
(const PipelineDescriptor& descriptor),
(override));
MOCK_METHOD(void,
RemovePipelinesWithEntryPoint,
(std::shared_ptr<const ShaderFunction> function),
(override));
};

class MockCommandBuffer : public CommandBuffer {
public:
explicit MockCommandBuffer(std::weak_ptr<const Context> context)
Expand Down
3 changes: 3 additions & 0 deletions engine/src/flutter/runtime/service_protocol.cc
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ const std::string_view
"_flutter.estimateRasterCacheMemory";
const std::string_view ServiceProtocol::kReloadAssetFonts =
"_flutter.reloadAssetFonts";
const std::string_view ServiceProtocol::kGetPipelineUsageExtensionName =
"_flutter.getPipelineUsage";

static constexpr std::string_view kViewIdPrefx = "_flutterView/";
static constexpr std::string_view kListViewsExtensionName =
Expand All @@ -59,6 +61,7 @@ ServiceProtocol::ServiceProtocol()
kGetSkSLsExtensionName,
kEstimateRasterCacheMemoryExtensionName,
kReloadAssetFonts,
kGetPipelineUsageExtensionName,
}) {}

ServiceProtocol::~ServiceProtocol() {
Expand Down
1 change: 1 addition & 0 deletions engine/src/flutter/runtime/service_protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class ServiceProtocol {
static const std::string_view kGetSkSLsExtensionName;
static const std::string_view kEstimateRasterCacheMemoryExtensionName;
static const std::string_view kReloadAssetFonts;
static const std::string_view kGetPipelineUsageExtensionName;

class Handler {
public:
Expand Down
38 changes: 38 additions & 0 deletions engine/src/flutter/shell/common/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "flutter/shell/common/skia_event_tracer_impl.h"
#include "flutter/shell/common/switches.h"
#include "flutter/shell/common/vsync_waiter.h"
#include "impeller/renderer/pipeline_library.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
#include "third_party/dart/runtime/include/dart_tools_api.h"
Expand Down Expand Up @@ -595,6 +596,10 @@ Shell::Shell(DartVMRef vm,
task_runners_.GetPlatformTaskRunner(),
std::bind(&Shell::OnServiceProtocolReloadAssetFonts, this,
std::placeholders::_1, std::placeholders::_2)};
service_protocol_handlers_[ServiceProtocol::kGetPipelineUsageExtensionName] =
{task_runners_.GetIOTaskRunner(),
std::bind(&Shell::OnServiceProtocolGetPipelineUsage, this,
std::placeholders::_1, std::placeholders::_2)};
}

Shell::~Shell() {
Expand Down Expand Up @@ -2178,6 +2183,39 @@ bool Shell::OnServiceProtocolSetAssetBundlePath(
return false;
}

bool Shell::OnServiceProtocolGetPipelineUsage(
const ServiceProtocol::Handler::ServiceProtocolMap& params,
rapidjson::Document* response) {
FML_DCHECK(task_runners_.GetIOTaskRunner()->RunsTasksOnCurrentThread());

response->SetObject();

auto context = io_manager_->GetImpellerContext();

if (!context) {
FML_DLOG(ERROR) << "Pipeline usage profiling only available in Impeller";
ServiceProtocolFailureError(
response, "Pipeline usage profiling only available in Impeller");
return false;
}

auto use_counts = context->GetPipelineLibrary()->GetPipelineUseCounts();

rapidjson::Value pipelines_json(rapidjson::kObjectType);

for (const auto& pipelineCount : use_counts) {
std::string_view pipeline_name = pipelineCount.first.GetLabel();
rapidjson::Value pipeline_key(pipeline_name.data(), pipeline_name.length(),
response->GetAllocator());

pipelines_json.AddMember(pipeline_key, pipelineCount.second,
response->GetAllocator());
}

response->AddMember("Usages", pipelines_json, response->GetAllocator());
return true;
}

void Shell::SendFontChangeNotification() {
// After system fonts are reloaded, we send a system channel message
// to notify flutter framework.
Expand Down
5 changes: 5 additions & 0 deletions engine/src/flutter/shell/common/shell.h
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,11 @@ class Shell final : public PlatformView::Delegate,
const ServiceProtocol::Handler::ServiceProtocolMap& params,
rapidjson::Document* response);

// Service protocol handler
bool OnServiceProtocolGetPipelineUsage(
const ServiceProtocol::Handler::ServiceProtocolMap& params,
rapidjson::Document* response);

// Send a system font change notification.
void SendFontChangeNotification();

Expand Down