-
Notifications
You must be signed in to change notification settings - Fork 135
/
replay.go
150 lines (135 loc) · 4.57 KB
/
replay.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
148
149
150
// Copyright (C) 2017 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 replay
import (
"context"
"github.com/google/gapid/core/event/task"
"github.com/google/gapid/core/os/device"
"github.com/google/gapid/gapis/api/transform"
"github.com/google/gapid/gapis/capture"
"github.com/google/gapid/gapis/service/path"
)
// Generator is the interface for types that support replay generation.
type Generator interface {
// Replay is called when a replay pass is ready to be sent to the replay
// device. Replay may filter or transform the list of commands, satisfying
// all the specified requests and config, before outputting the final
// command stream to out.
Replay(
ctx context.Context,
intent Intent,
cfg Config,
dependentPayload string,
requests []RequestAndResult,
device *device.Instance,
capture *capture.GraphicsCapture,
out transform.Writer) error
}
// SplitGenerator is the interface for types that support
// split-replay generation.
type SplitGenerator interface {
Generator
// GetInitialPayload returns a set of instructions
// that can be used to set up the replay.
GetInitialPayload(ctx context.Context,
capture *path.Capture,
device *device.Instance,
out transform.Writer) error
// CleanupResources returns a set of instructions
// that can be used to clean up from the Initial payload.
CleanupResources(ctx context.Context,
device *device.Instance,
out transform.Writer) error
}
// Intent describes the source capture and replay target information used for
// issuing a replay request.
type Intent struct {
Device *path.Device // The path to the device being used for replay.
Capture *path.Capture // The path to the capture that is being replayed.
}
// Config is a user-defined type used to describe the type of replay being
// requested. Replay requests made with configs that have equality (==) will
// likely be batched into the same replay pass. Configs can be used to force
// requests into different replay passes. For example, by issuing requests with
// different configs we can prevent a profiling Request from being issued in the
// same pass as a Request to render all draw calls in wireframe.
type Config interface{}
// Request is a user-defined type that holds information relevant to a single
// replay request. An example Request would be one that informs ReplayTransforms
// to insert a postback of the currently bound render-target content at a
// specific command.
type Request interface{}
// Result is the function called for the result of a request.
// One of val and err must be nil.
type Result func(val interface{}, err error)
// Do calls f and passes the return value-error pair to Result.
func (r Result) Do(f func() (val interface{}, err error)) error {
val, err := f()
if err != nil {
r(nil, err)
return err
}
r(val, nil)
return nil
}
// Transform returns a new Result that passes the non-error value through f
// before calling the original r.
func (r Result) Transform(f func(in interface{}) (out interface{}, err error)) Result {
return func(val interface{}, err error) {
if err != nil {
r(nil, err)
return
}
if val, err := f(val); err != nil {
r(nil, err)
} else {
r(val, nil)
}
}
}
// RequestAndResult is a pair of Request and Result.
type RequestAndResult struct {
Request Request
Result Result
}
// TODO(apbodnar) move this into whatever eventually calls Profile()
type SignalHandler struct {
StartSignal task.Signal
StartFunc task.Task
ReadySignal task.Signal
ReadyFunc task.Task
StopSignal task.Signal
StopFunc task.Task
DoneSignal task.Signal
DoneFunc task.Task
Written int64
Err error
}
func NewSignalHandler() *SignalHandler {
startSignal, startFunc := task.NewSignal()
readySignal, readyFunc := task.NewSignal()
stopSignal, stopFunc := task.NewSignal()
doneSignal, doneFunc := task.NewSignal()
handler := &SignalHandler{
StartSignal: startSignal,
StartFunc: startFunc,
ReadySignal: readySignal,
ReadyFunc: readyFunc,
StopSignal: stopSignal,
StopFunc: stopFunc,
DoneSignal: doneSignal,
DoneFunc: doneFunc,
}
return handler
}