Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/amd/common/ac_surface_modifier_test.c
7136 views
1
/* Make the test not meaningless when asserts are disabled. */
2
#undef NDEBUG
3
4
#include <assert.h>
5
#include <inttypes.h>
6
#include <stdio.h>
7
#include <stdlib.h>
8
9
#include <amdgpu.h>
10
#include "drm-uapi/amdgpu_drm.h"
11
#include "drm-uapi/drm_fourcc.h"
12
13
#include "ac_surface.h"
14
#include "util/macros.h"
15
#include "util/u_math.h"
16
#include "util/u_vector.h"
17
#include "util/mesa-sha1.h"
18
#include "addrlib/inc/addrinterface.h"
19
20
#include "ac_surface_test_common.h"
21
22
/*
23
* The main goal of this test is making sure that we do
24
* not change the meaning of existing modifiers.
25
*/
26
27
struct test_entry {
28
/* key part */
29
uint64_t modifier;
30
unsigned w;
31
unsigned h;
32
enum pipe_format format;
33
34
/* debug info */
35
const char *name;
36
uint8_t pipes;
37
uint8_t rb;
38
uint8_t banks_or_pkrs;
39
uint8_t se;
40
41
/* value to determine uniqueness */
42
unsigned char hash[20];
43
44
/* u_vector requires power of two sizing */
45
char padding[sizeof(void*) == 8 ? 8 : 16];
46
};
47
48
static uint64_t
49
block_count(unsigned w, unsigned h, unsigned elem_bits, unsigned block_bits,
50
unsigned *aligned_pitch, unsigned *aligned_height)
51
{
52
unsigned align_bits = block_bits - elem_bits;
53
unsigned w_align = 1 << (align_bits / 2 + align_bits % 2);
54
unsigned h_align = 1 << (align_bits / 2);
55
56
w = align(w, w_align);
57
h = align(h, h_align);
58
59
if (aligned_pitch)
60
*aligned_pitch = w;
61
62
if (aligned_height)
63
*aligned_height = h;
64
return ((uint64_t)w * h) >> align_bits;
65
}
66
67
68
static ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT
69
get_addr_from_coord_base(ADDR_HANDLE addrlib, const struct radeon_surf *surf,
70
unsigned w, unsigned h, enum pipe_format format,
71
bool rb_aligned, bool pipe_aligned)
72
{
73
ADDR2_COMPUTE_DCCINFO_INPUT din = {0};
74
ADDR2_COMPUTE_DCCINFO_OUTPUT dout = {0};
75
din.size = sizeof(ADDR2_COMPUTE_DCCINFO_INPUT);
76
dout.size = sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT);
77
78
din.swizzleMode = surf->u.gfx9.swizzle_mode;
79
din.resourceType = ADDR_RSRC_TEX_2D;
80
din.bpp = util_format_get_blocksizebits(format);
81
din.unalignedWidth = w;
82
din.unalignedHeight = h;
83
din.numSlices = 1;
84
din.numMipLevels = 1;
85
din.numFrags = 1;
86
din.dccKeyFlags.pipeAligned = surf->u.gfx9.color.dcc.pipe_aligned;
87
din.dccKeyFlags.rbAligned = surf->u.gfx9.color.dcc.rb_aligned;
88
din.dataSurfaceSize = surf->surf_size;
89
90
ADDR_E_RETURNCODE ret = Addr2ComputeDccInfo(addrlib, &din, &dout);
91
assert(ret == ADDR_OK);
92
93
ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT dcc_input = {0};
94
dcc_input.size = sizeof(dcc_input);
95
dcc_input.swizzleMode = surf->u.gfx9.swizzle_mode;
96
dcc_input.resourceType = ADDR_RSRC_TEX_2D;
97
dcc_input.bpp = din.bpp;
98
dcc_input.numSlices = 1;
99
dcc_input.numMipLevels = 1;
100
dcc_input.numFrags = 1;
101
dcc_input.dccKeyFlags.pipeAligned = pipe_aligned;
102
dcc_input.dccKeyFlags.rbAligned = rb_aligned;
103
dcc_input.pitch = dout.pitch;
104
dcc_input.height = dout.height;
105
dcc_input.compressBlkWidth = dout.compressBlkWidth;
106
dcc_input.compressBlkHeight = dout.compressBlkHeight;
107
dcc_input.compressBlkDepth = dout.compressBlkDepth;
108
dcc_input.metaBlkWidth = dout.metaBlkWidth;
109
dcc_input.metaBlkHeight = dout.metaBlkHeight;
110
dcc_input.metaBlkDepth = dout.metaBlkDepth;
111
return dcc_input;
112
}
113
114
static
115
void generate_hash(struct ac_addrlib *ac_addrlib,
116
struct test_entry *entry,
117
const struct radeon_surf *surf)
118
{
119
ADDR_HANDLE addrlib = ac_addrlib_get_handle(ac_addrlib);
120
121
srandom(53);
122
struct mesa_sha1 ctx;
123
_mesa_sha1_init(&ctx);
124
125
_mesa_sha1_update(&ctx, &surf->total_size, sizeof(surf->total_size));
126
_mesa_sha1_update(&ctx, &surf->meta_offset, sizeof(surf->meta_offset));
127
_mesa_sha1_update(&ctx, &surf->display_dcc_offset, sizeof(surf->display_dcc_offset));
128
_mesa_sha1_update(&ctx, &surf->u.gfx9.color.display_dcc_pitch_max,
129
sizeof(surf->u.gfx9.color.display_dcc_pitch_max));
130
131
ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT input = {0};
132
input.size = sizeof(input);
133
input.swizzleMode = surf->u.gfx9.swizzle_mode;
134
input.resourceType = ADDR_RSRC_TEX_2D;
135
input.bpp = util_format_get_blocksizebits(entry->format);
136
input.unalignedWidth = entry->w;
137
input.unalignedHeight = entry->h;
138
input.numSlices = 1;
139
input.numMipLevels = 1;
140
input.numSamples = 1;
141
input.numFrags = 1;
142
input.pitchInElement = surf->u.gfx9.surf_pitch;
143
144
ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT dcc_input = {0};
145
if (surf->meta_offset) {
146
dcc_input = get_addr_from_coord_base(addrlib, surf, entry->w,
147
entry->h, entry->format,
148
surf->u.gfx9.color.dcc.rb_aligned,
149
surf->u.gfx9.color.dcc.pipe_aligned);
150
}
151
152
ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT display_dcc_input = {0};
153
if (surf->display_dcc_offset) {
154
display_dcc_input = get_addr_from_coord_base(addrlib, surf, entry->w,
155
entry->h, entry->format,
156
false, false);
157
}
158
159
for (unsigned i = 0; i < 1000; ++i) {
160
int32_t x, y;
161
x = random();
162
y = random();
163
164
input.x = (x & INT_MAX) % entry->w;
165
input.y = (y & INT_MAX) % entry->h;
166
167
ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT output = {0};
168
output.size = sizeof(output);
169
170
ADDR_E_RETURNCODE ret = Addr2ComputeSurfaceAddrFromCoord(addrlib, &input, &output);
171
assert(ret == ADDR_OK);
172
173
_mesa_sha1_update(&ctx, &output.addr, sizeof(output.addr));
174
175
if (surf->meta_offset) {
176
dcc_input.x = (x & INT_MAX) % entry->w;
177
dcc_input.y = (y & INT_MAX) % entry->h;
178
179
ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT dcc_output = {0};
180
dcc_output.size = sizeof(dcc_output);
181
182
ret = Addr2ComputeDccAddrFromCoord(addrlib, &dcc_input, &dcc_output);
183
assert(ret == ADDR_OK);
184
185
_mesa_sha1_update(&ctx, &dcc_output.addr, sizeof(dcc_output.addr));
186
}
187
188
if (surf->display_dcc_offset) {
189
display_dcc_input.x = (x & INT_MAX) % entry->w;
190
display_dcc_input.y = (y & INT_MAX) % entry->h;
191
192
ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT dcc_output = {0};
193
dcc_output.size = sizeof(dcc_output);
194
195
ret = Addr2ComputeDccAddrFromCoord(addrlib, &display_dcc_input, &dcc_output);
196
assert(ret == ADDR_OK);
197
198
_mesa_sha1_update(&ctx, &dcc_output.addr, sizeof(dcc_output.addr));
199
}
200
}
201
202
_mesa_sha1_final(&ctx, entry->hash);
203
}
204
205
static void test_modifier(const struct radeon_info *info,
206
const char *name,
207
struct ac_addrlib *addrlib,
208
uint64_t modifier,
209
enum pipe_format format,
210
struct u_vector *test_entries)
211
{
212
unsigned elem_bits = util_logbase2(util_format_get_blocksize(format));
213
const unsigned dims[][2] = {
214
{1, 1},
215
{1920, 1080},
216
{1366, 768},
217
{3840, 2160},
218
{233, 938},
219
};
220
for (unsigned i = 0; i < ARRAY_SIZE(dims); ++i) {
221
struct ac_surf_config config = (struct ac_surf_config) {
222
.info = (struct ac_surf_info) {
223
.width = dims[i][0],
224
.height = dims[i][1],
225
.depth = 1,
226
.samples = 1,
227
.storage_samples = 1,
228
.levels = 1,
229
.num_channels = 3,
230
.array_size = 1
231
},
232
};
233
234
struct test_entry entry = {
235
.modifier = modifier,
236
.w = config.info.width,
237
.h = config.info.height,
238
.format = format,
239
.name = name,
240
.pipes = G_0098F8_NUM_PIPES(info->gb_addr_config),
241
.rb = G_0098F8_NUM_RB_PER_SE(info->gb_addr_config) +
242
G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config),
243
.se = G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config),
244
.banks_or_pkrs = info->chip_class >= GFX10 ?
245
(info->gb_addr_config) : G_0098F8_NUM_BANKS(info->gb_addr_config)
246
};
247
248
struct radeon_surf surf = (struct radeon_surf) {
249
.blk_w = 1,
250
.blk_h = 1,
251
.bpe = util_format_get_blocksize(format),
252
.modifier = modifier,
253
};
254
255
int r = ac_compute_surface(addrlib, info, &config, RADEON_SURF_MODE_2D, &surf);
256
assert(!r);
257
258
assert(surf.cmask_offset == 0);
259
assert(surf.fmask_offset == 0);
260
261
uint64_t surf_size;
262
unsigned aligned_pitch, aligned_height;
263
if (modifier != DRM_FORMAT_MOD_LINEAR) {
264
surf_size = block_count(dims[i][0], dims[i][1],
265
elem_bits, 16, &aligned_pitch,
266
&aligned_height) << 16;
267
} else {
268
aligned_pitch = align(dims[i][0], 256 / util_format_get_blocksize(format));
269
aligned_height = dims[i][1];
270
surf_size = align(dims[i][0] * util_format_get_blocksize(format), 256) * dims[i][1];
271
}
272
273
274
assert(surf.u.gfx9.surf_pitch == aligned_pitch);
275
assert(surf.u.gfx9.surf_height == aligned_height);
276
assert(surf.surf_size == surf_size);
277
uint64_t expected_offset = surf_size;
278
279
if (ac_modifier_has_dcc_retile(modifier)) {
280
unsigned dcc_align = info->chip_class >= GFX10 ? 4096 : 65536;
281
unsigned dcc_pitch;
282
uint64_t dcc_size = block_count(dims[i][0], dims[i][1],
283
elem_bits, 20, &dcc_pitch,
284
NULL) << 12;
285
286
assert(surf.u.gfx9.color.display_dcc_size == align(dcc_size, dcc_align));
287
assert(surf.u.gfx9.color.display_dcc_pitch_max + 1 == dcc_pitch);
288
assert(surf.display_dcc_offset == expected_offset);
289
290
expected_offset += align(dcc_size, dcc_align);
291
} else
292
assert(!surf.display_dcc_offset);
293
294
if (ac_modifier_has_dcc(modifier)) {
295
uint64_t dcc_align = 1;
296
unsigned block_bits;
297
if (info->chip_class >= GFX10) {
298
unsigned num_pipes = G_0098F8_NUM_PIPES(info->gb_addr_config);
299
if (info->chip_class == GFX10_3 &&
300
G_0098F8_NUM_PKRS(info->gb_addr_config) == num_pipes && num_pipes > 1)
301
++num_pipes;
302
block_bits = 16 +
303
num_pipes +
304
G_0098F8_PIPE_INTERLEAVE_SIZE_GFX9(info->gb_addr_config);
305
block_bits = MAX2(block_bits, 20);
306
dcc_align = MAX2(4096, 256 <<
307
(num_pipes +
308
G_0098F8_PIPE_INTERLEAVE_SIZE_GFX9(info->gb_addr_config)));
309
} else {
310
block_bits = 18 +
311
G_0098F8_NUM_RB_PER_SE(info->gb_addr_config) +
312
G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config);
313
block_bits = MAX2(block_bits, 20);
314
dcc_align = 65536;
315
}
316
317
expected_offset = align(expected_offset, dcc_align);
318
assert(surf.meta_offset == expected_offset);
319
320
uint64_t dcc_size = block_count(dims[i][0], dims[i][1],
321
elem_bits, block_bits,
322
NULL, NULL) << (block_bits - 8);
323
dcc_size = align64(dcc_size, dcc_align);
324
assert(surf.meta_size == dcc_size);
325
326
expected_offset += dcc_size;
327
} else
328
assert(!surf.meta_offset);
329
330
assert(surf.total_size == expected_offset);
331
332
generate_hash(addrlib, &entry, &surf);
333
*(struct test_entry*)u_vector_add(test_entries) = entry;
334
}
335
336
}
337
338
static void run_modifier_test(struct u_vector *test_entries, const char *name,
339
const struct radeon_info *info)
340
{
341
struct ac_addrlib *addrlib = ac_addrlib_create(info, NULL);
342
assert(addrlib);
343
344
const struct ac_modifier_options options = {
345
.dcc = true,
346
.dcc_retile = true,
347
};
348
349
enum pipe_format formats[] = {
350
PIPE_FORMAT_R8_UNORM,
351
PIPE_FORMAT_R16_UNORM,
352
PIPE_FORMAT_R32_FLOAT,
353
PIPE_FORMAT_R32G32_FLOAT,
354
PIPE_FORMAT_R32G32B32A32_FLOAT
355
};
356
for (unsigned j = 0; j < ARRAY_SIZE(formats); ++j) {
357
unsigned mod_count = 0;
358
ac_get_supported_modifiers(info, &options, formats[j], &mod_count, NULL);
359
360
uint64_t *modifiers = malloc(sizeof(uint64_t) * mod_count);
361
ac_get_supported_modifiers(info, &options, formats[j], &mod_count, modifiers);
362
363
for (unsigned i = 0; i < mod_count; ++i) {
364
test_modifier(info, name, addrlib, modifiers[i], formats[j], test_entries);
365
}
366
367
free(modifiers);
368
}
369
ac_addrlib_destroy(addrlib);
370
}
371
372
static int compare_test_entry(const void *a, const void *b)
373
{
374
return memcmp(a, b, sizeof(struct test_entry));
375
}
376
377
static bool test_entry_key_equal(const struct test_entry *a, const struct test_entry *b)
378
{
379
return a->modifier == b->modifier && a->w == b->w && a->h == b->h && a->format == b->format;
380
}
381
382
static bool test_entry_value_equal(const struct test_entry *a, const struct test_entry *b)
383
{
384
if (memcmp(a->hash, b->hash, sizeof(a->hash)))
385
return false;
386
return true;
387
}
388
389
static void print_test_entry(const struct test_entry *e)
390
{
391
printf("%.16" PRIx64 " %.4d %.4d %.2d %s %d %d %d %d\n", e->modifier, e->w, e->h,
392
util_format_get_blocksize(e->format), e->name, e->pipes, e->rb, e->se, e->banks_or_pkrs);
393
}
394
395
int main()
396
{
397
STATIC_ASSERT(sizeof(struct test_entry) == 64);
398
399
struct u_vector test_entries;
400
u_vector_init(&test_entries, sizeof(struct test_entry), 4096);
401
402
for (unsigned i = 0; i < ARRAY_SIZE(testcases); ++i) {
403
struct radeon_info info = get_radeon_info(&testcases[i]);
404
405
run_modifier_test(&test_entries, testcases[i].name, &info);
406
}
407
408
qsort(u_vector_tail(&test_entries),
409
u_vector_length(&test_entries),
410
sizeof(struct test_entry),
411
compare_test_entry);
412
413
struct test_entry *cur, *prev = NULL, *prevprev = NULL;
414
bool mismatched_duplicates = false;
415
u_vector_foreach(cur, &test_entries) {
416
if (prev && test_entry_key_equal(cur, prev) &&
417
!test_entry_value_equal(cur, prev)) {
418
if (!prevprev || !test_entry_key_equal(prev, prevprev)) {
419
print_test_entry(prev);
420
}
421
print_test_entry(cur);
422
mismatched_duplicates = true;
423
}
424
prevprev = prev;
425
prev = cur;
426
}
427
assert(!mismatched_duplicates);
428
429
u_vector_finish(&test_entries);
430
431
return 0;
432
}
433
434