Path: blob/21.2-virgl/src/amd/common/ac_surface_modifier_test.c
7136 views
/* Make the test not meaningless when asserts are disabled. */1#undef NDEBUG23#include <assert.h>4#include <inttypes.h>5#include <stdio.h>6#include <stdlib.h>78#include <amdgpu.h>9#include "drm-uapi/amdgpu_drm.h"10#include "drm-uapi/drm_fourcc.h"1112#include "ac_surface.h"13#include "util/macros.h"14#include "util/u_math.h"15#include "util/u_vector.h"16#include "util/mesa-sha1.h"17#include "addrlib/inc/addrinterface.h"1819#include "ac_surface_test_common.h"2021/*22* The main goal of this test is making sure that we do23* not change the meaning of existing modifiers.24*/2526struct test_entry {27/* key part */28uint64_t modifier;29unsigned w;30unsigned h;31enum pipe_format format;3233/* debug info */34const char *name;35uint8_t pipes;36uint8_t rb;37uint8_t banks_or_pkrs;38uint8_t se;3940/* value to determine uniqueness */41unsigned char hash[20];4243/* u_vector requires power of two sizing */44char padding[sizeof(void*) == 8 ? 8 : 16];45};4647static uint64_t48block_count(unsigned w, unsigned h, unsigned elem_bits, unsigned block_bits,49unsigned *aligned_pitch, unsigned *aligned_height)50{51unsigned align_bits = block_bits - elem_bits;52unsigned w_align = 1 << (align_bits / 2 + align_bits % 2);53unsigned h_align = 1 << (align_bits / 2);5455w = align(w, w_align);56h = align(h, h_align);5758if (aligned_pitch)59*aligned_pitch = w;6061if (aligned_height)62*aligned_height = h;63return ((uint64_t)w * h) >> align_bits;64}656667static ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT68get_addr_from_coord_base(ADDR_HANDLE addrlib, const struct radeon_surf *surf,69unsigned w, unsigned h, enum pipe_format format,70bool rb_aligned, bool pipe_aligned)71{72ADDR2_COMPUTE_DCCINFO_INPUT din = {0};73ADDR2_COMPUTE_DCCINFO_OUTPUT dout = {0};74din.size = sizeof(ADDR2_COMPUTE_DCCINFO_INPUT);75dout.size = sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT);7677din.swizzleMode = surf->u.gfx9.swizzle_mode;78din.resourceType = ADDR_RSRC_TEX_2D;79din.bpp = util_format_get_blocksizebits(format);80din.unalignedWidth = w;81din.unalignedHeight = h;82din.numSlices = 1;83din.numMipLevels = 1;84din.numFrags = 1;85din.dccKeyFlags.pipeAligned = surf->u.gfx9.color.dcc.pipe_aligned;86din.dccKeyFlags.rbAligned = surf->u.gfx9.color.dcc.rb_aligned;87din.dataSurfaceSize = surf->surf_size;8889ADDR_E_RETURNCODE ret = Addr2ComputeDccInfo(addrlib, &din, &dout);90assert(ret == ADDR_OK);9192ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT dcc_input = {0};93dcc_input.size = sizeof(dcc_input);94dcc_input.swizzleMode = surf->u.gfx9.swizzle_mode;95dcc_input.resourceType = ADDR_RSRC_TEX_2D;96dcc_input.bpp = din.bpp;97dcc_input.numSlices = 1;98dcc_input.numMipLevels = 1;99dcc_input.numFrags = 1;100dcc_input.dccKeyFlags.pipeAligned = pipe_aligned;101dcc_input.dccKeyFlags.rbAligned = rb_aligned;102dcc_input.pitch = dout.pitch;103dcc_input.height = dout.height;104dcc_input.compressBlkWidth = dout.compressBlkWidth;105dcc_input.compressBlkHeight = dout.compressBlkHeight;106dcc_input.compressBlkDepth = dout.compressBlkDepth;107dcc_input.metaBlkWidth = dout.metaBlkWidth;108dcc_input.metaBlkHeight = dout.metaBlkHeight;109dcc_input.metaBlkDepth = dout.metaBlkDepth;110return dcc_input;111}112113static114void generate_hash(struct ac_addrlib *ac_addrlib,115struct test_entry *entry,116const struct radeon_surf *surf)117{118ADDR_HANDLE addrlib = ac_addrlib_get_handle(ac_addrlib);119120srandom(53);121struct mesa_sha1 ctx;122_mesa_sha1_init(&ctx);123124_mesa_sha1_update(&ctx, &surf->total_size, sizeof(surf->total_size));125_mesa_sha1_update(&ctx, &surf->meta_offset, sizeof(surf->meta_offset));126_mesa_sha1_update(&ctx, &surf->display_dcc_offset, sizeof(surf->display_dcc_offset));127_mesa_sha1_update(&ctx, &surf->u.gfx9.color.display_dcc_pitch_max,128sizeof(surf->u.gfx9.color.display_dcc_pitch_max));129130ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT input = {0};131input.size = sizeof(input);132input.swizzleMode = surf->u.gfx9.swizzle_mode;133input.resourceType = ADDR_RSRC_TEX_2D;134input.bpp = util_format_get_blocksizebits(entry->format);135input.unalignedWidth = entry->w;136input.unalignedHeight = entry->h;137input.numSlices = 1;138input.numMipLevels = 1;139input.numSamples = 1;140input.numFrags = 1;141input.pitchInElement = surf->u.gfx9.surf_pitch;142143ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT dcc_input = {0};144if (surf->meta_offset) {145dcc_input = get_addr_from_coord_base(addrlib, surf, entry->w,146entry->h, entry->format,147surf->u.gfx9.color.dcc.rb_aligned,148surf->u.gfx9.color.dcc.pipe_aligned);149}150151ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT display_dcc_input = {0};152if (surf->display_dcc_offset) {153display_dcc_input = get_addr_from_coord_base(addrlib, surf, entry->w,154entry->h, entry->format,155false, false);156}157158for (unsigned i = 0; i < 1000; ++i) {159int32_t x, y;160x = random();161y = random();162163input.x = (x & INT_MAX) % entry->w;164input.y = (y & INT_MAX) % entry->h;165166ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT output = {0};167output.size = sizeof(output);168169ADDR_E_RETURNCODE ret = Addr2ComputeSurfaceAddrFromCoord(addrlib, &input, &output);170assert(ret == ADDR_OK);171172_mesa_sha1_update(&ctx, &output.addr, sizeof(output.addr));173174if (surf->meta_offset) {175dcc_input.x = (x & INT_MAX) % entry->w;176dcc_input.y = (y & INT_MAX) % entry->h;177178ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT dcc_output = {0};179dcc_output.size = sizeof(dcc_output);180181ret = Addr2ComputeDccAddrFromCoord(addrlib, &dcc_input, &dcc_output);182assert(ret == ADDR_OK);183184_mesa_sha1_update(&ctx, &dcc_output.addr, sizeof(dcc_output.addr));185}186187if (surf->display_dcc_offset) {188display_dcc_input.x = (x & INT_MAX) % entry->w;189display_dcc_input.y = (y & INT_MAX) % entry->h;190191ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT dcc_output = {0};192dcc_output.size = sizeof(dcc_output);193194ret = Addr2ComputeDccAddrFromCoord(addrlib, &display_dcc_input, &dcc_output);195assert(ret == ADDR_OK);196197_mesa_sha1_update(&ctx, &dcc_output.addr, sizeof(dcc_output.addr));198}199}200201_mesa_sha1_final(&ctx, entry->hash);202}203204static void test_modifier(const struct radeon_info *info,205const char *name,206struct ac_addrlib *addrlib,207uint64_t modifier,208enum pipe_format format,209struct u_vector *test_entries)210{211unsigned elem_bits = util_logbase2(util_format_get_blocksize(format));212const unsigned dims[][2] = {213{1, 1},214{1920, 1080},215{1366, 768},216{3840, 2160},217{233, 938},218};219for (unsigned i = 0; i < ARRAY_SIZE(dims); ++i) {220struct ac_surf_config config = (struct ac_surf_config) {221.info = (struct ac_surf_info) {222.width = dims[i][0],223.height = dims[i][1],224.depth = 1,225.samples = 1,226.storage_samples = 1,227.levels = 1,228.num_channels = 3,229.array_size = 1230},231};232233struct test_entry entry = {234.modifier = modifier,235.w = config.info.width,236.h = config.info.height,237.format = format,238.name = name,239.pipes = G_0098F8_NUM_PIPES(info->gb_addr_config),240.rb = G_0098F8_NUM_RB_PER_SE(info->gb_addr_config) +241G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config),242.se = G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config),243.banks_or_pkrs = info->chip_class >= GFX10 ?244(info->gb_addr_config) : G_0098F8_NUM_BANKS(info->gb_addr_config)245};246247struct radeon_surf surf = (struct radeon_surf) {248.blk_w = 1,249.blk_h = 1,250.bpe = util_format_get_blocksize(format),251.modifier = modifier,252};253254int r = ac_compute_surface(addrlib, info, &config, RADEON_SURF_MODE_2D, &surf);255assert(!r);256257assert(surf.cmask_offset == 0);258assert(surf.fmask_offset == 0);259260uint64_t surf_size;261unsigned aligned_pitch, aligned_height;262if (modifier != DRM_FORMAT_MOD_LINEAR) {263surf_size = block_count(dims[i][0], dims[i][1],264elem_bits, 16, &aligned_pitch,265&aligned_height) << 16;266} else {267aligned_pitch = align(dims[i][0], 256 / util_format_get_blocksize(format));268aligned_height = dims[i][1];269surf_size = align(dims[i][0] * util_format_get_blocksize(format), 256) * dims[i][1];270}271272273assert(surf.u.gfx9.surf_pitch == aligned_pitch);274assert(surf.u.gfx9.surf_height == aligned_height);275assert(surf.surf_size == surf_size);276uint64_t expected_offset = surf_size;277278if (ac_modifier_has_dcc_retile(modifier)) {279unsigned dcc_align = info->chip_class >= GFX10 ? 4096 : 65536;280unsigned dcc_pitch;281uint64_t dcc_size = block_count(dims[i][0], dims[i][1],282elem_bits, 20, &dcc_pitch,283NULL) << 12;284285assert(surf.u.gfx9.color.display_dcc_size == align(dcc_size, dcc_align));286assert(surf.u.gfx9.color.display_dcc_pitch_max + 1 == dcc_pitch);287assert(surf.display_dcc_offset == expected_offset);288289expected_offset += align(dcc_size, dcc_align);290} else291assert(!surf.display_dcc_offset);292293if (ac_modifier_has_dcc(modifier)) {294uint64_t dcc_align = 1;295unsigned block_bits;296if (info->chip_class >= GFX10) {297unsigned num_pipes = G_0098F8_NUM_PIPES(info->gb_addr_config);298if (info->chip_class == GFX10_3 &&299G_0098F8_NUM_PKRS(info->gb_addr_config) == num_pipes && num_pipes > 1)300++num_pipes;301block_bits = 16 +302num_pipes +303G_0098F8_PIPE_INTERLEAVE_SIZE_GFX9(info->gb_addr_config);304block_bits = MAX2(block_bits, 20);305dcc_align = MAX2(4096, 256 <<306(num_pipes +307G_0098F8_PIPE_INTERLEAVE_SIZE_GFX9(info->gb_addr_config)));308} else {309block_bits = 18 +310G_0098F8_NUM_RB_PER_SE(info->gb_addr_config) +311G_0098F8_NUM_SHADER_ENGINES_GFX9(info->gb_addr_config);312block_bits = MAX2(block_bits, 20);313dcc_align = 65536;314}315316expected_offset = align(expected_offset, dcc_align);317assert(surf.meta_offset == expected_offset);318319uint64_t dcc_size = block_count(dims[i][0], dims[i][1],320elem_bits, block_bits,321NULL, NULL) << (block_bits - 8);322dcc_size = align64(dcc_size, dcc_align);323assert(surf.meta_size == dcc_size);324325expected_offset += dcc_size;326} else327assert(!surf.meta_offset);328329assert(surf.total_size == expected_offset);330331generate_hash(addrlib, &entry, &surf);332*(struct test_entry*)u_vector_add(test_entries) = entry;333}334335}336337static void run_modifier_test(struct u_vector *test_entries, const char *name,338const struct radeon_info *info)339{340struct ac_addrlib *addrlib = ac_addrlib_create(info, NULL);341assert(addrlib);342343const struct ac_modifier_options options = {344.dcc = true,345.dcc_retile = true,346};347348enum pipe_format formats[] = {349PIPE_FORMAT_R8_UNORM,350PIPE_FORMAT_R16_UNORM,351PIPE_FORMAT_R32_FLOAT,352PIPE_FORMAT_R32G32_FLOAT,353PIPE_FORMAT_R32G32B32A32_FLOAT354};355for (unsigned j = 0; j < ARRAY_SIZE(formats); ++j) {356unsigned mod_count = 0;357ac_get_supported_modifiers(info, &options, formats[j], &mod_count, NULL);358359uint64_t *modifiers = malloc(sizeof(uint64_t) * mod_count);360ac_get_supported_modifiers(info, &options, formats[j], &mod_count, modifiers);361362for (unsigned i = 0; i < mod_count; ++i) {363test_modifier(info, name, addrlib, modifiers[i], formats[j], test_entries);364}365366free(modifiers);367}368ac_addrlib_destroy(addrlib);369}370371static int compare_test_entry(const void *a, const void *b)372{373return memcmp(a, b, sizeof(struct test_entry));374}375376static bool test_entry_key_equal(const struct test_entry *a, const struct test_entry *b)377{378return a->modifier == b->modifier && a->w == b->w && a->h == b->h && a->format == b->format;379}380381static bool test_entry_value_equal(const struct test_entry *a, const struct test_entry *b)382{383if (memcmp(a->hash, b->hash, sizeof(a->hash)))384return false;385return true;386}387388static void print_test_entry(const struct test_entry *e)389{390printf("%.16" PRIx64 " %.4d %.4d %.2d %s %d %d %d %d\n", e->modifier, e->w, e->h,391util_format_get_blocksize(e->format), e->name, e->pipes, e->rb, e->se, e->banks_or_pkrs);392}393394int main()395{396STATIC_ASSERT(sizeof(struct test_entry) == 64);397398struct u_vector test_entries;399u_vector_init(&test_entries, sizeof(struct test_entry), 4096);400401for (unsigned i = 0; i < ARRAY_SIZE(testcases); ++i) {402struct radeon_info info = get_radeon_info(&testcases[i]);403404run_modifier_test(&test_entries, testcases[i].name, &info);405}406407qsort(u_vector_tail(&test_entries),408u_vector_length(&test_entries),409sizeof(struct test_entry),410compare_test_entry);411412struct test_entry *cur, *prev = NULL, *prevprev = NULL;413bool mismatched_duplicates = false;414u_vector_foreach(cur, &test_entries) {415if (prev && test_entry_key_equal(cur, prev) &&416!test_entry_value_equal(cur, prev)) {417if (!prevprev || !test_entry_key_equal(prev, prevprev)) {418print_test_entry(prev);419}420print_test_entry(cur);421mismatched_duplicates = true;422}423prevprev = prev;424prev = cur;425}426assert(!mismatched_duplicates);427428u_vector_finish(&test_entries);429430return 0;431}432433434