diff --git a/common/settings.h b/common/settings.h index 49fbad6f02cc6..ec4e8f5a842fa 100644 --- a/common/settings.h +++ b/common/settings.h @@ -232,6 +232,9 @@ struct Settings { // Some devices claim to support the required APIs but crash on their usage. bool enable_opengl_gpu_tracing = false; + // Enable GPU tracing in Vulkan backends. + bool enable_vulkan_gpu_tracing = false; + // Data set by platform-specific embedders for use in font initialization. uint32_t font_initialization_data = 0; diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index 1a625f357a609..4fcd35f9b8d6e 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -452,7 +452,8 @@ void ContextVK::Setup(Settings settings) { // Create the GPU Tracer later because it depends on state from // the ContextVK. - gpu_tracer_ = std::make_shared(weak_from_this()); + gpu_tracer_ = std::make_shared(weak_from_this(), + settings.enable_gpu_tracing); gpu_tracer_->InitializeQueryPool(*this); //---------------------------------------------------------------------------- diff --git a/impeller/renderer/backend/vulkan/context_vk.h b/impeller/renderer/backend/vulkan/context_vk.h index 07884f1f1ef35..d3f925ac51598 100644 --- a/impeller/renderer/backend/vulkan/context_vk.h +++ b/impeller/renderer/backend/vulkan/context_vk.h @@ -47,6 +47,7 @@ class ContextVK final : public Context, std::vector> shader_libraries_data; fml::UniqueFD cache_directory; bool enable_validation = false; + bool enable_gpu_tracing = false; Settings() = default; diff --git a/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc b/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc index 85e66d5c01ef8..ea26279a206e8 100644 --- a/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc +++ b/impeller/renderer/backend/vulkan/gpu_tracer_vk.cc @@ -22,8 +22,12 @@ namespace impeller { static constexpr uint32_t kPoolSize = 128u; -GPUTracerVK::GPUTracerVK(std::weak_ptr context) +GPUTracerVK::GPUTracerVK(std::weak_ptr context, + bool enable_gpu_tracing) : context_(std::move(context)) { + if (!enable_gpu_tracing) { + return; + } timestamp_period_ = context_.lock() ->GetDeviceHolder() ->GetPhysicalDevice() diff --git a/impeller/renderer/backend/vulkan/gpu_tracer_vk.h b/impeller/renderer/backend/vulkan/gpu_tracer_vk.h index a17241549b61c..a975c737616e3 100644 --- a/impeller/renderer/backend/vulkan/gpu_tracer_vk.h +++ b/impeller/renderer/backend/vulkan/gpu_tracer_vk.h @@ -18,9 +18,14 @@ class GPUProbe; /// @brief A class that uses timestamp queries to record the approximate GPU /// execution time. +/// +/// To enable, add the following metadata to the application's Android manifest: +/// class GPUTracerVK : public std::enable_shared_from_this { public: - explicit GPUTracerVK(std::weak_ptr context); + GPUTracerVK(std::weak_ptr context, bool enable_gpu_tracing); ~GPUTracerVK() = default; diff --git a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc b/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc index 860fcf0e225f5..fd04a97d12958 100644 --- a/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc +++ b/impeller/renderer/backend/vulkan/swapchain_impl_vk.cc @@ -439,6 +439,7 @@ bool SwapchainImplVK::Present(const std::shared_ptr& image, const auto& context = ContextVK::Cast(*context_strong); const auto& sync = synchronizers_[current_frame_]; + context.GetGPUTracer()->MarkFrameEnd(); //---------------------------------------------------------------------------- /// Transition the image to color-attachment-optimal. @@ -489,8 +490,6 @@ bool SwapchainImplVK::Present(const std::shared_ptr& image, } } - context.GetGPUTracer()->MarkFrameEnd(); - auto task = [&, index, current_frame = current_frame_] { auto context_strong = context_.lock(); if (!context_strong) { diff --git a/impeller/renderer/backend/vulkan/test/gpu_tracer_unittests.cc b/impeller/renderer/backend/vulkan/test/gpu_tracer_unittests.cc index a9a267b19e67f..896ff3c421cd9 100644 --- a/impeller/renderer/backend/vulkan/test/gpu_tracer_unittests.cc +++ b/impeller/renderer/backend/vulkan/test/gpu_tracer_unittests.cc @@ -15,8 +15,25 @@ namespace impeller { namespace testing { #ifdef IMPELLER_DEBUG +TEST(GPUTracerVK, CanBeDisabled) { + auto const context = + MockVulkanContextBuilder() + .SetSettingsCallback([](ContextVK::Settings& settings) { + settings.enable_gpu_tracing = false; + }) + .Build(); + auto tracer = context->GetGPUTracer(); + + ASSERT_FALSE(tracer->IsEnabled()); +} + TEST(GPUTracerVK, CanTraceCmdBuffer) { - auto const context = MockVulkanContextBuilder().Build(); + auto const context = + MockVulkanContextBuilder() + .SetSettingsCallback([](ContextVK::Settings& settings) { + settings.enable_gpu_tracing = true; + }) + .Build(); auto tracer = context->GetGPUTracer(); ASSERT_TRUE(tracer->IsEnabled()); @@ -48,7 +65,12 @@ TEST(GPUTracerVK, CanTraceCmdBuffer) { } TEST(GPUTracerVK, DoesNotTraceOutsideOfFrameWorkload) { - auto const context = MockVulkanContextBuilder().Build(); + auto const context = + MockVulkanContextBuilder() + .SetSettingsCallback([](ContextVK::Settings& settings) { + settings.enable_gpu_tracing = true; + }) + .Build(); auto tracer = context->GetGPUTracer(); ASSERT_TRUE(tracer->IsEnabled()); @@ -78,7 +100,12 @@ TEST(GPUTracerVK, DoesNotTraceOutsideOfFrameWorkload) { // This cmd buffer starts when there is a frame but finishes when there is none. // This should result in the same recorded work. TEST(GPUTracerVK, TracesWithPartialFrameOverlap) { - auto const context = MockVulkanContextBuilder().Build(); + auto const context = + MockVulkanContextBuilder() + .SetSettingsCallback([](ContextVK::Settings& settings) { + settings.enable_gpu_tracing = true; + }) + .Build(); auto tracer = context->GetGPUTracer(); ASSERT_TRUE(tracer->IsEnabled()); diff --git a/shell/common/switches.cc b/shell/common/switches.cc index e51ed973c470a..0c28e81d5af1c 100644 --- a/shell/common/switches.cc +++ b/shell/common/switches.cc @@ -468,6 +468,8 @@ Settings SettingsFromCommandLine(const fml::CommandLine& command_line) { command_line.HasOption(FlagForSwitch(Switch::EnableVulkanValidation)); settings.enable_opengl_gpu_tracing = command_line.HasOption(FlagForSwitch(Switch::EnableOpenGLGPUTracing)); + settings.enable_vulkan_gpu_tracing = + command_line.HasOption(FlagForSwitch(Switch::EnableVulkanGPUTracing)); settings.enable_embedder_api = command_line.HasOption(FlagForSwitch(Switch::EnableEmbedderAPI)); diff --git a/shell/common/switches.h b/shell/common/switches.h index 08c75309c1107..70e54a68061b1 100644 --- a/shell/common/switches.h +++ b/shell/common/switches.h @@ -279,6 +279,10 @@ DEF_SWITCH(EnableOpenGLGPUTracing, "enable-opengl-gpu-tracing", "Enable tracing of GPU execution time when using the Impeller " "OpenGLES backend.") +DEF_SWITCH(EnableVulkanGPUTracing, + "enable-vulkan-gpu-tracing", + "Enable tracing of GPU execution time when using the Impeller " + "Vulkan backend.") DEF_SWITCH(LeakVM, "leak-vm", "When the last shell shuts down, the shared VM is leaked by default " diff --git a/shell/platform/android/android_context_vulkan_impeller.cc b/shell/platform/android/android_context_vulkan_impeller.cc index 98b61db42d739..7f4babb7ed984 100644 --- a/shell/platform/android/android_context_vulkan_impeller.cc +++ b/shell/platform/android/android_context_vulkan_impeller.cc @@ -18,7 +18,8 @@ namespace flutter { static std::shared_ptr CreateImpellerContext( const fml::RefPtr& proc_table, - bool enable_vulkan_validation) { + bool enable_vulkan_validation, + bool enable_gpu_tracing) { std::vector> shader_mappings = { std::make_shared(impeller_entity_shaders_vk_data, impeller_entity_shaders_vk_length), @@ -41,6 +42,7 @@ static std::shared_ptr CreateImpellerContext( settings.shader_libraries_data = std::move(shader_mappings); settings.cache_directory = fml::paths::GetCachesDirectory(); settings.enable_validation = enable_vulkan_validation; + settings.enable_gpu_tracing = enable_gpu_tracing; auto context = impeller::ContextVK::Create(std::move(settings)); @@ -56,10 +58,12 @@ static std::shared_ptr CreateImpellerContext( } AndroidContextVulkanImpeller::AndroidContextVulkanImpeller( - bool enable_validation) + bool enable_validation, + bool enable_gpu_tracing) : AndroidContext(AndroidRenderingAPI::kVulkan), proc_table_(fml::MakeRefCounted()) { - auto impeller_context = CreateImpellerContext(proc_table_, enable_validation); + auto impeller_context = + CreateImpellerContext(proc_table_, enable_validation, enable_gpu_tracing); SetImpellerContext(impeller_context); is_valid_ = proc_table_->HasAcquiredMandatoryProcAddresses() && impeller_context; diff --git a/shell/platform/android/android_context_vulkan_impeller.h b/shell/platform/android/android_context_vulkan_impeller.h index 1800fe00bccc1..8bbf18ef04957 100644 --- a/shell/platform/android/android_context_vulkan_impeller.h +++ b/shell/platform/android/android_context_vulkan_impeller.h @@ -14,7 +14,7 @@ namespace flutter { class AndroidContextVulkanImpeller : public AndroidContext { public: - explicit AndroidContextVulkanImpeller(bool enable_validation); + AndroidContextVulkanImpeller(bool enable_validation, bool enable_gpu_tracing); ~AndroidContextVulkanImpeller(); diff --git a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java index c7eb09b0a2727..82a3b8c20ec6c 100644 --- a/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java +++ b/shell/platform/android/io/flutter/embedding/engine/loader/FlutterLoader.java @@ -47,6 +47,8 @@ public class FlutterLoader { "io.flutter.embedding.android.ImpellerBackend"; private static final String IMPELLER_OPENGL_GPU_TRACING_DATA_KEY = "io.flutter.embedding.android.EnableOpenGLGPUTracing"; + private static final String IMPELLER_VULKAN_GPU_TRACING_DATA_KEY = + "io.flutter.embedding.android.EnableVulkanGPUTracing"; /** * Set whether leave or clean up the VM after the last shell shuts down. It can be set from app's @@ -333,6 +335,9 @@ ENABLE_VULKAN_VALIDATION_META_DATA_KEY, areValidationLayersOnByDefault())) { if (metaData.getBoolean(IMPELLER_OPENGL_GPU_TRACING_DATA_KEY, false)) { shellArgs.add("--enable-opengl-gpu-tracing"); } + if (metaData.getBoolean(IMPELLER_VULKAN_GPU_TRACING_DATA_KEY, false)) { + shellArgs.add("--enable-vulkan-gpu-tracing"); + } String backend = metaData.getString(IMPELLER_BACKEND_META_DATA_KEY); if (backend != null) { shellArgs.add("--impeller-backend=" + backend); diff --git a/shell/platform/android/platform_view_android.cc b/shell/platform/android/platform_view_android.cc index ba979963e51e9..b8d1f80fafe8b 100644 --- a/shell/platform/android/platform_view_android.cc +++ b/shell/platform/android/platform_view_android.cc @@ -74,7 +74,8 @@ static std::shared_ptr CreateAndroidContext( bool enable_impeller, const std::optional& impeller_backend, bool enable_vulkan_validation, - bool enable_opengl_gpu_tracing) { + bool enable_opengl_gpu_tracing, + bool enable_vulkan_gpu_tracing) { if (use_software_rendering) { FML_DCHECK(!enable_impeller); return std::make_shared(AndroidRenderingAPI::kSoftware); @@ -119,10 +120,10 @@ static std::shared_ptr CreateAndroidContext( enable_opengl_gpu_tracing); case AndroidRenderingAPI::kVulkan: return std::make_unique( - enable_vulkan_validation); + enable_vulkan_validation, enable_vulkan_gpu_tracing); case AndroidRenderingAPI::kAutoselect: { auto vulkan_backend = std::make_unique( - enable_vulkan_validation); + enable_vulkan_validation, enable_vulkan_gpu_tracing); if (!vulkan_backend->IsValid()) { return std::make_unique( std::make_unique(), @@ -159,7 +160,8 @@ PlatformViewAndroid::PlatformViewAndroid( delegate.OnPlatformViewGetSettings().enable_impeller, delegate.OnPlatformViewGetSettings().impeller_backend, delegate.OnPlatformViewGetSettings().enable_vulkan_validation, - delegate.OnPlatformViewGetSettings().enable_opengl_gpu_tracing)) { + delegate.OnPlatformViewGetSettings().enable_opengl_gpu_tracing, + delegate.OnPlatformViewGetSettings().enable_vulkan_gpu_tracing)) { } PlatformViewAndroid::PlatformViewAndroid(