-
Notifications
You must be signed in to change notification settings - Fork 0
/
tracer.go
147 lines (134 loc) · 5.39 KB
/
tracer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Copyright (C) 2018 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package tracer
import (
"bytes"
"context"
"io"
"time"
"github.com/google/gapid/core/app"
"github.com/google/gapid/core/app/layout"
"github.com/google/gapid/core/event/task"
"github.com/google/gapid/core/os/device/bind"
gapii "github.com/google/gapid/gapii/client"
"github.com/google/gapid/gapis/api"
"github.com/google/gapid/gapis/api/sync"
"github.com/google/gapid/gapis/service"
"github.com/google/gapid/gapis/service/path"
)
// TraceTargetTreeNode represents a node in the traceable application
// Tree
type TraceTargetTreeNode struct {
Name string // What is the name of this tree node
Icon []byte // What is the icon for this node
URI string // What is the URI of this node
TraceURI string // Can this node be traced
Children []string // Child URIs of this node
Parent string // What is the URI of this node's parent
ApplicationName string // The friendly application name for the trace node if it exists
ExecutableName string // The friendly executable name for the trace node if it exists
}
// Process is a handle to an initialized trace that can be started.
type Process interface {
// Capture connects to this trace and waits for a capture to be delivered.
// It copies the capture into the supplied writer.
// If the process was started with the DeferStart flag, then tracing will wait
// until start is fired.
// Capturing will stop when the stop signal is fired (clean stop) or the
// context is cancelled (abort).
Capture(ctx context.Context, start task.Signal, stop task.Signal, ready task.Task, w io.Writer, written *int64) (size int64, err error)
}
// Tracer is an option interface that a bind.Device can implement.
// If it exists, it is used to set up and connect to a tracing application.
type Tracer interface {
// TraceConfiguration returns the device's supported trace configuration.
TraceConfiguration(ctx context.Context) (*service.DeviceTraceConfiguration, error)
// GetTraceTargetNode returns a TraceTargetTreeNode for the given URI
// on the device
GetTraceTargetNode(ctx context.Context, uri string, iconDensity float32) (*TraceTargetTreeNode, error)
// FindTraceTargets finds TraceTargetTreeNodes for a given search string on
// the device
FindTraceTargets(ctx context.Context, uri string) ([]*TraceTargetTreeNode, error)
// SetupTrace starts the application on the device, and causes it to wait
// for the trace to be started. It returns the process that was created, as
// well as a function that can be used to clean up the device
SetupTrace(ctx context.Context, o *service.TraceOptions) (Process, app.Cleanup, error)
// GetDevice returns the device associated with this tracer
GetDevice() bind.Device
// ProcessProfilingData takes a buffer for a Perfetto trace and translates it into
// a ProfilingData
ProcessProfilingData(ctx context.Context, buffer *bytes.Buffer, capture *path.Capture, staticAnalysisResult chan *api.StaticAnalysisProfileData, handleMapping map[uint64][]service.VulkanHandleMappingItem, syncData *sync.Data) (*service.ProfilingData, error)
// Validate validates the GPU profiling capabilities of the given device and returns
// an error if validation failed or the GPU profiling data is invalid.
Validate(ctx context.Context, enableLocalFiles bool) (*service.DeviceValidationResult, error)
}
// LayersFromOptions Parses the perfetto options, and returns the required layers
func LayersFromOptions(ctx context.Context, o *service.TraceOptions) []string {
ret := []string{}
if o.PerfettoConfig == nil {
return ret
}
added := map[string]struct{}{}
for _, x := range o.PerfettoConfig.GetDataSources() {
if layer, err := layout.LayerFromDataSource(x.GetConfig().GetName()); err == nil {
if _, err := layout.LibraryFromLayerName(layer); err == nil {
if _, ok := added[layer]; !ok {
added[layer] = struct{}{}
ret = append(ret, layer)
}
}
}
}
return ret
}
// GapiiOptions converts the given TraceOptions to gapii.Options.
func GapiiOptions(o *service.TraceOptions) gapii.Options {
apis := gapii.VulkanAPI
enableAngle := o.Type == service.TraceType_ANGLE
flags := gapii.Flags(0)
if o.DeferStart {
flags |= gapii.DeferStart
}
if o.NoBuffer {
flags |= gapii.NoBuffer
}
if o.HideUnknownExtensions {
flags |= gapii.HideUnknownExtensions
}
if o.RecordTraceTimes {
flags |= gapii.StoreTimestamps
}
if o.DisableCoherentMemoryTracker {
flags |= gapii.DisableCoherentMemoryTracker
}
if o.WaitForDebugger {
flags |= gapii.WaitForDebugger
}
if o.IgnoreFrameBoundaryDelimiters {
flags |= gapii.IgnoreFrameBoundaryDelimiters
}
return gapii.Options{
o.ObserveFrameFrequency,
o.StartFrame,
o.FramesToCapture,
time.Duration(o.Duration * float32(time.Second)),
apis,
flags,
o.AdditionalCommandLineArgs,
enableAngle,
o.PipeName,
o.ProcessName,
o.LoadValidationLayer,
}
}