xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/radeonsi/si_test_blit_perf.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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