1 /*
2 * Copyright © 2021 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #ifndef INTEL_DRIVER_DS_H
25 #define INTEL_DRIVER_DS_H
26
27 #include <stdint.h>
28
29 #include "util/macros.h"
30 #include "util/perf/u_trace.h"
31 #include "util/u_vector.h"
32
33 #include "dev/intel_device_info.h"
34
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38
39 enum intel_ds_api {
40 INTEL_DS_API_OPENGL,
41 INTEL_DS_API_VULKAN,
42 };
43
44 enum intel_ds_stall_flag {
45 INTEL_DS_DEPTH_CACHE_FLUSH_BIT = BITFIELD_BIT(0),
46 INTEL_DS_DATA_CACHE_FLUSH_BIT = BITFIELD_BIT(1),
47 INTEL_DS_HDC_PIPELINE_FLUSH_BIT = BITFIELD_BIT(2),
48 INTEL_DS_RENDER_TARGET_CACHE_FLUSH_BIT = BITFIELD_BIT(3),
49 INTEL_DS_TILE_CACHE_FLUSH_BIT = BITFIELD_BIT(4),
50 INTEL_DS_STATE_CACHE_INVALIDATE_BIT = BITFIELD_BIT(5),
51 INTEL_DS_CONST_CACHE_INVALIDATE_BIT = BITFIELD_BIT(6),
52 INTEL_DS_VF_CACHE_INVALIDATE_BIT = BITFIELD_BIT(7),
53 INTEL_DS_TEXTURE_CACHE_INVALIDATE_BIT = BITFIELD_BIT(8),
54 INTEL_DS_INST_CACHE_INVALIDATE_BIT = BITFIELD_BIT(9),
55 INTEL_DS_STALL_AT_SCOREBOARD_BIT = BITFIELD_BIT(10),
56 INTEL_DS_DEPTH_STALL_BIT = BITFIELD_BIT(11),
57 INTEL_DS_CS_STALL_BIT = BITFIELD_BIT(12),
58 INTEL_DS_UNTYPED_DATAPORT_CACHE_FLUSH_BIT = BITFIELD_BIT(13),
59 INTEL_DS_PSS_STALL_SYNC_BIT = BITFIELD_BIT(14),
60 INTEL_DS_END_OF_PIPE_BIT = BITFIELD_BIT(15),
61 INTEL_DS_CCS_CACHE_FLUSH_BIT = BITFIELD_BIT(16),
62 };
63
64 enum intel_ds_tracepoint_flags {
65 /**
66 * Whether the tracepoint's timestamp must be recorded with as an
67 * end-of-pipe timestamp.
68 */
69 INTEL_DS_TRACEPOINT_FLAG_END_OF_PIPE = BITFIELD_BIT(0),
70 /**
71 * Whether this tracepoint's timestamp is recorded on the compute pipeline.
72 */
73 INTEL_DS_TRACEPOINT_FLAG_END_OF_PIPE_CS = BITFIELD_BIT(1),
74
75 };
76
77 /* Convert internal driver PIPE_CONTROL stall bits to intel_ds_stall_flag. */
78 typedef enum intel_ds_stall_flag (*intel_ds_stall_cb_t)(uint32_t flags);
79
80 enum intel_ds_queue_stage {
81 INTEL_DS_QUEUE_STAGE_QUEUE,
82 INTEL_DS_QUEUE_STAGE_FRAME,
83 INTEL_DS_QUEUE_STAGE_CMD_BUFFER,
84 INTEL_DS_QUEUE_STAGE_INTERNAL_OPS,
85 INTEL_DS_QUEUE_STAGE_STALL,
86 INTEL_DS_QUEUE_STAGE_COMPUTE,
87 INTEL_DS_QUEUE_STAGE_AS,
88 INTEL_DS_QUEUE_STAGE_RT,
89 INTEL_DS_QUEUE_STAGE_RENDER_PASS,
90 INTEL_DS_QUEUE_STAGE_BLORP,
91 INTEL_DS_QUEUE_STAGE_DRAW,
92 INTEL_DS_QUEUE_STAGE_DRAW_MESH,
93 INTEL_DS_QUEUE_STAGE_N_STAGES,
94 };
95
96 struct intel_ds_device {
97 struct intel_device_info info;
98
99 /* DRM fd */
100 int fd;
101
102 /* API of this device */
103 enum intel_ds_api api;
104
105 /* GPU identifier (minor number) */
106 uint32_t gpu_id;
107
108 /* Clock identifier for this device. */
109 uint32_t gpu_clock_id;
110
111 /* The timestamp at the point where we first emitted the clock_sync..
112 * this will be a *later* timestamp that the first GPU traces (since
113 * we capture the first clock_sync from the CPU *after* the first GPU
114 * tracepoints happen). To avoid confusing perfetto we need to drop
115 * the GPU traces with timestamps before this.
116 */
117 uint64_t sync_gpu_ts;
118
119 /* Next timestamp after which we should resend a clock correlation. */
120 uint64_t next_clock_sync_ns;
121
122 /* Unique perfetto identifier for the context */
123 uint64_t iid;
124
125 /* Event ID generator (manipulate only inside
126 * IntelRenderpassDataSource::Trace)
127 */
128 uint64_t event_id;
129
130 /* Tracepoint name perfetto identifiers for each of the events. */
131 uint64_t tracepoint_iids[96];
132
133 /* Protects submissions of u_trace data to trace_context */
134 simple_mtx_t trace_context_mutex;
135
136 struct u_trace_context trace_context;
137
138 /* List of intel_ds_queue */
139 struct list_head queues;
140 };
141
142 struct intel_ds_stage {
143 /* Unique hw_queue IID */
144 uint64_t queue_iid;
145
146 /* Unique stage IID */
147 uint64_t stage_iid;
148
149 /* Start timestamp of the last work element. We have a array indexed by
150 * level so that we can track multi levels of events (like
151 * primary/secondary command buffers).
152 */
153 uint64_t start_ns[5];
154
155 /* Current number of valid elements in start_ns */
156 uint32_t level;
157 };
158
159 struct intel_ds_queue {
160 struct list_head link;
161
162 /* Device this queue belongs to */
163 struct intel_ds_device *device;
164
165 /* Unique name of the queue */
166 char name[80];
167
168 /* Counter incremented on each intel_ds_end_submit() call */
169 uint64_t submission_id;
170
171 struct intel_ds_stage stages[INTEL_DS_QUEUE_STAGE_N_STAGES];
172 };
173
174 struct intel_ds_flush_data {
175 struct intel_ds_queue *queue;
176
177 /* u_trace element in which we copy other traces in case we deal with
178 * reusable command buffers.
179 */
180 struct u_trace trace;
181
182 /* Unique submission ID associated with the trace */
183 uint64_t submission_id;
184 };
185
186 void intel_driver_ds_init(void);
187
188 void intel_ds_device_init(struct intel_ds_device *device,
189 const struct intel_device_info *devinfo,
190 int drm_fd,
191 uint32_t gpu_id,
192 enum intel_ds_api api);
193 void intel_ds_device_fini(struct intel_ds_device *device);
194
195 struct intel_ds_queue *
196 intel_ds_device_init_queue(struct intel_ds_device *device,
197 struct intel_ds_queue *queue,
198 const char *fmt_name,
199 ...);
200
201 void intel_ds_flush_data_init(struct intel_ds_flush_data *data,
202 struct intel_ds_queue *queue,
203 uint64_t submission_id);
204
205 void intel_ds_flush_data_fini(struct intel_ds_flush_data *data);
206
207 void intel_ds_queue_flush_data(struct intel_ds_queue *queue,
208 struct u_trace *ut,
209 struct intel_ds_flush_data *data,
210 uint32_t frame_nr,
211 bool free_data);
212
213 void intel_ds_device_process(struct intel_ds_device *device, bool eof);
214
215 #ifdef HAVE_PERFETTO
216
217 uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue);
218 void intel_ds_end_submit(struct intel_ds_queue *queue,
219 uint64_t start_ts);
220
221 #else
222
intel_ds_begin_submit(struct intel_ds_queue * queue)223 static inline uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue)
224 {
225 return 0;
226 }
227
intel_ds_end_submit(struct intel_ds_queue * queue,uint64_t start_ts)228 static inline void intel_ds_end_submit(struct intel_ds_queue *queue,
229 uint64_t start_ts)
230 {
231 }
232
233 #endif /* HAVE_PERFETTO */
234
235 #ifdef __cplusplus
236 }
237 #endif
238
239 #endif /* INTEL_DRIVER_DS_H */
240