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 };
59 
60 /* Convert internal driver PIPE_CONTROL stall bits to intel_ds_stall_flag. */
61 typedef enum intel_ds_stall_flag (*intel_ds_stall_cb_t)(uint32_t flags);
62 
63 enum intel_ds_queue_stage {
64    INTEL_DS_QUEUE_STAGE_CMD_BUFFER,
65    INTEL_DS_QUEUE_STAGE_STALL,
66    INTEL_DS_QUEUE_STAGE_COMPUTE,
67    INTEL_DS_QUEUE_STAGE_RENDER_PASS,
68    INTEL_DS_QUEUE_STAGE_BLORP,
69    INTEL_DS_QUEUE_STAGE_DRAW,
70    INTEL_DS_QUEUE_STAGE_N_STAGES,
71 };
72 
73 struct intel_ds_device {
74    struct intel_device_info info;
75 
76    /* DRM fd */
77    int fd;
78 
79    /* API of this device */
80    enum intel_ds_api api;
81 
82    /* GPU identifier (minor number) */
83    uint32_t gpu_id;
84 
85    /* Clock identifier for this device. */
86    uint32_t gpu_clock_id;
87 
88    /* The timestamp at the point where we first emitted the clock_sync..
89     * this  will be a *later* timestamp that the first GPU traces (since
90     * we capture the first clock_sync from the CPU *after* the first GPU
91     * tracepoints happen).  To avoid confusing perfetto we need to drop
92     * the GPU traces with timestamps before this.
93     */
94    uint64_t sync_gpu_ts;
95 
96    /* Next timestamp after which we should resend a clock correlation. */
97    uint64_t next_clock_sync_ns;
98 
99    /* Unique perfetto identifier for the context */
100    uint64_t iid;
101 
102    /* Event ID generator */
103    uint64_t event_id;
104 
105    struct u_trace_context trace_context;
106 
107    /* List of intel_ds_queue */
108    struct u_vector queues;
109 };
110 
111 struct intel_ds_stage {
112    /* Unique hw_queue IID */
113    uint64_t queue_iid;
114 
115    /* Unique stage IID */
116    uint64_t stage_iid;
117 
118    /* Start timestamp of the last work element */
119    uint64_t start_ns;
120 };
121 
122 struct intel_ds_queue {
123    /* Device this queue belongs to */
124    struct intel_ds_device *device;
125 
126    /* Unique queue ID across the device */
127    uint32_t queue_id;
128 
129    /* Unique name of the queue */
130    char name[80];
131 
132    /* Counter incremented on each intel_ds_end_submit() call */
133    uint64_t submission_id;
134 
135    struct intel_ds_stage stages[INTEL_DS_QUEUE_STAGE_N_STAGES];
136 };
137 
138 struct intel_ds_flush_data {
139    struct intel_ds_queue *queue;
140 
141    /* u_trace element in which we copy other traces in case we deal with
142     * reusable command buffers.
143     */
144    struct u_trace trace;
145 
146    /* Unique submission ID associated with the trace */
147    uint64_t submission_id;
148 };
149 
150 void intel_driver_ds_init(void);
151 
152 void intel_ds_device_init(struct intel_ds_device *device,
153                           struct intel_device_info *devinfo,
154                           int drm_fd,
155                           uint32_t gpu_id,
156                           enum intel_ds_api api);
157 void intel_ds_device_fini(struct intel_ds_device *device);
158 
159 struct intel_ds_queue *intel_ds_device_add_queue(struct intel_ds_device *device,
160                                                  const char *fmt_name,
161                                                  ...);
162 
163 void intel_ds_flush_data_init(struct intel_ds_flush_data *data,
164                               struct intel_ds_queue *queue,
165                               uint64_t submission_id);
166 
167 void intel_ds_flush_data_fini(struct intel_ds_flush_data *data);
168 
169 #ifdef HAVE_PERFETTO
170 
171 uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue);
172 void intel_ds_end_submit(struct intel_ds_queue *queue,
173                          uint64_t start_ts);
174 
175 #else
176 
intel_ds_begin_submit(struct intel_ds_queue * queue)177 static inline uint64_t intel_ds_begin_submit(struct intel_ds_queue *queue)
178 {
179    return 0;
180 }
181 
intel_ds_end_submit(struct intel_ds_queue * queue,uint64_t start_ts)182 static inline void intel_ds_end_submit(struct intel_ds_queue *queue,
183                                        uint64_t start_ts)
184 {
185 }
186 
187 #endif /* HAVE_PERFETTO */
188 
189 #ifdef __cplusplus
190 }
191 #endif
192 
193 #endif /* INTEL_DRIVER_DS_H */
194