Add UMA for PresentationDelayForInteractiveFrames feature
This CL adds two histograms to help understand the percentage of frames that can be swapped immediately and frames that need to wait. GPU.Presentation.FrameHandlesAnimationOrInteraction GPU.Presentation.NonAnimatdOrInteractiveFrameWithPendingFrame When VSyncAlignedPresent and kPresentationDelayForInteractiveFrames are enabled, frames not handling interaction and animation can be swapped immediately. However, they must wait in the queue for VSync when there is a pending frame(s). Bug: 330771325 Change-Id: I9a85b2c398c37c5e428dd8327f5e0a332f335b00 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6334447 Commit-Queue: Maggie Chen <magchen@chromium.org> Reviewed-by: Colin Blundell <blundell@chromium.org> Reviewed-by: Jonathan Ross <jonross@chromium.org> Cr-Commit-Position: refs/heads/main@{#1430521}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
6ab89ac2b4
commit
3bdab00d57
components/viz/service/display
gpu/ipc/service
tools/metrics/histograms
ui/gfx
@ -121,7 +121,8 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
|
|||||||
gfx::CALayerResult ca_layer_error_code = gfx::kCALayerSuccess;
|
gfx::CALayerResult ca_layer_error_code = gfx::kCALayerSuccess;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool is_handling_interaction_or_animation = false;
|
bool is_handling_interaction = false;
|
||||||
|
bool is_handling_animation = false;
|
||||||
|
|
||||||
std::optional<int64_t> choreographer_vsync_id;
|
std::optional<int64_t> choreographer_vsync_id;
|
||||||
int64_t swap_trace_id = -1;
|
int64_t swap_trace_id = -1;
|
||||||
|
@ -1115,7 +1115,8 @@ bool Display::DrawAndSwap(const DrawAndSwapParams& params) {
|
|||||||
std::move(animation_thread_ids), std::move(renderer_main_thread_ids),
|
std::move(animation_thread_ids), std::move(renderer_main_thread_ids),
|
||||||
boost_type);
|
boost_type);
|
||||||
|
|
||||||
bool has_interactive_or_animated_frame = false;
|
bool has_interactive_frame = false;
|
||||||
|
bool has_animated_frame = false;
|
||||||
for (const auto& surface_id : aggregator_->previous_contained_surfaces()) {
|
for (const auto& surface_id : aggregator_->previous_contained_surfaces()) {
|
||||||
surface = surface_manager_->GetSurfaceForId(surface_id);
|
surface = surface_manager_->GetSurfaceForId(surface_id);
|
||||||
if (surface) {
|
if (surface) {
|
||||||
@ -1125,10 +1126,12 @@ bool Display::DrawAndSwap(const DrawAndSwapParams& params) {
|
|||||||
presentation_group_timing.AddPresentationHelper(std::move(helper));
|
presentation_group_timing.AddPresentationHelper(std::move(helper));
|
||||||
}
|
}
|
||||||
|
|
||||||
has_interactive_or_animated_frame |=
|
has_interactive_frame |=
|
||||||
surface->HasActiveFrame() &&
|
surface->HasActiveFrame() &&
|
||||||
(surface->GetActiveFrameMetadata().is_handling_interaction ||
|
surface->GetActiveFrameMetadata().is_handling_interaction;
|
||||||
surface->GetActiveFrameMetadata().is_handling_animation);
|
has_animated_frame |=
|
||||||
|
surface->HasActiveFrame() &&
|
||||||
|
surface->GetActiveFrameMetadata().is_handling_animation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1164,8 +1167,8 @@ bool Display::DrawAndSwap(const DrawAndSwapParams& params) {
|
|||||||
swap_frame_data.ca_layer_error_code =
|
swap_frame_data.ca_layer_error_code =
|
||||||
overlay_processor_->GetCALayerErrorCode();
|
overlay_processor_->GetCALayerErrorCode();
|
||||||
#endif
|
#endif
|
||||||
swap_frame_data.is_handling_interaction_or_animation =
|
swap_frame_data.is_handling_interaction = has_interactive_frame;
|
||||||
has_interactive_or_animated_frame;
|
swap_frame_data.is_handling_animation = has_animated_frame;
|
||||||
|
|
||||||
// We must notify scheduler and increase |pending_swaps_| before calling
|
// We must notify scheduler and increase |pending_swaps_| before calling
|
||||||
// SwapBuffers() as it can call DidReceiveSwapBuffersAck synchronously.
|
// SwapBuffers() as it can call DidReceiveSwapBuffersAck synchronously.
|
||||||
|
@ -1197,8 +1197,10 @@ void SkiaRenderer::SwapBuffers(SwapFrameData swap_frame_data) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
output_frame.data.is_handling_interaction_or_animation =
|
output_frame.data.is_handling_interaction =
|
||||||
swap_frame_data.is_handling_interaction_or_animation;
|
swap_frame_data.is_handling_interaction;
|
||||||
|
output_frame.data.is_handling_animation =
|
||||||
|
swap_frame_data.is_handling_animation;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (buffer_queue_) {
|
if (buffer_queue_) {
|
||||||
|
@ -63,6 +63,48 @@ void RecordVSyncCallbackDelay(base::TimeDelta delay) {
|
|||||||
/*min=*/base::Microseconds(10),
|
/*min=*/base::Microseconds(10),
|
||||||
/*max=*/base::Milliseconds(33), /*bucket_count=*/50);
|
/*max=*/base::Milliseconds(33), /*bucket_count=*/50);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// These values are persisted to logs. Entries should not be renumbered and
|
||||||
|
// numeric values should never be reused.
|
||||||
|
//
|
||||||
|
// LINT.IfChange(AnimationOrInteractionType)
|
||||||
|
enum class AnimationOrInteractionType {
|
||||||
|
kNone = 0,
|
||||||
|
kInteractionOnly = 1,
|
||||||
|
kAnimationOnly = 2,
|
||||||
|
kAnimationAndInteraction = 3,
|
||||||
|
kMaxValue = kAnimationAndInteraction,
|
||||||
|
};
|
||||||
|
// LINT.ThenChange(//tools/metrics/histograms/enums.xml:FrameHandlingType)
|
||||||
|
|
||||||
|
void RecordFrameTypes(bool is_handling_interaction,
|
||||||
|
bool is_handling_animation,
|
||||||
|
int num_pending_frames) {
|
||||||
|
AnimationOrInteractionType type;
|
||||||
|
if (is_handling_interaction && is_handling_animation) {
|
||||||
|
type = AnimationOrInteractionType::kAnimationAndInteraction;
|
||||||
|
} else if (is_handling_interaction) {
|
||||||
|
type = AnimationOrInteractionType::kInteractionOnly;
|
||||||
|
} else if (is_handling_animation) {
|
||||||
|
type = AnimationOrInteractionType::kAnimationOnly;
|
||||||
|
} else {
|
||||||
|
type = AnimationOrInteractionType::kNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
UMA_HISTOGRAM_ENUMERATION(
|
||||||
|
"GPU.Presentation.FrameHandlesAnimationOrInteraction", type);
|
||||||
|
|
||||||
|
// Although the current frame is free of interation and animation, the pending
|
||||||
|
// frame blocks the current frame from being swapped immediately when
|
||||||
|
// VSyncAlignedPresent and kPresentationDelayForInteractiveFrames are enabled.
|
||||||
|
// Note: |num_pending_frames| is always 0 when VSyncAlignedPresent is
|
||||||
|
// disabled.
|
||||||
|
if (type == AnimationOrInteractionType::kNone) {
|
||||||
|
UMA_HISTOGRAM_BOOLEAN(
|
||||||
|
"GPU.Presentation.NonAnimatedOrInteractiveFrameWithPendingFrame",
|
||||||
|
!!num_pending_frames);
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif // BUILDFLAG(IS_MAC)
|
#endif // BUILDFLAG(IS_MAC)
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -129,7 +171,7 @@ void ImageTransportSurfaceOverlayMacEGL::Present(
|
|||||||
// Commit the first pending frame before adding one more in Present() if there
|
// Commit the first pending frame before adding one more in Present() if there
|
||||||
// are more than supported .
|
// are more than supported .
|
||||||
if (ca_layer_tree_coordinator_->NumPendingSwaps() >= cap_max_pending_swaps_) {
|
if (ca_layer_tree_coordinator_->NumPendingSwaps() >= cap_max_pending_swaps_) {
|
||||||
TRACE_EVENT0("gpu", "Commit now. Exceeds the max pending swaps.");
|
TRACE_EVENT0("gpu", "Exceeds the max pending swaps. Commit now.");
|
||||||
CommitPresentedFrameToCA();
|
CommitPresentedFrameToCA();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -185,10 +227,16 @@ void ImageTransportSurfaceOverlayMacEGL::Present(
|
|||||||
|
|
||||||
if (base::FeatureList::IsEnabled(kPresentationDelayForInteractiveFrames) &&
|
if (base::FeatureList::IsEnabled(kPresentationDelayForInteractiveFrames) &&
|
||||||
!ca_layer_tree_coordinator_->NumPendingSwaps() &&
|
!ca_layer_tree_coordinator_->NumPendingSwaps() &&
|
||||||
!data.is_handling_interaction_or_animation) {
|
!data.is_handling_interaction && !data.is_handling_animation) {
|
||||||
delay_presenetation_until_next_vsync = false;
|
delay_presenetation_until_next_vsync = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (features::IsVSyncAlignedPresentEnabled() &&
|
||||||
|
base::FeatureList::IsEnabled(kPresentationDelayForInteractiveFrames)) {
|
||||||
|
RecordFrameTypes(data.is_handling_interaction, data.is_handling_animation,
|
||||||
|
ca_layer_tree_coordinator_->NumPendingSwaps());
|
||||||
|
}
|
||||||
|
|
||||||
if (vsync_callback_mac_) {
|
if (vsync_callback_mac_) {
|
||||||
vsync_callback_mac_keep_alive_counter_ = kMaxKeepAliveCounter;
|
vsync_callback_mac_keep_alive_counter_ = kMaxKeepAliveCounter;
|
||||||
if (delay_presenetation_until_next_vsync) {
|
if (delay_presenetation_until_next_vsync) {
|
||||||
|
@ -5388,6 +5388,17 @@ to ensure that the crash string is shown properly on the user-facing crash UI.
|
|||||||
<int value="3" label="Start on NTP"/>
|
<int value="3" label="Start on NTP"/>
|
||||||
</enum>
|
</enum>
|
||||||
|
|
||||||
|
<!-- LINT.IfChange(FrameHandlingType) -->
|
||||||
|
|
||||||
|
<enum name="FrameHandlingType">
|
||||||
|
<int value="0" label="None"/>
|
||||||
|
<int value="1" label="InteractionOnly"/>
|
||||||
|
<int value="2" label="AnimationOnly"/>
|
||||||
|
<int value="3" label="InteractionAndAnimation"/>
|
||||||
|
</enum>
|
||||||
|
|
||||||
|
<!-- LINT.ThenChange(//gpu/ipc/service/image_transport_surface_overlay_mac.mm:AnimationOrInteractionType) -->
|
||||||
|
|
||||||
<enum name="FsckResult">
|
<enum name="FsckResult">
|
||||||
<summary>
|
<summary>
|
||||||
These correspond to e2fsck exit codes. Note that 0 differs from e2fsck's man
|
These correspond to e2fsck exit codes. Note that 0 differs from e2fsck's man
|
||||||
|
@ -1199,6 +1199,33 @@ chromium-metrics-reviews@google.com.
|
|||||||
</summary>
|
</summary>
|
||||||
</histogram>
|
</histogram>
|
||||||
|
|
||||||
|
<histogram name="GPU.Presentation.FrameHandlesAnimationOrInteraction"
|
||||||
|
enum="FrameHandlingType" expires_after="2025-09-07">
|
||||||
|
<owner>magchen@chromium.org</owner>
|
||||||
|
<owner>vmiura@chromium.org</owner>
|
||||||
|
<owner>chrome-gpu-metric-alerts@chromium.org</owner>
|
||||||
|
<summary>
|
||||||
|
Recorded on Mac when a frame is ready to present and GPU Present() is
|
||||||
|
called. It records whether the current frame is handling interaction,
|
||||||
|
animation, both, or none.
|
||||||
|
</summary>
|
||||||
|
</histogram>
|
||||||
|
|
||||||
|
<histogram
|
||||||
|
name="GPU.Presentation.NonAnimatedOrInteractiveFrameWithPendingFrame"
|
||||||
|
enum="Boolean" expires_after="2025-09-07">
|
||||||
|
<owner>magchen@chromium.org</owner>
|
||||||
|
<owner>vmiura@chromium.org</owner>
|
||||||
|
<owner>chrome-gpu-metric-alerts@chromium.org</owner>
|
||||||
|
<summary>
|
||||||
|
Recorded on Mac for frames that are not handling interaction and animation
|
||||||
|
at the time when they are ready to present and GPU Present() is called . If
|
||||||
|
VSyncAlignedPresent and kPresentationDelayForInteractiveFrames are enabled,
|
||||||
|
this type of frames can be swapped immediately. However, they must wait in
|
||||||
|
the queue for VSync when there is a pending frame(s).
|
||||||
|
</summary>
|
||||||
|
</histogram>
|
||||||
|
|
||||||
<histogram name="GPU.Presentation.VSyncCallbackDelay" units="microseconds"
|
<histogram name="GPU.Presentation.VSyncCallbackDelay" units="microseconds"
|
||||||
expires_after="2025-08-10">
|
expires_after="2025-08-10">
|
||||||
<owner>magchen@chromium.org</owner>
|
<owner>magchen@chromium.org</owner>
|
||||||
|
@ -40,7 +40,8 @@ struct FrameData {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if BUILDFLAG(IS_MAC)
|
#if BUILDFLAG(IS_MAC)
|
||||||
bool is_handling_interaction_or_animation = false;
|
bool is_handling_interaction = false;
|
||||||
|
bool is_handling_animation = false;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user