• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    INTEL_DS_L3_FABRIC_FLUSH_BIT              = BITFIELD_BIT(17),
63 };
64 
65 enum intel_ds_tracepoint_flags {
66    /**
67     * Whether the tracepoint's timestamp must be recorded with as an
68     * end-of-pipe timestamp.
69     */
70    INTEL_DS_TRACEPOINT_FLAG_END_OF_PIPE    = BITFIELD_BIT(0),
71    /**
72     * Whether this tracepoint's timestamp is recorded on the compute pipeline.
73     */
74    INTEL_DS_TRACEPOINT_FLAG_END_CS         = BITFIELD_BIT(1),
75    /**
76     * Whether this tracepoint's timestamp is recorded on the compute pipeline
77     * or from top of pipe if there was no dispatch (useful for acceleration
78     * structure builds where the runtime might choose to not emit anything for
79     * a number of reasons).
80     */
81    INTEL_DS_TRACEPOINT_FLAG_END_CS_OR_NOOP = BITFIELD_BIT(2),
82 };
83 
84 /* Convert internal driver PIPE_CONTROL stall bits to intel_ds_stall_flag. */
85 typedef enum intel_ds_stall_flag (*intel_ds_stall_cb_t)(uint32_t flags);
86 
87 enum intel_ds_queue_stage {
88    INTEL_DS_QUEUE_STAGE_QUEUE,
89    INTEL_DS_QUEUE_STAGE_FRAME,
90    INTEL_DS_QUEUE_STAGE_CMD_BUFFER,
91    INTEL_DS_QUEUE_STAGE_INTERNAL_OPS,
92    INTEL_DS_QUEUE_STAGE_STALL,
93    INTEL_DS_QUEUE_STAGE_COMPUTE,
94    INTEL_DS_QUEUE_STAGE_AS,
95    INTEL_DS_QUEUE_STAGE_RT,
96    INTEL_DS_QUEUE_STAGE_RENDER_PASS,
97    INTEL_DS_QUEUE_STAGE_BLORP,
98    INTEL_DS_QUEUE_STAGE_DRAW,
99    INTEL_DS_QUEUE_STAGE_DRAW_MESH,
100    INTEL_DS_QUEUE_STAGE_N_STAGES,
101 };
102 
103 struct intel_ds_device {
104    struct intel_device_info info;
105 
106    /* DRM fd */
107    int fd;
108 
109    /* API of this device */
110    enum intel_ds_api api;
111 
112    /* GPU identifier (minor number) */
113    uint32_t gpu_id;
114 
115    /* Clock identifier for this device. */
116    uint32_t gpu_clock_id;
117 
118    /* The timestamp at the point where we first emitted the clock_sync..
119     * this  will be a *later* timestamp that the first GPU traces (since
120     * we capture the first clock_sync from the CPU *after* the first GPU
121     * tracepoints happen).  To avoid confusing perfetto we need to drop
122     * the GPU traces with timestamps before this.
123     */
124    uint64_t sync_gpu_ts;
125 
126    /* Next timestamp after which we should resend a clock correlation. */
127    uint64_t next_clock_sync_ns;
128 
129    /* Unique perfetto identifier for the context */
130    uint64_t iid;
131 
132    /* Event ID generator (manipulate only inside
133     * IntelRenderpassDataSource::Trace)
134     */
135    uint64_t event_id;
136 
137    /* Tracepoint name perfetto identifiers for each of the events. */
138    uint64_t tracepoint_iids[96];
139 
140    /* Protects submissions of u_trace data to trace_context */
141    simple_mtx_t trace_context_mutex;
142 
143    struct u_trace_context trace_context;
144 
145    /* List of intel_ds_queue */
146    struct list_head queues;
147 };
148 
149 struct intel_ds_stage {
150    /* Unique hw_queue IID */
151    uint64_t queue_iid;
152 
153    /* Unique stage IID */
154    uint64_t stage_iid;
155 
156    /* Start timestamp of the last work element. We have a array indexed by
157     * level so that we can track multi levels of events (like
158     * primary/secondary command buffers).
159     */
160    uint64_t start_ns[5];
161 
162    /* Current number of valid elements in start_ns */
163    uint32_t level;
164 };
165 
166 struct intel_ds_queue {
167    struct list_head link;
168 
169    /* Device this queue belongs to */
170    struct intel_ds_device *device;
171 
172    /* Unique name of the queue */
173    char name[80];
174 
175    /* Counter incremented on each intel_ds_end_submit() call */
176    uint64_t submission_id;
177 
178    struct intel_ds_stage stages[INTEL_DS_QUEUE_STAGE_N_STAGES];
179 };
180 
181 struct intel_ds_flush_data {
182    struct intel_ds_queue *queue;
183 
184    /* u_trace element in which we copy other traces in case we deal with
185     * reusable command buffers.
186     */
187    struct u_trace trace;
188 
189    /* Unique submission ID associated with the trace */
190    uint64_t submission_id;
191 };
192 
193 void intel_driver_ds_init(void);
194 
195 void intel_ds_device_init(struct intel_ds_device *device,
196                           const struct intel_device_info *devinfo,
197                           int drm_fd,
198                           uint32_t gpu_id,
199                           enum intel_ds_api api);
200 void intel_ds_device_fini(struct intel_ds_device *device);
201 
202 struct intel_ds_queue *
203 intel_ds_device_init_queue(struct intel_ds_device *device,
204                            struct intel_ds_queue *queue,
205                            const char *fmt_name,
206                            ...);
207 
208 void intel_ds_flush_data_init(struct intel_ds_flush_data *data,
209                               struct intel_ds_queue *queue,
210                               uint64_t submission_id);
211 
212 void intel_ds_flush_data_fini(struct intel_ds_flush_data *data);
213 
214 void intel_ds_queue_flush_data(struct intel_ds_queue *queue,
215                                struct u_trace *ut,
216                                struct intel_ds_flush_data *data,
217                                uint32_t frame_nr,
218                                bool free_data);
219 
220 void intel_ds_device_process(struct intel_ds_device *device, bool eof);
221 
222 #ifdef HAVE_PERFETTO
223 
224 uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue);
225 void intel_ds_end_submit(struct intel_ds_queue *queue,
226                          uint64_t start_ts);
227 
228 #else
229 
intel_ds_begin_submit(struct intel_ds_queue * queue)230 static inline uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue)
231 {
232    return 0;
233 }
234 
intel_ds_end_submit(struct intel_ds_queue * queue,uint64_t start_ts)235 static inline void intel_ds_end_submit(struct intel_ds_queue *queue,
236                                        uint64_t start_ts)
237 {
238 }
239 
240 #endif /* HAVE_PERFETTO */
241 
242 #ifdef __cplusplus
243 }
244 #endif
245 
246 #endif /* INTEL_DRIVER_DS_H */
247