From ce2e23a4e923e7abe9692f3223235c075dd504e4 Mon Sep 17 00:00:00 2001 From: Oleh Kuznetsov Date: Wed, 18 Dec 2024 16:07:50 +0000 Subject: [PATCH] Add "Fixed Perfomance Mode" system profile capture option --- core/os/android/adb/commands.go | 17 +++++++ core/os/android/device.go | 2 + core/os/device/device.proto | 1 + .../main/com/google/gapid/server/Tracer.java | 11 +++++ .../src/main/com/google/gapid/settings.proto | 3 +- .../com/google/gapid/views/TracerDialog.java | 28 +++++++++++- gapis/perfetto/android/trace.go | 44 ++++++++++++++++--- gapis/server/server.go | 3 ++ gapis/service/service.proto | 5 ++- 9 files changed, 106 insertions(+), 8 deletions(-) diff --git a/core/os/android/adb/commands.go b/core/os/android/adb/commands.go index 5d9760c47..4e5ccf267 100644 --- a/core/os/android/adb/commands.go +++ b/core/os/android/adb/commands.go @@ -375,6 +375,8 @@ func (b *binding) QueryPerfettoServiceState(ctx context.Context) (*device.Perfet // This has anecdotally not worked well in Q, but appears to be fine in R. result.CanDownloadWhileTracing = true + + result.HasFixedPerformanceMode = true } services, err := b.Shell("service", "list").Call(ctx) @@ -437,6 +439,21 @@ func (b *binding) SupportsAngle(ctx context.Context) bool { return os.GetAPIVersion() >= 29 } +func (b *binding) SetFixedPerformanceMode(ctx context.Context, value bool) error { + var stringValue string = "false" + if value { + stringValue = "true" + } + res, err := b.Shell("cmd power", "set-fixed-performance-mode-enabled", stringValue).Call(ctx) + if res != "" { + return log.Errf(ctx, nil, "cmd power set-fixed-performance-mode-enabled error: \n%s", res) + } + if err != nil { + return err + } + return nil +} + func (b *binding) QueryAngle(ctx context.Context) (*device.ANGLE, error) { if !b.SupportsAngle(ctx) { return nil, fmt.Errorf("ANGLE not supported on this device") diff --git a/core/os/android/device.go b/core/os/android/device.go index 129998d1b..f3b6fcff0 100644 --- a/core/os/android/device.go +++ b/core/os/android/device.go @@ -94,6 +94,8 @@ type Device interface { StartPerfettoTrace(ctx context.Context, config *perfetto_pb.TraceConfig, out string, stop task.Signal, ready task.Task) error // SupportsAngle returns true if this device will work with ANGLE SupportsAngle(ctx context.Context) bool + // Enable/Disable Fixed Performance Mode + SetFixedPerformanceMode(ctx context.Context, value bool) error } // LogcatMessage represents a single logcat message. diff --git a/core/os/device/device.proto b/core/os/device/device.proto index f2b188199..b56def0bb 100644 --- a/core/os/device/device.proto +++ b/core/os/device/device.proto @@ -195,6 +195,7 @@ message PerfettoCapability { // Whether the Perfetto tracing API supports tracing to a file on the device // given a path, rather than a file descriptor. bool can_provide_trace_file_path = 7; + bool has_fixed_performance_mode = 8; } message GPUProfiling { diff --git a/gapic/src/main/com/google/gapid/server/Tracer.java b/gapic/src/main/com/google/gapid/server/Tracer.java index e1334d946..7ac89f7c7 100644 --- a/gapic/src/main/com/google/gapid/server/Tracer.java +++ b/gapic/src/main/com/google/gapid/server/Tracer.java @@ -92,6 +92,11 @@ public boolean stop() { return sendEvent(Service.TraceEvent.Stop); } + @Override + public boolean cancel() { + return sendEvent(Service.TraceEvent.Cancel); + } + private boolean sendEvent(Service.TraceEvent event) { if (done.get()) { return false; @@ -145,6 +150,12 @@ public static interface Trace { * @returns whether the stop request was sent. */ public boolean stop(); + + /** + * Requests the current trace to be canceled. + * @returns whether the cancel request was sent. + */ + public boolean cancel(); } /** diff --git a/gapic/src/main/com/google/gapid/settings.proto b/gapic/src/main/com/google/gapid/settings.proto index 22f9a24d2..40371eb5f 100644 --- a/gapic/src/main/com/google/gapid/settings.proto +++ b/gapic/src/main/com/google/gapid/settings.proto @@ -115,7 +115,6 @@ message Trace { string device_serial = 1; string device_name = 2; string type = 3; - bool last_frame_trace_was_vulkan = 21; string api = 4 [deprecated = true]; // Kept for de-serialization. string uri = 5; string arguments = 6; @@ -133,6 +132,8 @@ message Trace { Duration profile_duration = 18; string process_name = 19; bool load_validation_layer = 20; + bool last_frame_trace_was_vulkan = 21; + bool fixed_performance_mode = 22; } message Perfetto { diff --git a/gapic/src/main/com/google/gapid/views/TracerDialog.java b/gapic/src/main/com/google/gapid/views/TracerDialog.java index 91e69d547..35adcff93 100644 --- a/gapic/src/main/com/google/gapid/views/TracerDialog.java +++ b/gapic/src/main/com/google/gapid/views/TracerDialog.java @@ -347,6 +347,7 @@ private static class TraceInput extends Composite { private final Button includeUnsupportedExtensions; private final Button loadValidationLayer; private final Button clearCache; + private final Button fixedPerformanceMode; private final Composite systemTracingConfig; private final Label systemTracingConfigLabel; private final FileTextbox.Directory directory; @@ -532,6 +533,10 @@ protected String createAndShowDialog(String current) { optGroup, "Load Vulkan Validation Layer", trace.getLoadValidationLayer()); loadValidationLayer.setEnabled(false); loadValidationLayer.setVisible(enableLoadValidationLayer.get()); + fixedPerformanceMode = createCheckbox( + optGroup, "Fixed Performance Mode", trace.getFixedPerformanceMode()); + fixedPerformanceMode.setEnabled(false); + fixedPerformanceMode.setVisible(false); systemTracingConfig = withLayoutData( createComposite(optGroup, withMargin(new GridLayout(2, false), 5, 0)), @@ -776,6 +781,13 @@ private void updateOnConfigChange(Settings settings, SettingsProto.TraceOrBuilde systemTracingConfig.setVisible(isSystem); + boolean hasFixedPerformanceMode = + isSystem + && dev != null + && dev.device.getConfiguration().getPerfettoCapability().getHasFixedPerformanceMode(); + fixedPerformanceMode.setEnabled(hasFixedPerformanceMode); + fixedPerformanceMode.setVisible(hasFixedPerformanceMode); + if (!userHasChangedOutputFile) { file.setText(formatTraceName(friendlyName)); userHasChangedOutputFile = false; // cancel the modify event from set call. @@ -1092,6 +1104,8 @@ public TraceRequest getTraceRequest(Settings settings) { trace.setClearCache(clearCache.getSelection()); options.setClearCache(clearCache.getSelection()); } + trace.setFixedPerformanceMode(fixedPerformanceMode.getSelection()); + options.setFixedPerformanceMode(fixedPerformanceMode.getSelection()); if (dev.isFuchsia()) { if(type == TraceType.System) { @@ -1300,6 +1314,18 @@ public void onProgress(StatusResponse progress) { update(); } + @Override + protected void handleShellCloseEvent() { +// trace.cancel(); + super.handleShellCloseEvent(); + } + + @Override + protected void cancelPressed() { +// trace.cancel(); + super.handleShellCloseEvent(); + } + @Override public void onFailure(Throwable e) { error = e; @@ -1341,7 +1367,7 @@ protected Control createDialogArea(Composite parent) { // Make sure the stop signal is issued when the dialog is closed. getShell().addListener(SWT.Close, e -> { if (!successful()) { - trace.stop(); + trace.cancel(); } }); diff --git a/gapis/perfetto/android/trace.go b/gapis/perfetto/android/trace.go index e29776552..8c8bb9a0c 100644 --- a/gapis/perfetto/android/trace.go +++ b/gapis/perfetto/android/trace.go @@ -78,6 +78,20 @@ func hasDataSourceEnabled(perfettoConfig *perfetto_pb.TraceConfig, ds string) bo return false } +func setupFixedPerformanceMode(ctx context.Context, d adb.Device, opts *service.TraceOptions) (app.Cleanup, error) { + if opts.FixedPerformanceMode { + var cleanup app.Cleanup + cleanup = cleanup.Then(func(ctx context.Context) { + d.SetFixedPerformanceMode(ctx, false) + }) + if err := d.SetFixedPerformanceMode(ctx, true); err != nil { + return cleanup.Invoke(ctx), err + } + return cleanup, nil + } + return nil, nil +} + // SetupProfileLayersSource configures the device to allow packages to be used as layer sources for profiling func SetupProfileLayersSource(ctx context.Context, d adb.Device, apk *android.InstalledPackage, abi *device.ABI) (app.Cleanup, error) { supported, packageName, cleanup, err := d.PrepareGpuProfiling(ctx, apk) @@ -137,6 +151,14 @@ func Start(ctx context.Context, d adb.Device, a *android.ActivityAction, opts *s var cleanup app.Cleanup + nextCleanup, err := setupFixedPerformanceMode(ctx, d, opts) + if nextCleanup != nil { + cleanup = cleanup.Then(nextCleanup) + } + if err != nil { + return nil, cleanup.Invoke(ctx), err + } + if a != nil { ctx = log.V{ "package": a.Package.Name, @@ -240,8 +262,14 @@ func (p *Process) Capture(ctx context.Context, start task.Signal, stop task.Sign // Signal that we are ready to start. atomic.StoreInt64(written, 1) - if p.deferred && !start.Wait(ctx) { - return 0, log.Err(ctx, nil, "Cancelled") + if p.deferred { + select { + case <-start: + break + case <-stop: + case <-task.ShouldStop(ctx): + return 0, log.Err(ctx, nil, "Cancelled") + } } if err := p.device.StartPerfettoTrace(ctx, p.config, perfettoTraceFile, stop, ready); err != nil { @@ -356,9 +384,15 @@ func (p *Process) captureWithClientApi(ctx context.Context, start task.Signal, s delayedReady := task.Delay(ready, 250*time.Millisecond) atomic.StoreInt64(written, 1) - if p.deferred && !start.Wait(ctx) { - ts.Stop(ctx) - return 0, errors.New("Cancelled") + if p.deferred { + select { + case <-start: + break + case <-stop: + case <-task.ShouldStop(ctx): + ts.Stop(ctx) + return 0, errors.New("Cancelled") + } } delayedReady(ctx) ts.Start(ctx) diff --git a/gapis/server/server.go b/gapis/server/server.go index c0a8e59e8..aff16b6fe 100644 --- a/gapis/server/server.go +++ b/gapis/server/server.go @@ -794,6 +794,9 @@ func (r *traceHandler) Event(ctx context.Context, req service.TraceEvent) (*serv } r.stopFunc(ctx) r.doneSignal.Wait(ctx) + case service.TraceEvent_Cancel: + r.stopFunc(ctx) + r.doneSignal.Wait(ctx) case service.TraceEvent_Status: // intentionally empty } diff --git a/gapis/service/service.proto b/gapis/service/service.proto index 71f17c993..636bfe6bc 100644 --- a/gapis/service/service.proto +++ b/gapis/service/service.proto @@ -1370,12 +1370,15 @@ message TraceOptions { bool load_validation_layer = 28; // The config options to use if doing a Fuchsia trace. FuchsiaTraceConfig fuchsia_trace_config = 29; + // Do we need to set fixed performance mode on device + bool fixed_performance_mode = 30; } enum TraceEvent { Begin = 0; // Begin tracing (only valid if started with MidExecution) Stop = 1; // Flush and stop the trace - Status = 2; // Get the status of the trace + Cancel = 2; // Cancel the trace + Status = 3; // Get the status of the trace } message StatusResponse {