1 /*
2 * Copyright 2024 Advanced Micro Devices, Inc.
3 *
4 * SPDX-License-Identifier: MIT
5 */
6
7 /* This file implements performance tests for graphics and compute blits and clears. */
8
9 #include "si_pipe.h"
10 #include "util/rand_xor.h"
11 #include "util/u_surface.h"
12
13 #define RANDOM_DATA_SIZE (611953 * 8) /* prime number * 8 */
14
15 /* For MSAA, level_or_sample_index == 0 means set all samples, while level_or_sample_index > 0
16 * means set the sample equal to level_or_sample_index - 1.
17 */
set_random_pixels(struct pipe_context * ctx,struct pipe_resource * tex,unsigned level_or_sample_index,uint64_t * random_data)18 static void set_random_pixels(struct pipe_context *ctx, struct pipe_resource *tex,
19 unsigned level_or_sample_index, uint64_t *random_data)
20 {
21 struct pipe_transfer *t;
22 uint8_t *map = pipe_texture_map_3d(ctx, tex, level_or_sample_index, PIPE_MAP_WRITE, 0, 0, 0,
23 tex->width0, tex->height0, tex->depth0, &t);
24 assert(map);
25 /* It's static because we want following calls of this function to continue from
26 * the previous offset.
27 */
28 static unsigned random_data_offset = 0;
29
30 for (unsigned z = 0; z < tex->depth0; z++) {
31 for (unsigned y = 0; y < tex->height0; y++) {
32 uint64_t *ptr = (uint64_t *)(map + t->layer_stride * z + t->stride * y);
33 unsigned size = t->stride;
34 assert(size % 8 == 0);
35
36 while (size) {
37 unsigned copy_size =
38 random_data_offset + size <= RANDOM_DATA_SIZE ? size :
39 RANDOM_DATA_SIZE - random_data_offset;
40
41 memcpy(ptr, (uint8_t*)random_data + random_data_offset, copy_size);
42 size -= copy_size;
43 ptr += copy_size / 8;
44 random_data_offset += copy_size;
45 if (random_data_offset >= RANDOM_DATA_SIZE) {
46 assert(random_data_offset == RANDOM_DATA_SIZE);
47 random_data_offset = 0;
48 }
49 }
50 }
51 }
52
53 pipe_texture_unmap(ctx, t);
54 }
55
set_gradient_pixels(struct pipe_context * ctx,struct pipe_resource * tex)56 static void set_gradient_pixels(struct pipe_context *ctx, struct pipe_resource *tex)
57 {
58 struct pipe_transfer *t;
59 uint8_t *map = pipe_texture_map_3d(ctx, tex, 0, PIPE_MAP_WRITE, 0, 0, 0,
60 tex->width0, tex->height0, tex->depth0, &t);
61 assert(map);
62
63 /* Generate just 1 line of pixels. */
64 unsigned pix_size = util_format_get_blocksize(tex->format);
65 unsigned line_size = tex->width0 * pix_size;
66 uint8_t *line = (uint8_t*)malloc(line_size);
67
68 if (util_format_is_pure_integer(tex->format)) {
69 for (unsigned x = 0; x < tex->width0; x++) {
70 union pipe_color_union color;
71 color.ui[0] = color.ui[1] = color.ui[2] = color.ui[3] = x;
72
73 util_pack_color_union(tex->format, (union util_color *)(line + x * pix_size), &color);
74 }
75 } else if (util_format_is_float(tex->format)) {
76 for (unsigned x = 0; x < tex->width0; x++) {
77 union pipe_color_union color;
78 color.f[0] = color.f[1] = color.f[2] = color.f[3] = (float)x / (tex->width0 - 1);
79
80 util_pack_color_union(tex->format, (union util_color *)(line + x * pix_size), &color);
81 }
82 } else {
83 for (unsigned x = 0; x < tex->width0; x++)
84 util_pack_color_ub(x, x, x, x, tex->format, (union util_color *)(line + x * pix_size));
85 }
86
87 /* Copy the generated line to all lines. */
88 for (unsigned z = 0; z < tex->depth0; z++) {
89 for (unsigned y = 0; y < tex->height0; y++)
90 memcpy(map + t->layer_stride * z + t->stride * y, line, line_size);
91 }
92
93 free(line);
94 pipe_texture_unmap(ctx, t);
95 }
96
97 static enum pipe_format formats[] = {
98 PIPE_FORMAT_R8_UNORM,
99 PIPE_FORMAT_R8_UINT,
100 PIPE_FORMAT_R16_UINT,
101 PIPE_FORMAT_R16_FLOAT,
102 PIPE_FORMAT_R8G8B8A8_UNORM,
103 PIPE_FORMAT_R32_UINT,
104 PIPE_FORMAT_R32_FLOAT,
105 PIPE_FORMAT_R32G32_UINT,
106 PIPE_FORMAT_R32G32_FLOAT,
107 PIPE_FORMAT_R16G16B16A16_FLOAT,
108 PIPE_FORMAT_R32G32B32A32_UINT,
109 PIPE_FORMAT_R32G32B32A32_FLOAT,
110 };
111
112 enum {
113 TEST_FB_CLEAR,
114 TEST_CLEAR,
115 TEST_COPY,
116 TEST_BLIT,
117 TEST_RESOLVE,
118 NUM_TESTS,
119 };
120
121 static const char *test_strings[] = {
122 [TEST_FB_CLEAR] = "fbclear",
123 [TEST_CLEAR] = "cleartex",
124 [TEST_COPY] = "copy",
125 [TEST_BLIT] = "blit",
126 [TEST_RESOLVE] = "resolve",
127 };
128
129 enum {
130 LAYOUT_T2T, /* tiled to tiled or clear tiled */
131 LAYOUT_L2T, /* linear to tiled */
132 LAYOUT_T2L, /* tiled to linear */
133 LAYOUT_L2L, /* linear to linear or clear linear */
134 NUM_LAYOUTS,
135 };
136
137 static const char *layout_strings[] = {
138 [LAYOUT_T2T] = "T2T",
139 [LAYOUT_L2T] = "L2T",
140 [LAYOUT_T2L] = "T2L",
141 [LAYOUT_L2L] = "L2L",
142 };
143
144 enum {
145 BOX_FULL,
146 BOX_FULL_YFLIP,
147 BOX_PARTIAL,
148 BOX_PARTIAL_UNALIGNED,
149 BOX_PARTIAL_UNALIGNED_YFLIP,
150 NUM_BOXES,
151 };
152
153 static const char *box_strings[] = {
154 [BOX_FULL] = "full",
155 [BOX_FULL_YFLIP] = "yflip",
156 [BOX_PARTIAL] = "partial",
157 [BOX_PARTIAL_UNALIGNED] = "unaligned",
158 [BOX_PARTIAL_UNALIGNED_YFLIP] = "yflip/unali",
159 };
160
161 enum {
162 FILL_BLACK,
163 FILL_SOLID,
164 FILL_GRADIENT,
165 FILL_RANDOM,
166 FILL_RANDOM_FRAGMENTED2,
167 FILL_RANDOM_FRAGMENTED4,
168 FILL_RANDOM_FRAGMENTED8,
169 NUM_FILLS,
170 };
171
172 static const char *fill_strings[] = {
173 [FILL_BLACK] = "black",
174 [FILL_SOLID] = "solid",
175 [FILL_GRADIENT] = "gradient",
176 [FILL_RANDOM] = "random",
177 [FILL_RANDOM_FRAGMENTED2] = "fragmented2",
178 [FILL_RANDOM_FRAGMENTED4] = "fragmented4",
179 [FILL_RANDOM_FRAGMENTED8] = "fragmented8",
180 };
181
182 enum {
183 METHOD_DEFAULT,
184 METHOD_GFX,
185 METHOD_COMPUTE,
186 METHOD_SPECIAL,
187 NUM_METHODS,
188 };
189
190 static const union pipe_color_union black_color_float = {.f = {0, 0, 0, 0}};
191 static const union pipe_color_union solid_color_float = {.f = {0.2, 0.3, 0.4, 0.5}};
192 static const union pipe_color_union black_color_uint = {.ui = {0, 0, 0, 0}};
193 static const union pipe_color_union solid_color_uint = {.ui = {23, 45, 89, 107}};
194
si_test_blit_perf(struct si_screen * sscreen)195 void si_test_blit_perf(struct si_screen *sscreen)
196 {
197 struct pipe_screen *screen = &sscreen->b;
198 struct pipe_context *ctx = screen->context_create(screen, NULL, 0);
199 struct si_context *sctx = (struct si_context *)ctx;
200
201 uint64_t seed_xorshift128plus[2];
202 uint64_t random_data[RANDOM_DATA_SIZE / 8];
203
204 /* Set the seed for random pixel data */
205 s_rand_xorshift128plus(seed_xorshift128plus, false);
206
207 /* Pre-generate random data for initializing textures. */
208 for (unsigned i = 0; i < ARRAY_SIZE(random_data); i++)
209 random_data[i] = rand_xorshift128plus(seed_xorshift128plus);
210
211 sscreen->ws->cs_set_pstate(&sctx->gfx_cs, RADEON_CTX_PSTATE_PEAK);
212
213 printf("Op , Special ,Dim, Format ,MS,Layout, Fill , Box ,"
214 " small , small , small , small , LARGE , LARGE , LARGE , LARGE\n");
215 printf("--------,----------,---,-------------------,--,------,------------,-------------,"
216 " Default , Gfx , Compute , Special , Default , Gfx , Compute , Special\n");
217
218 for (unsigned test_flavor = 0; test_flavor < NUM_TESTS; test_flavor++) {
219 for (unsigned dim = 1; dim <= 3; dim++) {
220 for (unsigned format_index = 0; format_index < ARRAY_SIZE(formats); format_index++) {
221 for (unsigned samples = 1; samples <= 8; samples *= 2) {
222 for (unsigned layout = 0; layout < NUM_LAYOUTS; layout++) {
223 /* Reject invalid combinations. */
224 if (samples >= 2 && (dim != 2 || layout != LAYOUT_T2T))
225 continue;
226
227 if (dim == 1 && layout != LAYOUT_L2L)
228 continue;
229
230 if (test_flavor != TEST_COPY &&
231 (layout == LAYOUT_L2T || layout == LAYOUT_T2L))
232 continue;
233
234 if (test_flavor != TEST_COPY && dim != 1 &&
235 layout != LAYOUT_T2T)
236 continue;
237
238 if (test_flavor == TEST_RESOLVE && samples == 1)
239 continue;
240
241 if (test_flavor == TEST_RESOLVE &&
242 util_format_is_pure_integer(formats[format_index]))
243 continue;
244
245 /* Create textures. */
246 struct pipe_resource *src[2] = {0}, *dst[2] = {0};
247 const struct pipe_resource templ = {
248 .array_size = 1,
249 .format = formats[format_index],
250 .target = PIPE_TEXTURE_1D + dim - 1,
251 .usage = PIPE_USAGE_DEFAULT,
252 };
253
254 unsigned bpe = util_format_get_blocksize(templ.format);
255 unsigned pix_size = bpe * samples;
256
257 /* TODOs:
258 * CS:
259 * - optimize for gfx10.3
260 * - move the compute blit to amd/common
261 */
262
263 for (unsigned size_factor = 0; size_factor <= 1; size_factor++) {
264 unsigned mb_size = (size_factor ? 256 : 8) * 1024 * 1024;
265 unsigned width = 1, height = 1, depth = 1;
266
267 /* Determine the size. The footprint must be exactly "mb_size" for 2D and 3D. */
268 if (dim == 1) {
269 width = size_factor ? 16384 : 2048;
270 } else if (dim == 2) {
271 width = height = util_next_power_of_two(sqrt(mb_size / pix_size));
272
273 for (unsigned i = 0; width * height * pix_size != mb_size; i++) {
274 if (i % 2 == 1)
275 width /= 2;
276 else
277 height /= 2;
278 }
279 } else if (dim == 3) {
280 width = height = depth = util_next_power_of_two(pow(mb_size / pix_size, 0.333333));
281
282 for (unsigned i = 0; width * height * depth * pix_size != mb_size; i++) {
283 if (i % 3 == 2)
284 width /= 2;
285 else if (i % 3 == 1)
286 height /= 2;
287 else
288 depth /= 2;
289 }
290 }
291
292 struct pipe_resource src_templ = templ;
293 src_templ.width0 = MIN2(width, 16384);
294 src_templ.height0 = MIN2(height, 16384);
295 src_templ.depth0 = MIN2(depth, 16384);
296 src_templ.nr_samples = src_templ.nr_storage_samples = samples;
297 src_templ.bind = layout == LAYOUT_L2L ||
298 layout == LAYOUT_L2T ? PIPE_BIND_LINEAR : 0;
299
300 if (test_flavor != TEST_FB_CLEAR && test_flavor != TEST_CLEAR)
301 src[size_factor] = screen->resource_create(screen, &src_templ);
302
303 struct pipe_resource dst_templ = src_templ;
304 dst_templ.bind = layout == LAYOUT_L2L ||
305 layout == LAYOUT_T2L ? PIPE_BIND_LINEAR : 0;
306 if (test_flavor == TEST_RESOLVE)
307 dst_templ.nr_samples = dst_templ.nr_storage_samples = 1;
308
309 dst[size_factor] = screen->resource_create(screen, &dst_templ);
310 }
311
312 for (unsigned fill_flavor = 0; fill_flavor < NUM_FILLS; fill_flavor++) {
313 const union pipe_color_union *clear_color =
314 util_format_is_pure_integer(templ.format) ?
315 (fill_flavor == FILL_BLACK ? &black_color_uint : &solid_color_uint) :
316 (fill_flavor == FILL_BLACK ? &black_color_float : &solid_color_float);
317
318 /* Reject invalid combinations. */
319 if ((test_flavor == TEST_FB_CLEAR || test_flavor == TEST_CLEAR) &&
320 fill_flavor != FILL_SOLID && fill_flavor != FILL_BLACK)
321 continue;
322
323 if ((samples == 1 && fill_flavor >= FILL_RANDOM_FRAGMENTED2) ||
324 (samples == 2 && fill_flavor >= FILL_RANDOM_FRAGMENTED4) ||
325 (samples == 4 && fill_flavor >= FILL_RANDOM_FRAGMENTED8))
326 continue;
327
328 /* Fill the source texture. */
329 if (test_flavor != TEST_FB_CLEAR && test_flavor != TEST_CLEAR) {
330 for (unsigned size_factor = 0; size_factor <= 1; size_factor++) {
331 switch (fill_flavor) {
332 case FILL_BLACK:
333 case FILL_SOLID: {
334 union util_color packed_color;
335 util_pack_color(clear_color->f, templ.format, &packed_color);
336
337 struct pipe_box box = {0};
338 box.width = src[size_factor]->width0;
339 box.height = src[size_factor]->height0;
340 box.depth = src[size_factor]->depth0;
341
342 ctx->clear_texture(ctx, src[size_factor], 0, &box, &packed_color);
343 break;
344 }
345
346 case FILL_GRADIENT:
347 set_gradient_pixels(ctx, src[size_factor]);
348 break;
349
350 case FILL_RANDOM:
351 set_random_pixels(ctx, src[size_factor], 0, random_data);
352 break;
353
354 case FILL_RANDOM_FRAGMENTED2:
355 assert(samples >= 2);
356 /* Make all samples equal. */
357 set_random_pixels(ctx, src[size_factor], 0, random_data);
358 /* Make sample 0 different. */
359 set_random_pixels(ctx, src[size_factor], 1, random_data);
360 break;
361
362 case FILL_RANDOM_FRAGMENTED4:
363 assert(samples >= 4);
364 /* Make all samples equal. */
365 set_random_pixels(ctx, src[size_factor], 0, random_data);
366 /* Make samples 0..2 different. */
367 for (unsigned i = 0; i <= 2; i++)
368 set_random_pixels(ctx, src[size_factor], i + 1, random_data);
369 break;
370
371 case FILL_RANDOM_FRAGMENTED8:
372 assert(samples == 8);
373 /* Make all samples equal. */
374 set_random_pixels(ctx, src[size_factor], 0, random_data);
375 /* Make samples 0..6 different. */
376 for (unsigned i = 0; i <= 6; i++)
377 set_random_pixels(ctx, src[size_factor], i + 1, random_data);
378 break;
379 }
380 }
381 }
382
383 for (unsigned box_flavor = 0; box_flavor < NUM_BOXES; box_flavor++) {
384 bool yflip = box_flavor == BOX_FULL_YFLIP ||
385 box_flavor == BOX_PARTIAL_UNALIGNED_YFLIP;
386
387 /* Reject invalid combinations. */
388 if (test_flavor == TEST_FB_CLEAR && box_flavor != BOX_FULL)
389 continue;
390
391 if ((test_flavor == TEST_CLEAR || test_flavor == TEST_COPY) && yflip)
392 continue;
393
394 const char *special_op =
395 test_flavor == TEST_FB_CLEAR ? "cleartex" :
396 test_flavor == TEST_CLEAR && box_flavor == BOX_FULL ? "fastclear" :
397 test_flavor == TEST_BLIT && !yflip ? "copy" :
398 test_flavor == TEST_RESOLVE ? "cbresolve" : "n/a";
399
400 printf("%-8s, %-9s, %uD, %-18s, %u, %-5s, %-11s, %-11s",
401 test_strings[test_flavor], special_op, dim,
402 util_format_short_name(formats[format_index]), samples,
403 layout_strings[layout], fill_strings[fill_flavor],
404 box_strings[box_flavor]);
405
406 for (unsigned size_factor = 0; size_factor <= 1; size_factor++) {
407 /* Determine the box. */
408 struct pipe_box src_box = {0}, dst_box = {0};
409 dst_box.width = dst[size_factor]->width0;
410 dst_box.height = dst[size_factor]->height0;
411 dst_box.depth = dst[size_factor]->depth0;
412 src_box = dst_box;
413
414 switch (box_flavor) {
415 case BOX_FULL:
416 break;
417
418 case BOX_FULL_YFLIP:
419 src_box.y = src_box.height;
420 src_box.height = -src_box.height;
421 break;
422
423 case BOX_PARTIAL:
424 if (dim == 1) {
425 dst_box.x = 256;
426 dst_box.width -= 256;
427 } else if (dim == 2) {
428 dst_box.x = 16;
429 dst_box.y = 16;
430 dst_box.width -= 16;
431 dst_box.height -= 16;
432 } else {
433 dst_box.x = 8;
434 dst_box.y = 8;
435 dst_box.z = 8;
436 dst_box.width -= 8;
437 dst_box.height -= 8;
438 dst_box.depth -= 8;
439 }
440 src_box = dst_box;
441 break;
442
443 case BOX_PARTIAL_UNALIGNED:
444 case BOX_PARTIAL_UNALIGNED_YFLIP: {
445 const unsigned off = 13;
446 dst_box.x = off;
447 dst_box.width -= off;
448 if (dim >= 2) {
449 dst_box.y = off;
450 dst_box.height -= off;
451 if (dim == 3) {
452 dst_box.z = off;
453 dst_box.depth -= off;
454 }
455 }
456 src_box = dst_box;
457
458 if (box_flavor == BOX_PARTIAL_UNALIGNED_YFLIP) {
459 src_box.y += src_box.height;
460 src_box.height = -src_box.height;
461 }
462 break;
463 }
464 }
465
466 assert(dst_box.x >= 0);
467 assert(dst_box.y >= 0);
468 assert(dst_box.z >= 0);
469 assert(dst_box.width > 0);
470 assert(dst_box.height > 0);
471 assert(dst_box.depth > 0);
472 assert(dst_box.x + dst_box.width <= dst[size_factor]->width0);
473 assert(dst_box.y + dst_box.height <= dst[size_factor]->height0);
474 assert(dst_box.z + dst_box.depth <= dst[size_factor]->depth0);
475
476 if (src[size_factor]) {
477 assert(src_box.width);
478 assert(src_box.height);
479 assert(src_box.depth > 0);
480 if (src_box.width > 0) {
481 assert(src_box.x >= 0);
482 assert(src_box.x + src_box.width <= src[size_factor]->width0);
483 } else {
484 assert(src_box.x + src_box.width >= 0);
485 assert(src_box.x - 1 < src[size_factor]->width0);
486 }
487 if (src_box.height > 0) {
488 assert(src_box.y >= 0);
489 assert(src_box.y + src_box.height <= src[size_factor]->height0);
490 } else {
491 assert(src_box.y + src_box.height >= 0);
492 assert(src_box.y - 1 < src[size_factor]->height0);
493 }
494 assert(src_box.z >= 0);
495 assert(src_box.z + src_box.depth <= src[size_factor]->depth0);
496 }
497
498 for (unsigned method = 0; method < NUM_METHODS; method++) {
499 struct pipe_surface *dst_surf = NULL;
500
501 /* Create pipe_surface for clears. */
502 if (test_flavor == TEST_FB_CLEAR || test_flavor == TEST_CLEAR) {
503 struct pipe_surface surf_templ;
504
505 u_surface_default_template(&surf_templ, dst[size_factor]);
506 surf_templ.u.tex.last_layer = dst[size_factor]->depth0 - 1;
507 dst_surf = ctx->create_surface(ctx, dst[size_factor], &surf_templ);
508
509 /* Bind the colorbuffer for FB clears. */
510 if (box_flavor == BOX_FULL) {
511 struct pipe_framebuffer_state fb = {0};
512 fb.width = dst[size_factor]->width0;
513 fb.height = dst[size_factor]->height0;
514 fb.layers = dst[size_factor]->depth0;
515 fb.samples = dst[size_factor]->nr_samples;
516 fb.nr_cbufs = 1;
517 fb.cbufs[0] = dst_surf;
518 ctx->set_framebuffer_state(ctx, &fb);
519 si_emit_barrier_direct(sctx);
520 }
521 }
522
523 struct pipe_query *q = ctx->create_query(ctx, PIPE_QUERY_TIME_ELAPSED, 0);
524 unsigned num_warmup_repeats = 1, num_repeats = 4;
525 bool success = true;
526
527 /* Run tests. */
528 for (unsigned i = 0; i < num_warmup_repeats + num_repeats; i++) {
529 /* The first few just warm up caches and the hw. */
530 if (i == num_warmup_repeats)
531 ctx->begin_query(ctx, q);
532
533 switch (test_flavor) {
534 case TEST_FB_CLEAR:
535 case TEST_CLEAR:
536 switch (method) {
537 case METHOD_DEFAULT:
538 if (test_flavor == TEST_FB_CLEAR) {
539 ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, clear_color, 0, 0);
540 sctx->barrier_flags |= SI_BARRIER_SYNC_AND_INV_CB | SI_BARRIER_INV_L2;
541 } else {
542 ctx->clear_render_target(ctx, dst_surf, clear_color,
543 dst_box.x, dst_box.y,
544 dst_box.width, dst_box.height,
545 false);
546 }
547 break;
548 case METHOD_GFX:
549 si_gfx_clear_render_target(ctx, dst_surf, clear_color,
550 dst_box.x, dst_box.y,
551 dst_box.width, dst_box.height,
552 false);
553 break;
554 case METHOD_COMPUTE:
555 success &=
556 si_compute_clear_image(sctx, dst_surf->texture,
557 dst_surf->format, 0, &dst_box,
558 clear_color, false, false);
559 break;
560 case METHOD_SPECIAL:
561 if (test_flavor == TEST_CLEAR) {
562 success &=
563 si_compute_fast_clear_image(sctx, dst_surf->texture,
564 dst_surf->format, 0,
565 &dst_box, clear_color,
566 false, false);
567 } else {
568 ctx->clear_render_target(ctx, dst_surf, clear_color,
569 dst_box.x, dst_box.y,
570 dst_box.width, dst_box.height,
571 false);
572 }
573 break;
574 }
575 break;
576
577 case TEST_COPY:
578 switch (method) {
579 case METHOD_DEFAULT:
580 si_resource_copy_region(ctx, dst[size_factor], 0, dst_box.x,
581 dst_box.y, dst_box.z, src[size_factor],
582 0, &src_box);
583 break;
584 case METHOD_GFX:
585 si_gfx_copy_image(sctx, dst[size_factor], 0, dst_box.x,
586 dst_box.y, dst_box.z, src[size_factor],
587 0, &src_box);
588 break;
589 case METHOD_COMPUTE:
590 success &= si_compute_copy_image(sctx, dst[size_factor], 0,
591 src[size_factor], 0,
592 dst_box.x, dst_box.y,
593 dst_box.z, &src_box, false);
594 break;
595 case METHOD_SPECIAL:
596 success = false;
597 break;
598 }
599 break;
600
601 case TEST_BLIT:
602 case TEST_RESOLVE: {
603 struct pipe_blit_info info;
604 memset(&info, 0, sizeof(info));
605 info.dst.resource = dst[size_factor];
606 info.dst.level = 0;
607 info.dst.box = dst_box;
608 info.dst.format = templ.format;
609 info.src.resource = src[size_factor];
610 info.src.level = 0;
611 info.src.box = src_box;
612 info.src.format = templ.format;
613 info.mask = PIPE_MASK_RGBA;
614
615 switch (method) {
616 case METHOD_DEFAULT:
617 ctx->blit(ctx, &info);
618 break;
619 case METHOD_GFX:
620 si_gfx_blit(ctx, &info);
621 break;
622 case METHOD_COMPUTE:
623 success &= si_compute_blit(sctx, &info, NULL, 0, 0, false);
624 break;
625 case METHOD_SPECIAL:
626 if (test_flavor == TEST_BLIT && !yflip) {
627 si_resource_copy_region(ctx, dst[size_factor], 0, dst_box.x,
628 dst_box.y, dst_box.z, src[size_factor],
629 0, &src_box);
630 } else if (test_flavor == TEST_RESOLVE) {
631 success &= si_msaa_resolve_blit_via_CB(ctx, &info, false);
632 } else {
633 success = false;
634 }
635 break;
636 }
637 break;
638 }
639 }
640 }
641
642 /* Wait for idle after all tests. */
643 sctx->barrier_flags |= SI_BARRIER_SYNC_AND_INV_CB |
644 SI_BARRIER_SYNC_CS |
645 SI_BARRIER_INV_L2 | SI_BARRIER_INV_SMEM |
646 SI_BARRIER_INV_VMEM;
647 si_emit_barrier_direct(sctx);
648
649 ctx->end_query(ctx, q);
650 pipe_surface_reference(&dst_surf, NULL);
651
652 /* Unbind the colorbuffer. */
653 if ((test_flavor == TEST_FB_CLEAR || test_flavor == TEST_CLEAR) &&
654 box_flavor == BOX_FULL) {
655 struct pipe_framebuffer_state fb = {0};
656 fb.width = 64;
657 fb.height = 64;
658 fb.layers = 1;
659 fb.samples = 1;
660 ctx->set_framebuffer_state(ctx, &fb);
661 }
662
663 /* Get results. */
664 if (success) {
665 union pipe_query_result result;
666 ctx->get_query_result(ctx, q, true, &result);
667 ctx->destroy_query(ctx, q);
668
669 double sec = (double)result.u64 / (1000 * 1000 * 1000);
670 uint64_t pixels_per_surf = num_repeats * dst_box.width *
671 dst_box.height * dst_box.depth;
672 uint64_t bytes;
673
674 if (test_flavor == TEST_FB_CLEAR || test_flavor == TEST_CLEAR)
675 bytes = pixels_per_surf * pix_size;
676 else if (test_flavor == TEST_RESOLVE)
677 bytes = pixels_per_surf * (pix_size + bpe);
678 else
679 bytes = pixels_per_surf * pix_size * 2;
680
681 double bytes_per_sec = bytes / sec;
682
683 printf(" , %9.2f", bytes_per_sec / (1024 * 1024 * 1024));
684 } else {
685 printf(" , n/a ");
686 }
687 }
688 }
689
690 printf("\n");
691 }
692 }
693
694 for (unsigned size_factor = 0; size_factor <= 1; size_factor++) {
695 pipe_resource_reference(&dst[size_factor], NULL);
696 pipe_resource_reference(&src[size_factor], NULL);
697 }
698 }
699 }
700 }
701 }
702 }
703
704 ctx->destroy(ctx);
705 exit(0);
706 }
707