1 /*
2 * Copyright © 2022 Friedrich Vock
3 *
4 * Exporter based on Radeon Memory Visualizer code which is
5 *
6 * Copyright (c) 2017-2022 Advanced Micro Devices, Inc.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
25 * IN THE SOFTWARE.
26 */
27
28 #include "vk_rmv_common.h"
29 #include "vk_rmv_tokens.h"
30
31 #include "util/format/u_format.h"
32 #include "util/u_process.h"
33 #include "vulkan/util/vk_format.h"
34
35 static int
vk_rmv_token_compare(const void * first,const void * second)36 vk_rmv_token_compare(const void *first, const void *second)
37 {
38 const struct vk_rmv_token *first_token = (struct vk_rmv_token *)first;
39 const struct vk_rmv_token *second_token = (struct vk_rmv_token *)second;
40 if (first_token->timestamp < second_token->timestamp)
41 return -1;
42 else if (first_token->timestamp > second_token->timestamp)
43 return 1;
44 return 0;
45 }
46
47 enum rmt_format {
48 RMT_FORMAT_UNDEFINED,
49 RMT_FORMAT_R1_UNORM,
50 RMT_FORMAT_R1_USCALED,
51 RMT_FORMAT_R4G4_UNORM,
52 RMT_FORMAT_R4G4_USCALED,
53 RMT_FORMAT_L4A4_UNORM,
54 RMT_FORMAT_R4G4B4A4_UNORM,
55 RMT_FORMAT_R4G4B4A4_USCALED,
56 RMT_FORMAT_R5G6B5_UNORM,
57 RMT_FORMAT_R5G6B5_USCALED,
58 RMT_FORMAT_R5G5B5A1_UNORM,
59 RMT_FORMAT_R5G5B5A1_USCALED,
60 RMT_FORMAT_R1G5B5A5_UNORM,
61 RMT_FORMAT_R1G5B5A5_USCALED,
62 RMT_FORMAT_R8_XNORM,
63 RMT_FORMAT_R8_SNORM,
64 RMT_FORMAT_R8_USCALED,
65 RMT_FORMAT_R8_SSCALED,
66 RMT_FORMAT_R8_UINT,
67 RMT_FORMAT_R8_SINT,
68 RMT_FORMAT_R8_SRGB,
69 RMT_FORMAT_A8_UNORM,
70 RMT_FORMAT_L8_UNORM,
71 RMT_FORMAT_P8_UINT,
72 RMT_FORMAT_R8G8_UNORM,
73 RMT_FORMAT_R8G8_SNORM,
74 RMT_FORMAT_R8G8_USCALED,
75 RMT_FORMAT_R8G8_SSCALED,
76 RMT_FORMAT_R8G8_UINT,
77 RMT_FORMAT_R8G8_SINT,
78 RMT_FORMAT_R8G8_SRGB,
79 RMT_FORMAT_L8A8_UNORM,
80 RMT_FORMAT_R8G8B8A8_UNORM,
81 RMT_FORMAT_R8G8B8A8_SNORM,
82 RMT_FORMAT_R8G8B8A8_USCALED,
83 RMT_FORMAT_R8G8B8A8_SSCALED,
84 RMT_FORMAT_R8G8B8A8_UINT,
85 RMT_FORMAT_R8G8B8A8_SINT,
86 RMT_FORMAT_R8G8B8A8_SRGB,
87 RMT_FORMAT_U8V8_SNORM_L8W8_UNORM,
88 RMT_FORMAT_R10G11B11_FLOAT,
89 RMT_FORMAT_R11G11B10_FLOAT,
90 RMT_FORMAT_R10G10B10A2_UNORM,
91 RMT_FORMAT_R10G10B10A2_SNORM,
92 RMT_FORMAT_R10G10B10A2_USCALED,
93 RMT_FORMAT_R10G10B10A2_SSCALED,
94 RMT_FORMAT_R10G10B10A2_UINT,
95 RMT_FORMAT_R10G10B10A2_SINT,
96 RMT_FORMAT_R10G10B10A2_BIAS_UNORM,
97 RMT_FORMAT_U10V10W10_SNORMA2_UNORM,
98 RMT_FORMAT_R16_UNORM,
99 RMT_FORMAT_R16_SNORM,
100 RMT_FORMAT_R16_USCALED,
101 RMT_FORMAT_R16_SSCALED,
102 RMT_FORMAT_R16_UINT,
103 RMT_FORMAT_R16_SINT,
104 RMT_FORMAT_R16_FLOAT,
105 RMT_FORMAT_L16_UNORM,
106 RMT_FORMAT_R16G16_UNORM,
107 RMT_FORMAT_R16G16_SNORM,
108 RMT_FORMAT_R16G16_USCALED,
109 RMT_FORMAT_R16G16_SSCALED,
110 RMT_FORMAT_R16G16_UINT,
111 RMT_FORMAT_R16G16_SINT,
112 RMT_FORMAT_R16G16_FLOAT,
113 RMT_FORMAT_R16G16B16A16_UNORM,
114 RMT_FORMAT_R16G16B16A16_SNORM,
115 RMT_FORMAT_R16G16B16A16_USCALED,
116 RMT_FORMAT_R16G16B16A16_SSCALED,
117 RMT_FORMAT_R16G16B16A16_UINT,
118 RMT_FORMAT_R16G16B16A16_SINT,
119 RMT_FORMAT_R16G16B16A16_FLOAT,
120 RMT_FORMAT_R32_UINT,
121 RMT_FORMAT_R32_SINT,
122 RMT_FORMAT_R32_FLOAT,
123 RMT_FORMAT_R32G32_UINT,
124 RMT_FORMAT_R32G32_SINT,
125 RMT_FORMAT_R32G32_FLOAT,
126 RMT_FORMAT_R32G32B32_UINT,
127 RMT_FORMAT_R32G32B32_SINT,
128 RMT_FORMAT_R32G32B32_FLOAT,
129 RMT_FORMAT_R32G32B32A32_UINT,
130 RMT_FORMAT_R32G32B32A32_SINT,
131 RMT_FORMAT_R32G32B32A32_FLOAT,
132 RMT_FORMAT_D16_UNORM_S8_UINT,
133 RMT_FORMAT_D32_UNORM_S8_UINT,
134 RMT_FORMAT_R9G9B9E5_FLOAT,
135 RMT_FORMAT_BC1_UNORM,
136 RMT_FORMAT_BC1_SRGB,
137 RMT_FORMAT_BC2_UNORM,
138 RMT_FORMAT_BC2_SRGB,
139 RMT_FORMAT_BC3_UNORM,
140 RMT_FORMAT_BC3_SRGB,
141 RMT_FORMAT_BC4_UNORM,
142 RMT_FORMAT_BC4_SRGB,
143 RMT_FORMAT_BC5_UNORM,
144 RMT_FORMAT_BC5_SRGB,
145 RMT_FORMAT_BC6_UNORM,
146 RMT_FORMAT_BC6_SRGB,
147 RMT_FORMAT_BC7_UNORM,
148 RMT_FORMAT_BC7_SRGB,
149 RMT_FORMAT_ETC2_R8G8B8_UNORM,
150 RMT_FORMAT_ETC2_R8G8B8_SRGB,
151 RMT_FORMAT_ETC2_R8G8B8A1_UNORM,
152 RMT_FORMAT_ETC2_R8G8B8A1_SRGB,
153 RMT_FORMAT_ETC2_R8G8B8A8_UNORM,
154 RMT_FORMAT_ETC2_R8G8B8A8_SRGB,
155 RMT_FORMAT_ETC2_R11_UNORM,
156 RMT_FORMAT_ETC2_R11_SNORM,
157 RMT_FORMAT_ETC2_R11G11_UNORM,
158 RMT_FORMAT_ETC2_R11G11_SNORM,
159 RMT_FORMAT_ASTCLD_R4X4_UNORM,
160 RMT_FORMAT_ASTCLD_R4X4_SRGB,
161 RMT_FORMAT_ASTCLD_R5X4_UNORM,
162 RMT_FORMAT_ASTCLD_R5X4_SRGB,
163 RMT_FORMAT_ASTCLD_R5X5_UNORM,
164 RMT_FORMAT_ASTCLD_R5X5_SRGB,
165 RMT_FORMAT_ASTCLD_R6X5_UNORM,
166 RMT_FORMAT_ASTCLD_R6X5_SRGB,
167 RMT_FORMAT_ASTCLD_R6X6_UNORM,
168 RMT_FORMAT_ASTCLD_R6X6_SRGB,
169 RMT_FORMAT_ASTCLD_R8X5_UNORM,
170 RMT_FORMAT_ASTCLD_R8X5_SRGB,
171 RMT_FORMAT_ASTCLD_R8X6_UNORM,
172 RMT_FORMAT_ASTCLD_R8X6_SRGB,
173 RMT_FORMAT_ASTCLD_R8X8_UNORM,
174 RMT_FORMAT_ASTCLD_R8X8_SRGB,
175 RMT_FORMAT_ASTCLD_R10X5_UNORM,
176 RMT_FORMAT_ASTCLD_R10X5_SRGB,
177 RMT_FORMAT_ASTCLD_R10X6_UNORM,
178 RMT_FORMAT_ASTCLD_R10X6_SRGB,
179 RMT_FORMAT_ASTCLD_R10X8_UNORM,
180 RMT_FORMAT_ASTCLD_R10X10_UNORM,
181 RMT_FORMAT_ASTCLD_R12X10_UNORM,
182 RMT_FORMAT_ASTCLD_R12X10_SRGB,
183 RMT_FORMAT_ASTCLD_R12X12_UNORM,
184 RMT_FORMAT_ASTCLD_R12X12_SRGB,
185 RMT_FORMAT_ASTCHD_R4x4_FLOAT,
186 RMT_FORMAT_ASTCHD_R5x4_FLOAT,
187 RMT_FORMAT_ASTCHD_R5x5_FLOAT,
188 RMT_FORMAT_ASTCHD_R6x5_FLOAT,
189 RMT_FORMAT_ASTCHD_R6x6_FLOAT,
190 RMT_FORMAT_ASTCHD_R8x5_FLOAT,
191 RMT_FORMAT_ASTCHD_R8x6_FLOAT,
192 RMT_FORMAT_ASTCHD_R8x8_FLOAT,
193 RMT_FORMAT_ASTCHD_R10x5_FLOAT,
194 RMT_FORMAT_ASTCHD_R10x6_FLOAT,
195 RMT_FORMAT_ASTCHD_R10x8_FLOAT,
196 RMT_FORMAT_ASTCHD_R10x10_FLOAT,
197 RMT_FORMAT_ASTCHD_R12x10_FLOAT,
198 RMT_FORMAT_ASTCHD_R12x12_FLOAT,
199 RMT_FORMAT_R8G8B8G8_UNORM,
200 RMT_FORMAT_R8G8B8G8_USCALED,
201 RMT_FORMAT_G8R8G8B8_UNORM,
202 RMT_FORMAT_G8R8G8B8_USCALED,
203 RMT_FORMAT_AYUV,
204 RMT_FORMAT_UYVY,
205 RMT_FORMAT_VYUY,
206 RMT_FORMAT_YUY2,
207 RMT_FORMAT_YVY2,
208 RMT_FORMAT_YV12,
209 RMT_FORMAT_NV11,
210 RMT_FORMAT_NV12,
211 RMT_FORMAT_NV21,
212 RMT_FORMAT_P016,
213 RMT_FORMAT_P010,
214 };
215
216 enum rmt_swizzle {
217 RMT_SWIZZLE_ZERO,
218 RMT_SWIZZLE_ONE,
219 RMT_SWIZZLE_R,
220 RMT_SWIZZLE_G,
221 RMT_SWIZZLE_B,
222 RMT_SWIZZLE_A,
223 };
224
225 static inline enum rmt_format
vk_to_rmt_format(VkFormat format)226 vk_to_rmt_format(VkFormat format)
227 {
228 switch (format) {
229 case VK_FORMAT_R8_UNORM:
230 return RMT_FORMAT_A8_UNORM;
231 case VK_FORMAT_R8_SNORM:
232 return RMT_FORMAT_R8_SNORM;
233 case VK_FORMAT_R8_USCALED:
234 return RMT_FORMAT_R8_USCALED;
235 case VK_FORMAT_R8_SSCALED:
236 return RMT_FORMAT_R8_SSCALED;
237 case VK_FORMAT_R8_UINT:
238 return RMT_FORMAT_R8_UINT;
239 case VK_FORMAT_R8_SINT:
240 return RMT_FORMAT_R8_SINT;
241 case VK_FORMAT_R8_SRGB:
242 return RMT_FORMAT_R8_SRGB;
243 case VK_FORMAT_R8G8_UNORM:
244 return RMT_FORMAT_R8G8_UNORM;
245 case VK_FORMAT_R8G8_SNORM:
246 return RMT_FORMAT_R8G8_SNORM;
247 case VK_FORMAT_R8G8_USCALED:
248 return RMT_FORMAT_R8G8_USCALED;
249 case VK_FORMAT_R8G8_SSCALED:
250 return RMT_FORMAT_R8G8_SSCALED;
251 case VK_FORMAT_R8G8_UINT:
252 return RMT_FORMAT_R8G8_UINT;
253 case VK_FORMAT_R8G8_SINT:
254 return RMT_FORMAT_R8G8_SINT;
255 case VK_FORMAT_R8G8_SRGB:
256 return RMT_FORMAT_R8G8_SRGB;
257 case VK_FORMAT_R8G8B8A8_UNORM:
258 case VK_FORMAT_B8G8R8A8_UNORM:
259 case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
260 return RMT_FORMAT_R8G8B8A8_UNORM;
261 case VK_FORMAT_R8G8B8A8_SNORM:
262 case VK_FORMAT_B8G8R8A8_SNORM:
263 case VK_FORMAT_A8B8G8R8_SNORM_PACK32:
264 return RMT_FORMAT_R8G8B8A8_SNORM;
265 case VK_FORMAT_R8G8B8A8_USCALED:
266 case VK_FORMAT_B8G8R8A8_USCALED:
267 case VK_FORMAT_A8B8G8R8_USCALED_PACK32:
268 return RMT_FORMAT_R8G8B8A8_USCALED;
269 case VK_FORMAT_R8G8B8A8_SSCALED:
270 case VK_FORMAT_B8G8R8A8_SSCALED:
271 case VK_FORMAT_A8B8G8R8_SSCALED_PACK32:
272 return RMT_FORMAT_R8G8B8A8_SSCALED;
273 case VK_FORMAT_R8G8B8A8_UINT:
274 case VK_FORMAT_B8G8R8A8_UINT:
275 case VK_FORMAT_A8B8G8R8_UINT_PACK32:
276 return RMT_FORMAT_R8G8B8A8_UINT;
277 case VK_FORMAT_R8G8B8A8_SINT:
278 case VK_FORMAT_B8G8R8A8_SINT:
279 case VK_FORMAT_A8B8G8R8_SINT_PACK32:
280 return RMT_FORMAT_R8G8B8A8_SINT;
281 case VK_FORMAT_R8G8B8A8_SRGB:
282 case VK_FORMAT_B8G8R8A8_SRGB:
283 case VK_FORMAT_A8B8G8R8_SRGB_PACK32:
284 return RMT_FORMAT_R8G8B8A8_SRGB;
285 case VK_FORMAT_R16_UNORM:
286 return RMT_FORMAT_R16_UNORM;
287 case VK_FORMAT_R16_SNORM:
288 return RMT_FORMAT_R16_SNORM;
289 case VK_FORMAT_R16_USCALED:
290 return RMT_FORMAT_R16_USCALED;
291 case VK_FORMAT_R16_SSCALED:
292 return RMT_FORMAT_R16_SSCALED;
293 case VK_FORMAT_R16_UINT:
294 return RMT_FORMAT_R16_UINT;
295 case VK_FORMAT_R16_SINT:
296 return RMT_FORMAT_R16_SINT;
297 case VK_FORMAT_R16G16_UNORM:
298 return RMT_FORMAT_R16G16_UNORM;
299 case VK_FORMAT_R16G16_SNORM:
300 return RMT_FORMAT_R16G16_SNORM;
301 case VK_FORMAT_R16G16_USCALED:
302 return RMT_FORMAT_R16G16_USCALED;
303 case VK_FORMAT_R16G16_SSCALED:
304 return RMT_FORMAT_R16G16_SSCALED;
305 case VK_FORMAT_R16G16_UINT:
306 return RMT_FORMAT_R16G16_UINT;
307 case VK_FORMAT_R16G16_SINT:
308 return RMT_FORMAT_R16G16_SINT;
309 case VK_FORMAT_R16G16_SFLOAT:
310 return RMT_FORMAT_R16G16_FLOAT;
311 case VK_FORMAT_R16G16B16A16_UNORM:
312 return RMT_FORMAT_R16G16B16A16_UNORM;
313 case VK_FORMAT_R16G16B16A16_SNORM:
314 return RMT_FORMAT_R16G16B16A16_SNORM;
315 case VK_FORMAT_R16G16B16A16_USCALED:
316 return RMT_FORMAT_R16G16B16A16_USCALED;
317 case VK_FORMAT_R16G16B16A16_SSCALED:
318 return RMT_FORMAT_R16G16B16A16_SSCALED;
319 case VK_FORMAT_R16G16B16A16_UINT:
320 return RMT_FORMAT_R16G16B16A16_UINT;
321 case VK_FORMAT_R16G16B16A16_SINT:
322 return RMT_FORMAT_R16G16B16A16_SINT;
323 case VK_FORMAT_R16G16B16A16_SFLOAT:
324 return RMT_FORMAT_R16G16B16A16_FLOAT;
325 case VK_FORMAT_R32_UINT:
326 return RMT_FORMAT_R32_UINT;
327 case VK_FORMAT_R32_SINT:
328 return RMT_FORMAT_R32_SINT;
329 case VK_FORMAT_R32_SFLOAT:
330 return RMT_FORMAT_R32_FLOAT;
331 case VK_FORMAT_R32G32_UINT:
332 return RMT_FORMAT_R32G32_UINT;
333 case VK_FORMAT_R32G32_SINT:
334 return RMT_FORMAT_R32G32_SINT;
335 case VK_FORMAT_R32G32_SFLOAT:
336 return RMT_FORMAT_R32G32_FLOAT;
337 case VK_FORMAT_R32G32B32_UINT:
338 return RMT_FORMAT_R32G32B32_UINT;
339 case VK_FORMAT_R32G32B32_SINT:
340 return RMT_FORMAT_R32G32B32_SINT;
341 case VK_FORMAT_R32G32B32_SFLOAT:
342 return RMT_FORMAT_R32G32B32_FLOAT;
343 case VK_FORMAT_R32G32B32A32_UINT:
344 return RMT_FORMAT_R32G32B32A32_UINT;
345 case VK_FORMAT_R32G32B32A32_SINT:
346 return RMT_FORMAT_R32G32B32A32_SINT;
347 case VK_FORMAT_R32G32B32A32_SFLOAT:
348 return RMT_FORMAT_R32G32B32A32_FLOAT;
349 case VK_FORMAT_D16_UNORM_S8_UINT:
350 return RMT_FORMAT_D16_UNORM_S8_UINT;
351 case VK_FORMAT_D32_SFLOAT_S8_UINT:
352 return RMT_FORMAT_D32_UNORM_S8_UINT;
353 case VK_FORMAT_BC1_RGBA_UNORM_BLOCK:
354 return RMT_FORMAT_BC1_UNORM;
355 case VK_FORMAT_BC1_RGBA_SRGB_BLOCK:
356 return RMT_FORMAT_BC1_SRGB;
357 case VK_FORMAT_BC2_UNORM_BLOCK:
358 return RMT_FORMAT_BC2_UNORM;
359 case VK_FORMAT_BC2_SRGB_BLOCK:
360 return RMT_FORMAT_BC2_SRGB;
361 case VK_FORMAT_BC3_UNORM_BLOCK:
362 return RMT_FORMAT_BC3_UNORM;
363 case VK_FORMAT_BC3_SRGB_BLOCK:
364 return RMT_FORMAT_BC3_SRGB;
365 case VK_FORMAT_BC4_UNORM_BLOCK:
366 return RMT_FORMAT_BC4_UNORM;
367 case VK_FORMAT_BC5_UNORM_BLOCK:
368 return RMT_FORMAT_BC5_UNORM;
369 case VK_FORMAT_BC7_UNORM_BLOCK:
370 return RMT_FORMAT_BC7_UNORM;
371 case VK_FORMAT_BC7_SRGB_BLOCK:
372 return RMT_FORMAT_BC7_SRGB;
373 case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK:
374 return RMT_FORMAT_ETC2_R8G8B8_UNORM;
375 case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK:
376 return RMT_FORMAT_ETC2_R8G8B8_SRGB;
377 case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK:
378 return RMT_FORMAT_ETC2_R8G8B8A1_UNORM;
379 case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK:
380 return RMT_FORMAT_ETC2_R8G8B8A1_SRGB;
381 case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK:
382 return RMT_FORMAT_ETC2_R8G8B8A8_UNORM;
383 case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK:
384 return RMT_FORMAT_ETC2_R8G8B8A8_SRGB;
385 case VK_FORMAT_ASTC_4x4_UNORM_BLOCK:
386 return RMT_FORMAT_ASTCLD_R4X4_UNORM;
387 case VK_FORMAT_ASTC_4x4_SRGB_BLOCK:
388 return RMT_FORMAT_ASTCLD_R4X4_SRGB;
389 case VK_FORMAT_ASTC_5x4_UNORM_BLOCK:
390 return RMT_FORMAT_ASTCLD_R5X4_UNORM;
391 case VK_FORMAT_ASTC_5x4_SRGB_BLOCK:
392 return RMT_FORMAT_ASTCLD_R5X4_SRGB;
393 case VK_FORMAT_ASTC_5x5_UNORM_BLOCK:
394 return RMT_FORMAT_ASTCLD_R5X5_UNORM;
395 case VK_FORMAT_ASTC_5x5_SRGB_BLOCK:
396 return RMT_FORMAT_ASTCLD_R5X5_SRGB;
397 case VK_FORMAT_ASTC_6x5_UNORM_BLOCK:
398 return RMT_FORMAT_ASTCLD_R6X5_UNORM;
399 case VK_FORMAT_ASTC_6x5_SRGB_BLOCK:
400 return RMT_FORMAT_ASTCLD_R6X5_SRGB;
401 case VK_FORMAT_ASTC_6x6_UNORM_BLOCK:
402 return RMT_FORMAT_ASTCLD_R6X6_UNORM;
403 case VK_FORMAT_ASTC_6x6_SRGB_BLOCK:
404 return RMT_FORMAT_ASTCLD_R6X6_SRGB;
405 case VK_FORMAT_ASTC_8x5_UNORM_BLOCK:
406 return RMT_FORMAT_ASTCLD_R8X5_UNORM;
407 case VK_FORMAT_ASTC_8x5_SRGB_BLOCK:
408 return RMT_FORMAT_ASTCLD_R8X5_SRGB;
409 case VK_FORMAT_ASTC_8x6_UNORM_BLOCK:
410 return RMT_FORMAT_ASTCLD_R8X6_UNORM;
411 case VK_FORMAT_ASTC_8x6_SRGB_BLOCK:
412 return RMT_FORMAT_ASTCLD_R8X6_SRGB;
413 case VK_FORMAT_ASTC_8x8_UNORM_BLOCK:
414 return RMT_FORMAT_ASTCLD_R8X8_UNORM;
415 case VK_FORMAT_ASTC_8x8_SRGB_BLOCK:
416 return RMT_FORMAT_ASTCLD_R8X8_SRGB;
417 case VK_FORMAT_ASTC_10x5_UNORM_BLOCK:
418 return RMT_FORMAT_ASTCLD_R10X5_UNORM;
419 case VK_FORMAT_ASTC_10x5_SRGB_BLOCK:
420 return RMT_FORMAT_ASTCLD_R10X5_SRGB;
421 case VK_FORMAT_ASTC_10x6_UNORM_BLOCK:
422 return RMT_FORMAT_ASTCLD_R10X6_UNORM;
423 case VK_FORMAT_ASTC_10x6_SRGB_BLOCK:
424 return RMT_FORMAT_ASTCLD_R10X6_SRGB;
425 case VK_FORMAT_ASTC_10x8_UNORM_BLOCK:
426 return RMT_FORMAT_ASTCLD_R10X8_UNORM;
427 case VK_FORMAT_ASTC_10x10_UNORM_BLOCK:
428 return RMT_FORMAT_ASTCLD_R10X10_UNORM;
429 case VK_FORMAT_ASTC_12x10_UNORM_BLOCK:
430 return RMT_FORMAT_ASTCLD_R12X10_UNORM;
431 case VK_FORMAT_ASTC_12x10_SRGB_BLOCK:
432 return RMT_FORMAT_ASTCLD_R12X10_SRGB;
433 case VK_FORMAT_ASTC_12x12_UNORM_BLOCK:
434 return RMT_FORMAT_ASTCLD_R12X12_UNORM;
435 case VK_FORMAT_ASTC_12x12_SRGB_BLOCK:
436 return RMT_FORMAT_ASTCLD_R12X12_SRGB;
437 case VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK:
438 return RMT_FORMAT_ASTCHD_R4x4_FLOAT;
439 case VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK:
440 return RMT_FORMAT_ASTCHD_R5x4_FLOAT;
441 case VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK:
442 return RMT_FORMAT_ASTCHD_R5x5_FLOAT;
443 case VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK:
444 return RMT_FORMAT_ASTCHD_R6x5_FLOAT;
445 case VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK:
446 return RMT_FORMAT_ASTCHD_R6x6_FLOAT;
447 case VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK:
448 return RMT_FORMAT_ASTCHD_R8x5_FLOAT;
449 case VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK:
450 return RMT_FORMAT_ASTCHD_R8x6_FLOAT;
451 case VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK:
452 return RMT_FORMAT_ASTCHD_R8x8_FLOAT;
453 case VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK:
454 return RMT_FORMAT_ASTCHD_R10x5_FLOAT;
455 case VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK:
456 return RMT_FORMAT_ASTCHD_R10x6_FLOAT;
457 case VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK:
458 return RMT_FORMAT_ASTCHD_R10x8_FLOAT;
459 case VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK:
460 return RMT_FORMAT_ASTCHD_R10x10_FLOAT;
461 case VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK:
462 return RMT_FORMAT_ASTCHD_R12x10_FLOAT;
463 case VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK:
464 return RMT_FORMAT_ASTCHD_R12x12_FLOAT;
465 default:
466 return RMT_FORMAT_UNDEFINED;
467 }
468 }
469
470 static void
rmt_format_to_swizzle(VkFormat format,enum rmt_swizzle * swizzles)471 rmt_format_to_swizzle(VkFormat format, enum rmt_swizzle *swizzles)
472 {
473 const struct util_format_description *description =
474 util_format_description(vk_format_to_pipe_format(format));
475 for (unsigned i = 0; i < 4; ++i) {
476 switch (description->swizzle[i]) {
477 case PIPE_SWIZZLE_X:
478 swizzles[i] = RMT_SWIZZLE_R;
479 break;
480 case PIPE_SWIZZLE_Y:
481 swizzles[i] = RMT_SWIZZLE_G;
482 break;
483 case PIPE_SWIZZLE_Z:
484 swizzles[i] = RMT_SWIZZLE_B;
485 break;
486 case PIPE_SWIZZLE_W:
487 swizzles[i] = RMT_SWIZZLE_A;
488 break;
489 case PIPE_SWIZZLE_0:
490 case PIPE_SWIZZLE_NONE:
491 swizzles[i] = RMT_SWIZZLE_ZERO;
492 break;
493 case PIPE_SWIZZLE_1:
494 swizzles[i] = RMT_SWIZZLE_ONE;
495 break;
496 }
497 }
498 }
499
500 #define RMT_FILE_MAGIC_NUMBER 0x494e494d
501 #define RMT_FILE_VERSION_MAJOR 1
502 #define RMT_FILE_VERSION_MINOR 0
503 #define RMT_FILE_ADAPTER_NAME_MAX_SIZE 128
504
505 enum rmt_heap_type {
506 RMT_HEAP_TYPE_LOCAL, /* DEVICE_LOCAL | HOST_VISIBLE */
507 RMT_HEAP_TYPE_INVISIBLE, /* DEVICE_LOCAL */
508 RMT_HEAP_TYPE_SYSTEM, /* HOST_VISIBLE | HOST_COHERENT */
509 RMT_HEAP_TYPE_NONE,
510 RMT_HEAP_TYPE_UNKNOWN = -1,
511 };
512
513 enum rmt_file_chunk_type {
514 RMT_FILE_CHUNK_TYPE_ASIC_INFO, /* Seems to be unused in RMV */
515 RMT_FILE_CHUNK_TYPE_API_INFO,
516 RMT_FILE_CHUNK_TYPE_SYSTEM_INFO,
517 RMT_FILE_CHUNK_TYPE_RMT_DATA,
518 RMT_FILE_CHUNK_TYPE_SEGMENT_INFO,
519 RMT_FILE_CHUNK_TYPE_PROCESS_START,
520 RMT_FILE_CHUNK_TYPE_SNAPSHOT_INFO,
521 RMT_FILE_CHUNK_TYPE_ADAPTER_INFO,
522 };
523
524 /**
525 * RMT API info.
526 */
527 enum rmt_api_type {
528 RMT_API_TYPE_DIRECTX_12,
529 RMT_API_TYPE_VULKAN,
530 RMT_API_TYPE_GENERIC,
531 RMT_API_TYPE_OPENCL,
532 };
533
534 struct rmt_file_chunk_id {
535 enum rmt_file_chunk_type type : 8;
536 int32_t index : 8;
537 int32_t reserved : 16;
538 };
539
540 struct rmt_file_chunk_header {
541 struct rmt_file_chunk_id chunk_id;
542 uint16_t minor_version;
543 uint16_t major_version;
544 int32_t size_in_bytes;
545 int32_t padding;
546 };
547
548 struct rmt_file_header_flags {
549 union {
550 struct {
551 int32_t reserved : 32;
552 };
553
554 uint32_t value;
555 };
556 };
557
558 struct rmt_file_header {
559 uint32_t magic_number;
560 uint32_t version_major;
561 uint32_t version_minor;
562 struct rmt_file_header_flags flags;
563 int32_t chunk_offset;
564 int32_t second;
565 int32_t minute;
566 int32_t hour;
567 int32_t day_in_month;
568 int32_t month;
569 int32_t year;
570 int32_t day_in_week;
571 int32_t day_in_year;
572 int32_t is_daylight_savings;
573 };
574
575 static_assert(sizeof(struct rmt_file_header) == 56, "rmt_file_header doesn't match RMV spec");
576
577 static void
rmt_fill_header(struct rmt_file_header * header)578 rmt_fill_header(struct rmt_file_header *header)
579 {
580 struct tm *timep, result;
581 time_t raw_time;
582
583 header->magic_number = RMT_FILE_MAGIC_NUMBER;
584 header->version_major = RMT_FILE_VERSION_MAJOR;
585 header->version_minor = RMT_FILE_VERSION_MINOR;
586 header->flags.value = 0;
587 header->chunk_offset = sizeof(*header);
588
589 time(&raw_time);
590 timep = os_localtime(&raw_time, &result);
591
592 header->second = timep->tm_sec;
593 header->minute = timep->tm_min;
594 header->hour = timep->tm_hour;
595 header->day_in_month = timep->tm_mday;
596 header->month = timep->tm_mon;
597 header->year = timep->tm_year;
598 header->day_in_week = timep->tm_wday;
599 header->day_in_year = timep->tm_yday;
600 header->is_daylight_savings = timep->tm_isdst;
601 }
602
603 /*
604 * RMT data.
605 */
606 struct rmt_file_chunk_rmt_data {
607 struct rmt_file_chunk_header header;
608 uint64_t process_id;
609 uint64_t thread_id;
610 };
611
612 static_assert(sizeof(struct rmt_file_chunk_rmt_data) == 32,
613 "rmt_file_chunk_rmt_data doesn't match RMV spec");
614
615 static void
rmt_fill_chunk_rmt_data(size_t token_stream_size,struct rmt_file_chunk_rmt_data * chunk)616 rmt_fill_chunk_rmt_data(size_t token_stream_size, struct rmt_file_chunk_rmt_data *chunk)
617 {
618 chunk->header.chunk_id.type = RMT_FILE_CHUNK_TYPE_RMT_DATA;
619 chunk->header.chunk_id.index = 0;
620 chunk->header.major_version = 1;
621 chunk->header.minor_version = 6;
622 chunk->header.size_in_bytes = sizeof(*chunk) + token_stream_size;
623
624 chunk->process_id = (uint64_t)getpid();
625 }
626
627 /*
628 * RMT System info. Equivalent to SQTT CPU info.
629 */
630 struct rmt_file_chunk_system_info {
631 struct rmt_file_chunk_header header;
632 uint32_t vendor_id[4];
633 uint32_t processor_brand[12];
634 uint32_t reserved[2];
635 uint64_t cpu_timestamp_freq;
636 uint32_t clock_speed;
637 uint32_t num_logical_cores;
638 uint32_t num_physical_cores;
639 uint32_t system_ram_size;
640 };
641
642 static_assert(sizeof(struct rmt_file_chunk_system_info) == 112,
643 "rmt_file_chunk_system_info doesn't match RMV spec");
644
645 /* same as vk_sqtt_fill_cpu_info. TODO: Share with ac_rgp.c */
646 static void
rmt_fill_chunk_system_info(struct rmt_file_chunk_system_info * chunk)647 rmt_fill_chunk_system_info(struct rmt_file_chunk_system_info *chunk)
648 {
649 uint32_t cpu_clock_speed_total = 0;
650 uint64_t system_ram_size = 0;
651 char line[1024];
652 FILE *f;
653
654 chunk->header.chunk_id.type = RMT_FILE_CHUNK_TYPE_SYSTEM_INFO;
655 chunk->header.chunk_id.index = 0;
656 chunk->header.major_version = 0;
657 chunk->header.minor_version = 0;
658 chunk->header.size_in_bytes = sizeof(*chunk);
659
660 /* For some reason, RMV allocates scratch data based on the
661 * maximum timestamp in clock ticks. A tick of 1ns produces extremely
662 * large timestamps, which causes RMV to run out of memory. Therefore,
663 * all timestamps are translated as if the clock ran at 1 MHz. */
664 chunk->cpu_timestamp_freq = 1 * 1000000;
665
666 strncpy((char *)chunk->vendor_id, "Unknown", sizeof(chunk->vendor_id));
667 strncpy((char *)chunk->processor_brand, "Unknown", sizeof(chunk->processor_brand));
668 chunk->clock_speed = 0;
669 chunk->num_logical_cores = 0;
670 chunk->num_physical_cores = 0;
671 chunk->system_ram_size = 0;
672 if (os_get_total_physical_memory(&system_ram_size))
673 chunk->system_ram_size = system_ram_size / (1024 * 1024);
674
675 /* Parse cpuinfo to get more detailled information. */
676 f = fopen("/proc/cpuinfo", "r");
677 if (!f)
678 return;
679
680 while (fgets(line, sizeof(line), f)) {
681 char *str;
682
683 /* Parse vendor name. */
684 str = strstr(line, "vendor_id");
685 if (str) {
686 char *ptr = (char *)chunk->vendor_id;
687 char *v = strtok(str, ":");
688 v = strtok(NULL, ":");
689 strncpy(ptr, v + 1, sizeof(chunk->vendor_id) - 1);
690 ptr[sizeof(chunk->vendor_id) - 1] = '\0';
691 }
692
693 /* Parse processor name. */
694 str = strstr(line, "model name");
695 if (str) {
696 char *ptr = (char *)chunk->processor_brand;
697 char *v = strtok(str, ":");
698 v = strtok(NULL, ":");
699 strncpy(ptr, v + 1, sizeof(chunk->processor_brand) - 1);
700 ptr[sizeof(chunk->processor_brand) - 1] = '\0';
701 }
702
703 /* Parse the current CPU clock speed for each cores. */
704 str = strstr(line, "cpu MHz");
705 if (str) {
706 uint32_t v = 0;
707 if (sscanf(str, "cpu MHz : %d", &v) == 1)
708 cpu_clock_speed_total += v;
709 }
710
711 /* Parse the number of logical cores. */
712 str = strstr(line, "siblings");
713 if (str) {
714 uint32_t v = 0;
715 if (sscanf(str, "siblings : %d", &v) == 1)
716 chunk->num_logical_cores = v;
717 }
718
719 /* Parse the number of physical cores. */
720 str = strstr(line, "cpu cores");
721 if (str) {
722 uint32_t v = 0;
723 if (sscanf(str, "cpu cores : %d", &v) == 1)
724 chunk->num_physical_cores = v;
725 }
726 }
727
728 if (chunk->num_logical_cores)
729 chunk->clock_speed = cpu_clock_speed_total / chunk->num_logical_cores;
730
731 fclose(f);
732 }
733
734 /*
735 * RMT Segment info.
736 */
737 struct rmt_file_chunk_segment_info {
738 struct rmt_file_chunk_header header;
739 uint64_t base_address;
740 uint64_t size;
741 enum rmt_heap_type heap_type;
742 int32_t memory_index;
743 };
744
745 static_assert(sizeof(struct rmt_file_chunk_segment_info) == 40,
746 "rmt_file_chunk_segment_info doesn't match RMV spec");
747
748 static void
rmt_fill_chunk_segment_info(struct vk_memory_trace_data * data,struct vk_rmv_device_info * info,struct rmt_file_chunk_segment_info * chunk,int32_t index)749 rmt_fill_chunk_segment_info(struct vk_memory_trace_data *data, struct vk_rmv_device_info *info,
750 struct rmt_file_chunk_segment_info *chunk, int32_t index)
751 {
752 chunk->header.chunk_id.type = RMT_FILE_CHUNK_TYPE_SEGMENT_INFO;
753 chunk->header.chunk_id.index = index;
754 chunk->header.major_version = 0;
755 chunk->header.minor_version = 0;
756 chunk->header.size_in_bytes = sizeof(*chunk);
757
758 chunk->memory_index = index;
759 chunk->heap_type = (enum rmt_heap_type)index;
760 chunk->base_address = info->memory_infos[index].physical_base_address;
761 chunk->size = info->memory_infos[index].size;
762 }
763
764 /*
765 * RMT PCIe adapter info
766 */
767 struct rmt_file_chunk_adapter_info {
768 struct rmt_file_chunk_header header;
769 char name[RMT_FILE_ADAPTER_NAME_MAX_SIZE];
770 uint32_t pcie_family_id;
771 uint32_t pcie_revision_id;
772 uint32_t device_id;
773 uint32_t minimum_engine_clock;
774 uint32_t maximum_engine_clock;
775 uint32_t memory_type;
776 uint32_t memory_operations_per_clock;
777 uint32_t memory_bus_width;
778 uint32_t memory_bandwidth;
779 uint32_t minimum_memory_clock;
780 uint32_t maximum_memory_clock;
781 };
782
783 static_assert(sizeof(struct rmt_file_chunk_adapter_info) == 188,
784 "rmt_file_chunk_adapter_info doesn't match RMV spec");
785
786 static void
rmt_fill_chunk_adapter_info(struct vk_rmv_device_info * info,struct rmt_file_chunk_adapter_info * chunk)787 rmt_fill_chunk_adapter_info(struct vk_rmv_device_info *info,
788 struct rmt_file_chunk_adapter_info *chunk)
789 {
790 chunk->header.chunk_id.type = RMT_FILE_CHUNK_TYPE_ADAPTER_INFO;
791 chunk->header.chunk_id.index = 0;
792 chunk->header.major_version = 0;
793 chunk->header.minor_version = 0;
794 chunk->header.size_in_bytes = sizeof(*chunk);
795
796 memcpy(chunk->name, info->device_name, RMT_FILE_ADAPTER_NAME_MAX_SIZE);
797 chunk->pcie_family_id = info->pcie_family_id;
798 chunk->pcie_revision_id = info->pcie_revision_id;
799 chunk->device_id = info->pcie_device_id;
800 chunk->minimum_engine_clock = info->minimum_shader_clock;
801 chunk->maximum_engine_clock = info->maximum_shader_clock;
802 chunk->memory_type = info->vram_type;
803 chunk->memory_operations_per_clock = info->vram_operations_per_clock;
804
805 chunk->memory_bus_width = info->vram_bus_width;
806 chunk->minimum_memory_clock = info->minimum_memory_clock;
807 chunk->maximum_memory_clock = info->maximum_memory_clock;
808 /* Convert bandwidth from GB/s to MiB/s */
809 chunk->memory_bandwidth =
810 ((uint64_t)info->vram_bandwidth * 1000ULL * 1000ULL * 1000ULL) / (1024ULL * 1024ULL);
811 }
812
813 /*
814 * RMT snapshot info
815 */
816 struct rmt_file_chunk_snapshot_info {
817 struct rmt_file_chunk_header header;
818 uint64_t snapshot_time;
819 int32_t name_length;
820 int32_t padding;
821 /* The name follows after this struct */
822 /* After the name, a stream of tokens is written. */
823 };
824
825 static_assert(sizeof(struct rmt_file_chunk_snapshot_info) == 32,
826 "rmt_file_chunk_snapshot_info doesn't match RMV spec");
827
828 static void
rmt_fill_chunk_snapshot_info(uint64_t timestamp,int32_t name_length,struct rmt_file_chunk_snapshot_info * chunk)829 rmt_fill_chunk_snapshot_info(uint64_t timestamp, int32_t name_length,
830 struct rmt_file_chunk_snapshot_info *chunk)
831 {
832 chunk->header.chunk_id.type = RMT_FILE_CHUNK_TYPE_SNAPSHOT_INFO;
833 chunk->header.chunk_id.index = 0;
834 chunk->header.major_version = 1;
835 chunk->header.minor_version = 6;
836 chunk->header.size_in_bytes = sizeof(*chunk) + name_length;
837
838 chunk->snapshot_time = timestamp;
839 chunk->name_length = name_length;
840 }
841
842 /*
843 * RMT stream tokens
844 */
845
846 enum rmt_token_type {
847 RMT_TOKEN_TYPE_TIMESTAMP,
848 RMT_TOKEN_TYPE_RESERVED0,
849 RMT_TOKEN_TYPE_RESERVED1,
850 RMT_TOKEN_TYPE_PAGE_TABLE_UPDATE,
851 RMT_TOKEN_TYPE_USERDATA,
852 RMT_TOKEN_TYPE_MISC,
853 RMT_TOKEN_TYPE_RESOURCE_REFERENCE,
854 RMT_TOKEN_TYPE_RESOURCE_BIND,
855 RMT_TOKEN_TYPE_PROCESS_EVENT,
856 RMT_TOKEN_TYPE_PAGE_REFERENCE,
857 RMT_TOKEN_TYPE_CPU_MAP,
858 RMT_TOKEN_TYPE_VIRTUAL_FREE,
859 RMT_TOKEN_TYPE_VIRTUAL_ALLOCATE,
860 RMT_TOKEN_TYPE_RESOURCE_CREATE,
861 RMT_TOKEN_TYPE_TIME_DELTA,
862 RMT_TOKEN_TYPE_RESOURCE_DESTROY,
863 };
864
865 static enum rmt_token_type
token_type_to_rmt(enum vk_rmv_token_type type)866 token_type_to_rmt(enum vk_rmv_token_type type)
867 {
868 switch (type) {
869 case VK_RMV_TOKEN_TYPE_PAGE_TABLE_UPDATE:
870 return RMT_TOKEN_TYPE_PAGE_TABLE_UPDATE;
871 case VK_RMV_TOKEN_TYPE_USERDATA:
872 return RMT_TOKEN_TYPE_USERDATA;
873 case VK_RMV_TOKEN_TYPE_MISC:
874 return RMT_TOKEN_TYPE_MISC;
875 case VK_RMV_TOKEN_TYPE_RESOURCE_REFERENCE:
876 return RMT_TOKEN_TYPE_RESOURCE_REFERENCE;
877 case VK_RMV_TOKEN_TYPE_RESOURCE_BIND:
878 return RMT_TOKEN_TYPE_RESOURCE_BIND;
879 case VK_RMV_TOKEN_TYPE_CPU_MAP:
880 return RMT_TOKEN_TYPE_CPU_MAP;
881 case VK_RMV_TOKEN_TYPE_VIRTUAL_FREE:
882 return RMT_TOKEN_TYPE_VIRTUAL_FREE;
883 case VK_RMV_TOKEN_TYPE_VIRTUAL_ALLOCATE:
884 return RMT_TOKEN_TYPE_VIRTUAL_ALLOCATE;
885 case VK_RMV_TOKEN_TYPE_RESOURCE_CREATE:
886 return RMT_TOKEN_TYPE_RESOURCE_CREATE;
887 case VK_RMV_TOKEN_TYPE_RESOURCE_DESTROY:
888 return RMT_TOKEN_TYPE_RESOURCE_DESTROY;
889 default:
890 unreachable("invalid token type");
891 }
892 }
893
894 enum rmt_descriptor_type {
895 RMT_DESCRIPTOR_TYPE_CSV_SRV_UAV,
896 RMT_DESCRIPTOR_TYPE_SAMPLER,
897 RMT_DESCRIPTOR_TYPE_RTV,
898 RMT_DESCRIPTOR_TYPE_DSV,
899 RMT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
900 RMT_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
901 RMT_DESCRIPTOR_TYPE_STORAGE_IMAGE,
902 RMT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
903 RMT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
904 RMT_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
905 RMT_DESCRIPTOR_TYPE_STORAGE_BUFFER,
906 RMT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
907 RMT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
908 RMT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
909 RMT_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK,
910 RMT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE,
911 RMT_DESCRIPTOR_TYPE_INVALID = 0x7FFF,
912 };
913
914 static enum rmt_descriptor_type
vk_to_rmt_descriptor_type(VkDescriptorType type)915 vk_to_rmt_descriptor_type(VkDescriptorType type)
916 {
917 switch (type) {
918 case VK_DESCRIPTOR_TYPE_SAMPLER:
919 return RMT_DESCRIPTOR_TYPE_SAMPLER;
920 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
921 return RMT_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
922 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
923 return RMT_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
924 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
925 return RMT_DESCRIPTOR_TYPE_STORAGE_IMAGE;
926 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
927 return RMT_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
928 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
929 return RMT_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
930 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
931 return RMT_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
932 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
933 return RMT_DESCRIPTOR_TYPE_STORAGE_BUFFER;
934 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
935 return RMT_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
936 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
937 return RMT_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
938 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
939 return RMT_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
940 case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
941 return RMT_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK;
942 case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
943 return RMT_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE;
944 default:
945 /* This is reachable, error should be handled by caller */
946 return RMT_DESCRIPTOR_TYPE_INVALID;
947 }
948 };
949
950 static uint32_t
rmt_valid_pool_size_count(struct vk_rmv_descriptor_pool_description * description)951 rmt_valid_pool_size_count(struct vk_rmv_descriptor_pool_description *description)
952 {
953 uint32_t count = 0;
954 for (uint32_t i = 0; i < description->pool_size_count; ++i) {
955 enum rmt_descriptor_type rmt_type =
956 vk_to_rmt_descriptor_type(description->pool_sizes[i].type);
957 if (rmt_type == RMT_DESCRIPTOR_TYPE_INVALID)
958 /* Unknown descriptor type, skip */
959 continue;
960 ++count;
961 }
962 return count;
963 }
964
965 enum rmt_resource_owner_type {
966 RMT_RESOURCE_OWNER_TYPE_APPLICATION,
967 RMT_RESOURCE_OWNER_TYPE_PAL,
968 RMT_RESOURCE_OWNER_TYPE_CLIENT_DRIVER,
969 RMT_RESOURCE_OWNER_TYPE_KMD,
970 };
971
972 static void
rmt_file_write_bits(uint64_t * dst,uint64_t data,unsigned first_bit,unsigned last_bit)973 rmt_file_write_bits(uint64_t *dst, uint64_t data, unsigned first_bit, unsigned last_bit)
974 {
975 unsigned index = first_bit / 64;
976 unsigned shift = first_bit % 64;
977
978 /* Data crosses an uint64_t boundary, split */
979 if (index != last_bit / 64) {
980 unsigned first_part_size = 64 - shift;
981 rmt_file_write_bits(dst, data & ((1ULL << first_part_size) - 1ULL), first_bit,
982 index * 64 + 63);
983 rmt_file_write_bits(dst, data >> first_part_size, (index + 1) * 64, last_bit);
984 } else {
985 assert(data <= (1ULL << (uint64_t)(last_bit - first_bit + 1ULL)) - 1ULL);
986 dst[index] |= data << shift;
987 }
988 }
989
990 static void
rmt_file_write_token_bits(uint64_t * dst,uint64_t data,unsigned first_bit,unsigned last_bit)991 rmt_file_write_token_bits(uint64_t *dst, uint64_t data, unsigned first_bit, unsigned last_bit)
992 {
993 rmt_file_write_bits(dst, data, first_bit - 8, last_bit - 8);
994 }
995
996 static enum rmt_heap_type
rmt_file_domain_to_heap_type(enum vk_rmv_kernel_memory_domain domain,bool has_cpu_access)997 rmt_file_domain_to_heap_type(enum vk_rmv_kernel_memory_domain domain, bool has_cpu_access)
998 {
999 switch (domain) {
1000 case VK_RMV_KERNEL_MEMORY_DOMAIN_CPU:
1001 case VK_RMV_KERNEL_MEMORY_DOMAIN_GTT:
1002 return RMT_HEAP_TYPE_SYSTEM;
1003 case VK_RMV_KERNEL_MEMORY_DOMAIN_VRAM:
1004 return has_cpu_access ? RMT_HEAP_TYPE_LOCAL : RMT_HEAP_TYPE_INVISIBLE;
1005 default:
1006 unreachable("invalid domain");
1007 }
1008 }
1009
1010 /*
1011 * Write helpers for stream tokens
1012 */
1013
1014 /* The timestamp frequency, in clock units / second.
1015 * Currently set to 1MHz. */
1016 #define RMT_TIMESTAMP_FREQUENCY (1 * 1000000)
1017 /* Factor needed to convert nanosecond timestamps as returned by os_get_time_nano
1018 * to RMV timestamps */
1019 #define RMT_TIMESTAMP_DIVISOR (1000000000L / RMT_TIMESTAMP_FREQUENCY)
1020
1021 static void
rmt_dump_timestamp(struct vk_rmv_timestamp_token * token,FILE * output)1022 rmt_dump_timestamp(struct vk_rmv_timestamp_token *token, FILE *output)
1023 {
1024 uint64_t data[2] = {0};
1025 rmt_file_write_bits(data, RMT_TOKEN_TYPE_TIMESTAMP, 0, 3);
1026 /* RMT stores clock ticks divided by 32 */
1027 rmt_file_write_bits(data, token->value / 32, 4, 63);
1028 rmt_file_write_bits(data, RMT_TIMESTAMP_FREQUENCY, 64, 89);
1029 fwrite(data, 12, 1, output);
1030 }
1031
1032 static void
rmt_dump_time_delta(uint64_t delta,FILE * output)1033 rmt_dump_time_delta(uint64_t delta, FILE *output)
1034 {
1035 uint64_t data = 0;
1036 rmt_file_write_bits(&data, RMT_TOKEN_TYPE_TIME_DELTA, 0, 3);
1037 rmt_file_write_bits(&data, 7, 4, 7); /* no. of delta bytes */
1038 rmt_file_write_bits(&data, delta, 8, 63);
1039 fwrite(&data, 8, 1, output);
1040 }
1041
1042 static void
rmt_dump_event_resource(struct vk_rmv_event_description * description,FILE * output)1043 rmt_dump_event_resource(struct vk_rmv_event_description *description, FILE *output)
1044 {
1045 /* 8 bits of flags are the only thing in the payload */
1046 fwrite(&description->flags, 1, 1, output);
1047 }
1048
1049 static void
rmt_dump_border_color_palette_resource(struct vk_rmv_border_color_palette_description * description,FILE * output)1050 rmt_dump_border_color_palette_resource(struct vk_rmv_border_color_palette_description *description,
1051 FILE *output)
1052 {
1053 /* no. of entries is the only thing in the payload */
1054 fwrite(&description->num_entries, 1, 1, output);
1055 }
1056
1057 enum rmt_page_size {
1058 RMT_PAGE_SIZE_UNMAPPED,
1059 RMT_PAGE_SIZE_4_KB,
1060 RMT_PAGE_SIZE_64_KB,
1061 RMT_PAGE_SIZE_256_KB,
1062 RMT_PAGE_SIZE_1_MB,
1063 RMT_PAGE_SIZE_2_MB,
1064 };
1065
1066 static enum rmt_page_size
rmt_size_to_page_size(uint32_t size)1067 rmt_size_to_page_size(uint32_t size)
1068 {
1069 switch (size) {
1070 case 4096:
1071 return RMT_PAGE_SIZE_4_KB;
1072 case 65536:
1073 return RMT_PAGE_SIZE_64_KB;
1074 case 262144:
1075 return RMT_PAGE_SIZE_256_KB;
1076 case 1048576:
1077 return RMT_PAGE_SIZE_1_MB;
1078 case 2097152:
1079 return RMT_PAGE_SIZE_2_MB;
1080 default:
1081 unreachable("invalid page size");
1082 }
1083 }
1084
1085 static void
rmt_dump_heap_resource(struct vk_rmv_heap_description * description,FILE * output)1086 rmt_dump_heap_resource(struct vk_rmv_heap_description *description, FILE *output)
1087 {
1088 uint64_t data[2] = {0};
1089 rmt_file_write_bits(data, description->alloc_flags, 0, 3);
1090 rmt_file_write_bits(data, description->size, 4, 68);
1091 rmt_file_write_bits(data, rmt_size_to_page_size(description->alignment), 69, 73);
1092 rmt_file_write_bits(data, description->heap_index, 74, 77);
1093 fwrite(data, 10, 1, output);
1094 }
1095
1096 enum rmt_buffer_usage_flags {
1097 RMT_BUFFER_USAGE_FLAGS_TRANSFER_SOURCE = 1 << 0,
1098 RMT_BUFFER_USAGE_FLAGS_TRANSFER_DESTINATION = 1 << 1,
1099 RMT_BUFFER_USAGE_FLAGS_UNIFORM_TEXEL_BUFFER = 1 << 2,
1100 RMT_BUFFER_USAGE_FLAGS_STORAGE_TEXEL_BUFFER = 1 << 3,
1101 RMT_BUFFER_USAGE_FLAGS_UNIFORM_BUFFER = 1 << 4,
1102 RMT_BUFFER_USAGE_FLAGS_STORAGE_BUFFER = 1 << 5,
1103 RMT_BUFFER_USAGE_FLAGS_INDEX_BUFFER = 1 << 6,
1104 RMT_BUFFER_USAGE_FLAGS_VERTEX_BUFFER = 1 << 7,
1105 RMT_BUFFER_USAGE_FLAGS_INDIRECT_BUFFER = 1 << 8,
1106 RMT_BUFFER_USAGE_FLAGS_TRANSFORM_FEEDBACK_BUFFER = 1 << 9,
1107 RMT_BUFFER_USAGE_FLAGS_TRANSFORM_FEEDBACK_COUNTER_BUFFER = 1 << 10,
1108 RMT_BUFFER_USAGE_FLAGS_CONDITIONAL_RENDERING = 1 << 11,
1109 RMT_BUFFER_USAGE_FLAGS_RAY_TRACING = 1 << 12,
1110 RMT_BUFFER_USAGE_FLAGS_SHADER_DEVICE_ADDRESS = 1 << 13,
1111 };
1112
1113 static void
rmt_dump_buffer_resource(struct vk_rmv_buffer_description * description,FILE * output)1114 rmt_dump_buffer_resource(struct vk_rmv_buffer_description *description, FILE *output)
1115 {
1116 /* flags up to indirect buffer are equivalent */
1117 uint32_t usage_flags =
1118 description->usage_flags & ((VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT << 1) - 1);
1119
1120 if (description->usage_flags & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT)
1121 usage_flags |= RMT_BUFFER_USAGE_FLAGS_TRANSFORM_FEEDBACK_BUFFER;
1122 if (description->usage_flags & VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT)
1123 usage_flags |= RMT_BUFFER_USAGE_FLAGS_TRANSFORM_FEEDBACK_COUNTER_BUFFER;
1124 if (description->usage_flags & VK_BUFFER_USAGE_CONDITIONAL_RENDERING_BIT_EXT)
1125 usage_flags |= RMT_BUFFER_USAGE_FLAGS_CONDITIONAL_RENDERING;
1126 if (description->usage_flags &
1127 (VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_BUILD_INPUT_READ_ONLY_BIT_KHR |
1128 VK_BUFFER_USAGE_ACCELERATION_STRUCTURE_STORAGE_BIT_KHR |
1129 VK_BUFFER_USAGE_SHADER_BINDING_TABLE_BIT_KHR))
1130 usage_flags |= RMT_BUFFER_USAGE_FLAGS_RAY_TRACING;
1131 if (description->usage_flags & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT)
1132 usage_flags |= RMT_BUFFER_USAGE_FLAGS_SHADER_DEVICE_ADDRESS;
1133
1134 uint64_t data[2] = {0};
1135 rmt_file_write_bits(data, description->create_flags, 0, 7);
1136 rmt_file_write_bits(data, usage_flags, 8, 23);
1137 rmt_file_write_bits(data, description->size, 24, 87);
1138 fwrite(data, 11, 1, output);
1139 }
1140
1141 enum rmt_tiling {
1142 RMT_TILING_LINEAR,
1143 RMT_TILING_OPTIMAL,
1144 RMT_TILING_SWIZZLED,
1145 };
1146
1147 enum rmt_tiling_optimization_mode {
1148 RMT_TILING_OPTIMIZATION_MODE_BALANCED,
1149 RMT_TILING_OPTIMIZATION_MODE_SPACE,
1150 RMT_TILING_OPTIMIZATION_MODE_SPEED,
1151 };
1152
1153 enum rmt_metadata_mode {
1154 RMT_METADATA_MODE_DEFAULT,
1155 RMT_METADATA_MODE_OPTIMIZE_TEX_PREFETCH,
1156 RMT_METADATA_MODE_DISABLE,
1157 };
1158
1159 enum rmt_image_create_flags {
1160 RMT_IMAGE_CREATE_INVARIANT = 1 << 0,
1161 RMT_IMAGE_CREATE_CLONEABLE = 1 << 1,
1162 RMT_IMAGE_CREATE_SHAREABLE = 1 << 2,
1163 RMT_IMAGE_CREATE_FLIPPABLE = 1 << 3,
1164 RMT_IMAGE_CREATE_STEREO = 1 << 4,
1165 RMT_IMAGE_CREATE_CUBEMAP = 1 << 5,
1166 RMT_IMAGE_CREATE_PRT = 1 << 6,
1167 };
1168
1169 enum rmt_image_usage_flags {
1170 RMT_IMAGE_USAGE_SHADER_READ = 1 << 0,
1171 RMT_IMAGE_USAGE_SHADER_WRITE = 1 << 1,
1172 RMT_IMAGE_USAGE_RESOLVE_SRC = 1 << 2,
1173 RMT_IMAGE_USAGE_RESOLVE_DST = 1 << 3,
1174 RMT_IMAGE_USAGE_COLOR_TARGET = 1 << 4,
1175 RMT_IMAGE_USAGE_DEPTH_STENCIL = 1 << 5,
1176 };
1177
1178 static void
rmt_dump_image_resource(struct vk_rmv_image_description * description,FILE * output)1179 rmt_dump_image_resource(struct vk_rmv_image_description *description, FILE *output)
1180 {
1181 uint64_t data[5] = {0};
1182
1183 enum rmt_tiling tiling;
1184 switch (description->tiling) {
1185 case VK_IMAGE_TILING_LINEAR:
1186 tiling = RMT_TILING_LINEAR;
1187 break;
1188 case VK_IMAGE_TILING_OPTIMAL:
1189 case VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT:
1190 tiling = RMT_TILING_OPTIMAL;
1191 break;
1192 default:
1193 unreachable("invalid image tiling");
1194 }
1195
1196 uint32_t create_flags = 0;
1197 if (description->create_flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT)
1198 create_flags |= RMT_IMAGE_CREATE_CUBEMAP;
1199 if (description->create_flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)
1200 create_flags |= RMT_IMAGE_CREATE_PRT;
1201
1202 uint32_t usage_flags = 0;
1203 if (description->usage_flags & VK_IMAGE_USAGE_SAMPLED_BIT ||
1204 description->usage_flags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
1205 usage_flags |= RMT_IMAGE_USAGE_SHADER_READ;
1206 if (description->usage_flags & VK_IMAGE_USAGE_STORAGE_BIT)
1207 usage_flags |= RMT_IMAGE_USAGE_SHADER_READ | RMT_IMAGE_USAGE_SHADER_WRITE;
1208 if (description->usage_flags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT)
1209 usage_flags |= RMT_IMAGE_USAGE_COLOR_TARGET;
1210 if (description->usage_flags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)
1211 usage_flags |= RMT_IMAGE_USAGE_DEPTH_STENCIL;
1212 if (description->usage_flags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT)
1213 usage_flags |= RMT_IMAGE_USAGE_RESOLVE_SRC;
1214 if (description->usage_flags & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
1215 usage_flags |= RMT_IMAGE_USAGE_RESOLVE_DST;
1216
1217 enum rmt_swizzle swizzles[4] = {RMT_SWIZZLE_ZERO, RMT_SWIZZLE_ZERO, RMT_SWIZZLE_ZERO,
1218 RMT_SWIZZLE_ZERO};
1219 rmt_format_to_swizzle(description->format, swizzles);
1220
1221 rmt_file_write_bits(data, create_flags, 0, 19);
1222 rmt_file_write_bits(data, usage_flags, 20, 34);
1223 rmt_file_write_bits(data, description->type, 35, 36);
1224 rmt_file_write_bits(data, description->extent.width - 1, 37, 50);
1225 rmt_file_write_bits(data, description->extent.height - 1, 51, 64);
1226 rmt_file_write_bits(data, description->extent.depth - 1, 65, 78);
1227 rmt_file_write_bits(data, swizzles[0], 79, 81);
1228 rmt_file_write_bits(data, swizzles[1], 82, 84);
1229 rmt_file_write_bits(data, swizzles[2], 85, 87);
1230 rmt_file_write_bits(data, swizzles[3], 88, 90);
1231 rmt_file_write_bits(data, vk_to_rmt_format(description->format), 91, 98);
1232 rmt_file_write_bits(data, description->num_mips, 99, 102);
1233 rmt_file_write_bits(data, description->num_slices - 1, 103, 113);
1234 rmt_file_write_bits(data, description->log2_samples, 114, 116);
1235 rmt_file_write_bits(data, description->log2_storage_samples, 117, 118);
1236 rmt_file_write_bits(data, tiling, 119, 120);
1237 rmt_file_write_bits(data, RMT_TILING_OPTIMIZATION_MODE_BALANCED, 121, 122);
1238 rmt_file_write_bits(data, RMT_METADATA_MODE_DEFAULT, 123, 124);
1239 rmt_file_write_bits(data, description->alignment_log2, 125, 129);
1240 rmt_file_write_bits(data, description->presentable, 130, 130);
1241 rmt_file_write_bits(data, description->size, 131, 162);
1242 rmt_file_write_bits(data, description->metadata_offset, 163, 194);
1243 rmt_file_write_bits(data, description->metadata_size, 195, 226);
1244 rmt_file_write_bits(data, description->metadata_header_offset, 227, 258);
1245 rmt_file_write_bits(data, description->metadata_header_size, 259, 290);
1246 rmt_file_write_bits(data, description->image_alignment_log2, 291, 295);
1247 rmt_file_write_bits(data, description->metadata_alignment_log2, 296, 300);
1248 /* metadata header alignment */
1249 rmt_file_write_bits(data, description->metadata_alignment_log2, 301, 305);
1250 /* is fullscreen presentable */
1251 rmt_file_write_bits(data, description->presentable, 306, 306);
1252 fwrite(data, 39, 1, output);
1253 }
1254
1255 enum rmt_query_pool_type {
1256 RMT_QUERY_POOL_TYPE_OCCLUSION,
1257 RMT_QUERY_POOL_TYPE_PIPELINE,
1258 RMT_QUERY_POOL_TYPE_STREAMOUT
1259 };
1260
1261 static void
rmt_dump_query_pool_resource(struct vk_rmv_query_pool_description * description,FILE * output)1262 rmt_dump_query_pool_resource(struct vk_rmv_query_pool_description *description, FILE *output)
1263 {
1264 enum rmt_query_pool_type pool_type;
1265 switch (description->type) {
1266 case VK_QUERY_TYPE_OCCLUSION:
1267 pool_type = RMT_QUERY_POOL_TYPE_OCCLUSION;
1268 break;
1269 case VK_QUERY_TYPE_PIPELINE_STATISTICS:
1270 pool_type = RMT_QUERY_POOL_TYPE_PIPELINE;
1271 break;
1272 case VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT:
1273 pool_type = RMT_QUERY_POOL_TYPE_STREAMOUT;
1274 break;
1275 default:
1276 unreachable("invalid query pool type");
1277 break;
1278 }
1279
1280 uint64_t data = 0;
1281 rmt_file_write_bits(&data, pool_type, 0, 1);
1282 rmt_file_write_bits(&data, description->has_cpu_access, 2, 2);
1283 fwrite(&data, 1, 1, output);
1284 }
1285
1286 enum rmt_pipeline_flags {
1287 RMT_PIPELINE_FLAG_INTERNAL = (1 << 0),
1288 RMT_PIPELINE_FLAG_OVERRIDE_GPU_HEAP = (1 << 1),
1289 };
1290
1291 enum rmt_pipeline_stage_flags {
1292 RMT_PIPELINE_STAGE_FRAGMENT = 1 << 0,
1293 RMT_PIPELINE_STAGE_TESS_CONTROL = 1 << 1,
1294 RMT_PIPELINE_STAGE_TESS_EVAL = 1 << 2,
1295 RMT_PIPELINE_STAGE_VERTEX = 1 << 3,
1296 RMT_PIPELINE_STAGE_GEOMETRY = 1 << 4,
1297 RMT_PIPELINE_STAGE_COMPUTE = 1 << 5,
1298 RMT_PIPELINE_STAGE_TASK = 1 << 6,
1299 RMT_PIPELINE_STAGE_MESH = 1 << 7
1300 };
1301
1302 static void
rmt_dump_pipeline_resource(struct vk_rmv_pipeline_description * description,FILE * output)1303 rmt_dump_pipeline_resource(struct vk_rmv_pipeline_description *description, FILE *output)
1304 {
1305 uint64_t data[3] = {0};
1306
1307 enum rmt_pipeline_flags flags = 0;
1308 if (description->is_internal)
1309 flags |= RMT_PIPELINE_FLAG_INTERNAL;
1310
1311 enum rmt_pipeline_stage_flags stage_flags = 0;
1312 if (description->shader_stages & VK_SHADER_STAGE_FRAGMENT_BIT)
1313 stage_flags |= RMT_PIPELINE_STAGE_FRAGMENT;
1314 if (description->shader_stages & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT)
1315 stage_flags |= RMT_PIPELINE_STAGE_TESS_CONTROL;
1316 if (description->shader_stages & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT)
1317 stage_flags |= RMT_PIPELINE_STAGE_TESS_EVAL;
1318 if (description->shader_stages & VK_SHADER_STAGE_VERTEX_BIT)
1319 stage_flags |= RMT_PIPELINE_STAGE_VERTEX;
1320 if (description->shader_stages & VK_SHADER_STAGE_GEOMETRY_BIT)
1321 stage_flags |= RMT_PIPELINE_STAGE_GEOMETRY;
1322 if (description->shader_stages & VK_SHADER_STAGE_COMPUTE_BIT ||
1323 description->shader_stages & VK_SHADER_STAGE_RAYGEN_BIT_KHR ||
1324 description->shader_stages & VK_SHADER_STAGE_INTERSECTION_BIT_KHR ||
1325 description->shader_stages & VK_SHADER_STAGE_ANY_HIT_BIT_KHR ||
1326 description->shader_stages & VK_SHADER_STAGE_CLOSEST_HIT_BIT_KHR ||
1327 description->shader_stages & VK_SHADER_STAGE_MISS_BIT_KHR ||
1328 description->shader_stages & VK_SHADER_STAGE_CALLABLE_BIT_KHR)
1329 stage_flags |= RMT_PIPELINE_STAGE_COMPUTE;
1330 if (description->shader_stages & VK_SHADER_STAGE_TASK_BIT_EXT)
1331 stage_flags |= RMT_PIPELINE_STAGE_TASK;
1332 if (description->shader_stages & VK_SHADER_STAGE_MESH_BIT_EXT)
1333 stage_flags |= RMT_PIPELINE_STAGE_MESH;
1334
1335 rmt_file_write_bits(data, flags, 0, 7);
1336 rmt_file_write_bits(data, description->hash_hi, 8, 71);
1337 rmt_file_write_bits(data, description->hash_lo, 72, 135);
1338 rmt_file_write_bits(data, stage_flags, 136, 143);
1339 rmt_file_write_bits(data, description->is_ngg, 144, 144);
1340 fwrite(data, 19, 1, output);
1341 }
1342
1343 static void
rmt_dump_descriptor_pool_resource(struct vk_rmv_descriptor_pool_description * description,FILE * output)1344 rmt_dump_descriptor_pool_resource(struct vk_rmv_descriptor_pool_description *description,
1345 FILE *output)
1346 {
1347 uint64_t data = 0;
1348 /* TODO: figure out a better way of handling descriptor counts > 65535 */
1349 rmt_file_write_bits(&data, MIN2(description->max_sets, 65535), 0, 15);
1350 rmt_file_write_bits(&data, rmt_valid_pool_size_count(description), 16, 23);
1351 fwrite(&data, 3, 1, output);
1352
1353 for (uint32_t i = 0; i < description->pool_size_count; ++i) {
1354 data = 0;
1355 enum rmt_descriptor_type rmt_type =
1356 vk_to_rmt_descriptor_type(description->pool_sizes[i].type);
1357 if (rmt_type == RMT_DESCRIPTOR_TYPE_INVALID)
1358 /* Unknown descriptor type, skip */
1359 continue;
1360 rmt_file_write_bits(&data, rmt_type, 0, 15);
1361 rmt_file_write_bits(&data, MIN2(description->pool_sizes[i].descriptorCount, 65535), 16, 31);
1362 fwrite(&data, 4, 1, output);
1363 }
1364 }
1365
1366 static void
rmt_dump_command_buffer_resource(struct vk_rmv_command_buffer_description * description,FILE * output)1367 rmt_dump_command_buffer_resource(struct vk_rmv_command_buffer_description *description,
1368 FILE *output)
1369 {
1370 uint64_t data[6] = {0};
1371 rmt_file_write_bits(data, 0, 0, 3); /* flags */
1372 /* heap for executable commands */
1373 rmt_file_write_bits(data, rmt_file_domain_to_heap_type(description->preferred_domain, true), 4,
1374 7);
1375 /* executable command allocation size */
1376 rmt_file_write_bits(data, description->executable_size, 8, 63);
1377 /* executable command size usable by command buffers */
1378 rmt_file_write_bits(data, description->app_available_executable_size, 64, 119);
1379 /* heap for embedded data */
1380 rmt_file_write_bits(data, rmt_file_domain_to_heap_type(description->preferred_domain, true), 120,
1381 123);
1382 /* embedded data allocation size */
1383 rmt_file_write_bits(data, description->embedded_data_size, 124, 179);
1384 /* embedded data size usable by command buffers */
1385 rmt_file_write_bits(data, description->app_available_embedded_data_size, 180, 235);
1386 /* heap for scratch data */
1387 rmt_file_write_bits(data, rmt_file_domain_to_heap_type(description->preferred_domain, true), 4,
1388 7);
1389 /* scratch data allocation size */
1390 rmt_file_write_bits(data, description->scratch_size, 240, 295);
1391 /* scratch data size usable by command buffers */
1392 rmt_file_write_bits(data, description->app_available_scratch_size, 296, 351);
1393
1394 fwrite(data, 44, 1, output);
1395 }
1396
1397 static void
rmt_dump_resource_create(struct vk_rmv_resource_create_token * token,FILE * output)1398 rmt_dump_resource_create(struct vk_rmv_resource_create_token *token, FILE *output)
1399 {
1400 uint64_t data = 0;
1401 rmt_file_write_token_bits(&data, token->resource_id, 8, 39);
1402 rmt_file_write_token_bits(&data,
1403 token->is_driver_internal ? RMT_RESOURCE_OWNER_TYPE_CLIENT_DRIVER
1404 : RMT_RESOURCE_OWNER_TYPE_APPLICATION,
1405 40, 41);
1406 rmt_file_write_token_bits(&data, token->type, 48, 53);
1407 fwrite(&data, 6, 1, output);
1408
1409 switch (token->type) {
1410 case VK_RMV_RESOURCE_TYPE_GPU_EVENT:
1411 rmt_dump_event_resource(&token->event, output);
1412 break;
1413 case VK_RMV_RESOURCE_TYPE_BORDER_COLOR_PALETTE:
1414 rmt_dump_border_color_palette_resource(&token->border_color_palette, output);
1415 break;
1416 case VK_RMV_RESOURCE_TYPE_HEAP:
1417 rmt_dump_heap_resource(&token->heap, output);
1418 break;
1419 case VK_RMV_RESOURCE_TYPE_BUFFER:
1420 rmt_dump_buffer_resource(&token->buffer, output);
1421 break;
1422 case VK_RMV_RESOURCE_TYPE_IMAGE:
1423 rmt_dump_image_resource(&token->image, output);
1424 break;
1425 case VK_RMV_RESOURCE_TYPE_QUERY_HEAP:
1426 rmt_dump_query_pool_resource(&token->query_pool, output);
1427 break;
1428 case VK_RMV_RESOURCE_TYPE_PIPELINE:
1429 rmt_dump_pipeline_resource(&token->pipeline, output);
1430 break;
1431 case VK_RMV_RESOURCE_TYPE_DESCRIPTOR_POOL:
1432 rmt_dump_descriptor_pool_resource(&token->descriptor_pool, output);
1433 break;
1434 case VK_RMV_RESOURCE_TYPE_COMMAND_ALLOCATOR:
1435 rmt_dump_command_buffer_resource(&token->command_buffer, output);
1436 break;
1437 default:
1438 unreachable("invalid resource type");
1439 }
1440 }
1441
1442 static void
rmt_dump_resource_bind(struct vk_rmv_resource_bind_token * token,FILE * output)1443 rmt_dump_resource_bind(struct vk_rmv_resource_bind_token *token, FILE *output)
1444 {
1445 uint64_t data[3] = {0};
1446 rmt_file_write_token_bits(data, token->address & 0xFFFFFFFFFFFF, 8, 55);
1447 rmt_file_write_token_bits(data, token->size, 56, 99);
1448 rmt_file_write_token_bits(data, token->is_system_memory, 100, 100);
1449 rmt_file_write_token_bits(data, token->resource_id, 104, 135);
1450 fwrite(data, 16, 1, output);
1451 }
1452
1453 static void
rmt_dump_resource_reference(struct vk_rmv_resource_reference_token * token,FILE * output)1454 rmt_dump_resource_reference(struct vk_rmv_resource_reference_token *token,
1455 FILE *output)
1456 {
1457 uint64_t data = 0;
1458 rmt_file_write_token_bits(&data, token->residency_removed, 8, 8);
1459 rmt_file_write_token_bits(&data, token->virtual_address & 0xFFFFFFFFFFFF, 9, 56);
1460 fwrite(&data, 7, 1, output);
1461 }
1462
1463 static void
rmt_dump_resource_destroy(struct vk_rmv_resource_destroy_token * token,FILE * output)1464 rmt_dump_resource_destroy(struct vk_rmv_resource_destroy_token *token, FILE *output)
1465 {
1466 uint64_t data = 0;
1467 rmt_file_write_token_bits(&data, token->resource_id, 8, 39);
1468 fwrite(&data, 4, 1, output);
1469 }
1470
1471 enum rmt_virtual_allocation_owner_type {
1472 RMT_VIRTUAL_ALLOCATION_OWNER_TYPE_APPLICATION,
1473 RMT_VIRTUAL_ALLOCATION_OWNER_TYPE_PAL,
1474 RMT_VIRTUAL_ALLOCATION_OWNER_TYPE_CLIENT_DRIVER,
1475 RMT_VIRTUAL_ALLOCATION_OWNER_TYPE_KERNEL_DRIVER
1476 };
1477
1478 static void
rmt_dump_virtual_alloc(struct vk_rmv_virtual_allocate_token * token,FILE * output)1479 rmt_dump_virtual_alloc(struct vk_rmv_virtual_allocate_token *token, FILE *output)
1480 {
1481 uint64_t data[2] = {0};
1482 rmt_file_write_token_bits(data, token->page_count - 1, 8, 31);
1483 rmt_file_write_token_bits(data,
1484 token->is_driver_internal
1485 ? RMT_VIRTUAL_ALLOCATION_OWNER_TYPE_CLIENT_DRIVER
1486 : RMT_VIRTUAL_ALLOCATION_OWNER_TYPE_APPLICATION,
1487 32, 33);
1488 rmt_file_write_token_bits(data, token->address & 0xFFFFFFFFFFFF, 34, 81);
1489 if (token->preferred_domains) {
1490 rmt_file_write_token_bits(
1491 data, rmt_file_domain_to_heap_type(token->preferred_domains, !token->is_in_invisible_vram),
1492 82, 83);
1493 /* num. of heap types */
1494 rmt_file_write_token_bits(data, 1, 90, 92);
1495 } else
1496 rmt_file_write_token_bits(data, 0, 90, 92);
1497 fwrite(data, 11, 1, output);
1498 }
1499
1500 static void
rmt_dump_virtual_free(struct vk_rmv_virtual_free_token * token,FILE * output)1501 rmt_dump_virtual_free(struct vk_rmv_virtual_free_token *token, FILE *output)
1502 {
1503 uint64_t data = 0;
1504 rmt_file_write_token_bits(&data, token->address & 0xFFFFFFFFFFFF, 8, 56);
1505 fwrite(&data, 6, 1, output);
1506 }
1507
1508 enum rmt_page_table_controller {
1509 RMT_PAGE_TABLE_CONTROLLER_OS,
1510 RMT_PAGE_TABLE_CONTROLLER_KMD,
1511 };
1512
1513 static void
rmt_dump_page_table_update(struct vk_rmv_page_table_update_token * token,FILE * output)1514 rmt_dump_page_table_update(struct vk_rmv_page_table_update_token *token,
1515 FILE *output)
1516 {
1517 uint64_t virtual_page_idx = (token->virtual_address / 4096);
1518 uint64_t physical_page_idx = (token->physical_address / 4096);
1519
1520 enum rmt_page_size page_size = rmt_size_to_page_size(token->page_size);
1521
1522 uint64_t data[3] = {0};
1523 rmt_file_write_token_bits(data, virtual_page_idx & 0xFFFFFFFFF, 8, 43);
1524 rmt_file_write_token_bits(data, physical_page_idx & 0xFFFFFFFFF, 44, 79);
1525 rmt_file_write_token_bits(data, token->page_count, 80, 99);
1526 rmt_file_write_token_bits(data, page_size, 100, 102);
1527 rmt_file_write_token_bits(data, token->is_unmap, 103, 103);
1528 rmt_file_write_token_bits(data, token->pid, 104, 135);
1529 rmt_file_write_token_bits(data, token->type, 136, 137);
1530 rmt_file_write_token_bits(data, RMT_PAGE_TABLE_CONTROLLER_KMD, 138, 138);
1531 fwrite(data, 17, 1, output);
1532 }
1533
1534 enum rmt_userdata_type {
1535 RMT_USERDATA_TYPE_NAME,
1536 RMT_USERDATA_TYPE_SNAPSHOT,
1537 RMT_USERDATA_TYPE_BINARY,
1538 RMT_USERDATA_TYPE_RESERVED,
1539 RMT_USERDATA_TYPE_CORRELATION,
1540 RMT_USERDATA_TYPE_MARK_IMPLICIT_RESOURCE,
1541 };
1542
1543 static void
rmt_dump_userdata(struct vk_rmv_userdata_token * token,FILE * output)1544 rmt_dump_userdata(struct vk_rmv_userdata_token *token, FILE *output)
1545 {
1546 uint64_t data = 0;
1547 /* userdata type */
1548 rmt_file_write_token_bits(&data, RMT_USERDATA_TYPE_NAME, 8, 11);
1549 /* size of userdata payload */
1550 rmt_file_write_token_bits(&data, strlen(token->name) + sizeof(uint32_t) + 1, 12, 23);
1551
1552 fwrite(&data, 3, 1, output);
1553 fwrite(token->name, 1, strlen(token->name) + 1, output);
1554 fwrite(&token->resource_id, sizeof(uint32_t), 1, output);
1555 }
1556
1557 static void
rmt_dump_misc(struct vk_rmv_misc_token * token,FILE * output)1558 rmt_dump_misc(struct vk_rmv_misc_token *token, FILE *output)
1559 {
1560 uint64_t data = 0;
1561 rmt_file_write_token_bits(&data, token->type, 8, 11);
1562 fwrite(&data, 1, 1, output);
1563 }
1564
1565 static void
rmt_dump_cpu_map(struct vk_rmv_cpu_map_token * token,FILE * output)1566 rmt_dump_cpu_map(struct vk_rmv_cpu_map_token *token, FILE *output)
1567 {
1568 uint64_t data = 0;
1569 rmt_file_write_token_bits(&data, token->address & 0xFFFFFFFFFFFF, 8, 55);
1570 rmt_file_write_token_bits(&data, token->unmapped, 56, 56);
1571 fwrite(&data, 7, 1, output);
1572 }
1573
1574 static void
rmt_dump_data(struct vk_memory_trace_data * data,FILE * output)1575 rmt_dump_data(struct vk_memory_trace_data *data, FILE *output)
1576 {
1577 struct rmt_file_header header = {0};
1578 struct rmt_file_chunk_system_info system_info_chunk = {0};
1579 struct rmt_file_chunk_adapter_info adapter_info_chunk = {0};
1580 struct rmt_file_chunk_rmt_data data_chunk = {0};
1581
1582 /* RMT header */
1583 rmt_fill_header(&header);
1584 fwrite(&header, sizeof(header), 1, output);
1585
1586 /* System info */
1587 rmt_fill_chunk_system_info(&system_info_chunk);
1588 fwrite(&system_info_chunk, sizeof(system_info_chunk), 1, output);
1589
1590 /* Segment info */
1591 for (int32_t i = 0; i < 3; ++i) {
1592 struct rmt_file_chunk_segment_info segment_info_chunk = {0};
1593
1594 rmt_fill_chunk_segment_info(data, &data->device_info, &segment_info_chunk, i);
1595 fwrite(&segment_info_chunk, sizeof(segment_info_chunk), 1, output);
1596 }
1597
1598 /* Adapter info */
1599 rmt_fill_chunk_adapter_info(&data->device_info, &adapter_info_chunk);
1600 fwrite(&adapter_info_chunk, sizeof(adapter_info_chunk), 1, output);
1601
1602 long chunk_start = ftell(output);
1603 /* Write a dummy data chunk to reserve space */
1604 fwrite(&data_chunk, sizeof(data_chunk), 1, output);
1605
1606 qsort(data->tokens.data, util_dynarray_num_elements(&data->tokens, struct vk_rmv_token),
1607 sizeof(struct vk_rmv_token), vk_rmv_token_compare);
1608
1609 uint64_t current_timestamp = 0;
1610 if (util_dynarray_num_elements(&data->tokens, struct vk_rmv_token))
1611 current_timestamp =
1612 util_dynarray_element(&data->tokens, struct vk_rmv_token, 0)->timestamp / RMT_TIMESTAMP_DIVISOR;
1613
1614 long stream_start = ftell(output);
1615
1616 struct vk_rmv_timestamp_token timestamp_token;
1617 timestamp_token.value = 0;
1618 rmt_dump_timestamp(×tamp_token, output);
1619
1620 util_dynarray_foreach (&data->tokens, struct vk_rmv_token, token) {
1621 /* Only temporarily modify the token's timestamp in case of multiple traces */
1622 uint64_t old_timestamp = token->timestamp;
1623 /* adjust timestamp to 1 MHz, see rmt_fill_chunk_system_info */
1624 token->timestamp /= RMT_TIMESTAMP_DIVISOR;
1625
1626 int64_t delta = token->timestamp - current_timestamp;
1627
1628 /* Time values are stored divided by 32 */
1629 delta /= 32;
1630
1631 /*
1632 * Each token can hold up to 4 bits of time delta. If the delta doesn't
1633 * fit in 4 bits, an additional token containing more space for the delta
1634 * has to be emitted.
1635 */
1636 if (delta > 0xF) {
1637 rmt_dump_time_delta(delta, output);
1638 delta = 0;
1639 }
1640
1641 uint64_t token_header = 0;
1642 rmt_file_write_bits(&token_header, token_type_to_rmt(token->type), 0, 3);
1643 rmt_file_write_bits(&token_header, delta, 4, 7);
1644 fwrite(&token_header, 1, 1, output);
1645
1646 switch (token->type) {
1647 case VK_RMV_TOKEN_TYPE_VIRTUAL_ALLOCATE:
1648 rmt_dump_virtual_alloc(&token->data.virtual_allocate, output);
1649 break;
1650 case VK_RMV_TOKEN_TYPE_VIRTUAL_FREE:
1651 rmt_dump_virtual_free(&token->data.virtual_free, output);
1652 break;
1653 case VK_RMV_TOKEN_TYPE_PAGE_TABLE_UPDATE:
1654 rmt_dump_page_table_update(&token->data.page_table_update, output);
1655 break;
1656 case VK_RMV_TOKEN_TYPE_RESOURCE_CREATE:
1657 rmt_dump_resource_create(&token->data.resource_create, output);
1658 break;
1659 case VK_RMV_TOKEN_TYPE_RESOURCE_DESTROY:
1660 rmt_dump_resource_destroy(&token->data.resource_destroy, output);
1661 break;
1662 case VK_RMV_TOKEN_TYPE_RESOURCE_BIND:
1663 rmt_dump_resource_bind(&token->data.resource_bind, output);
1664 break;
1665 case VK_RMV_TOKEN_TYPE_RESOURCE_REFERENCE:
1666 rmt_dump_resource_reference(&token->data.resource_reference, output);
1667 break;
1668 case VK_RMV_TOKEN_TYPE_USERDATA:
1669 rmt_dump_userdata(&token->data.userdata, output);
1670 break;
1671 case VK_RMV_TOKEN_TYPE_MISC:
1672 rmt_dump_misc(&token->data.misc, output);
1673 break;
1674 case VK_RMV_TOKEN_TYPE_CPU_MAP:
1675 rmt_dump_cpu_map(&token->data.cpu_map, output);
1676 break;
1677 default:
1678 unreachable("invalid token type");
1679 }
1680
1681 current_timestamp = token->timestamp;
1682 token->timestamp = old_timestamp;
1683 }
1684 long stream_end = ftell(output);
1685
1686 /* Go back and write the correct chunk data. */
1687 fseek(output, chunk_start, SEEK_SET);
1688 rmt_fill_chunk_rmt_data(stream_end - stream_start, &data_chunk);
1689 fwrite(&data_chunk, sizeof(data_chunk), 1, output);
1690 }
1691
1692 int
vk_dump_rmv_capture(struct vk_memory_trace_data * data)1693 vk_dump_rmv_capture(struct vk_memory_trace_data *data)
1694 {
1695 char filename[2048];
1696 struct tm now;
1697 FILE *f;
1698
1699 time_t t = time(NULL);
1700 now = *localtime(&t);
1701
1702 snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.%02d.rmv",
1703 util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour,
1704 now.tm_min, now.tm_sec);
1705
1706 f = fopen(filename, "wb");
1707 if (!f)
1708 return -1;
1709
1710 rmt_dump_data(data, f);
1711
1712 fprintf(stderr, "RMV capture saved to '%s'\n", filename);
1713
1714 fclose(f);
1715 return 0;
1716 }
1717