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(&timestamp_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