From: Marek Olšák <marek.ol...@amd.com> --- src/amd/common/ac_surface.c | 85 +++++++++++++++++++++++++- src/amd/common/ac_surface.h | 6 +- src/gallium/drivers/radeon/r600_texture.c | 1 + src/gallium/winsys/amdgpu/drm/amdgpu_surface.c | 2 + 4 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c index 590920e..92bdf1d 100644 --- a/src/amd/common/ac_surface.c +++ b/src/amd/common/ac_surface.c @@ -842,20 +842,21 @@ gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib, ret = Addr2GetPreferredSurfaceSetting(addrlib, &sin, &sout); if (ret != ADDR_OK) return ret; *swizzle_mode = sout.swizzleMode; return 0; } static int gfx9_compute_miptree(ADDR_HANDLE addrlib, + const struct ac_surf_config *config, struct radeon_surf *surf, bool compressed, ADDR2_COMPUTE_SURFACE_INFO_INPUT *in) { ADDR2_MIP_INFO mip_info[RADEON_SURF_MAX_LEVELS] = {}; ADDR2_COMPUTE_SURFACE_INFO_OUTPUT out = {0}; ADDR_E_RETURNCODE ret; out.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT); out.pMipInfo = mip_info; @@ -916,20 +917,51 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib, ret = Addr2ComputeHtileInfo(addrlib, &hin, &hout); if (ret != ADDR_OK) return ret; surf->u.gfx9.htile.rb_aligned = hin.hTileFlags.rbAligned; surf->u.gfx9.htile.pipe_aligned = hin.hTileFlags.pipeAligned; surf->htile_size = hout.htileBytes; surf->htile_slice_size = hout.sliceSize; surf->htile_alignment = hout.baseAlign; } else { + /* Compute tile swizzle for the color surface. + * All *_X and *_T modes can use the swizzle. + */ + if (config->info.surf_index && + in->swizzleMode >= ADDR_SW_64KB_Z_T && + !out.mipChainInTail && + !(surf->flags & RADEON_SURF_SHAREABLE) && + (in->numSamples > 1 || !(surf->flags & RADEON_SURF_SCANOUT))) { + ADDR2_COMPUTE_PIPEBANKXOR_INPUT xin = {0}; + ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT xout = {0}; + + xin.size = sizeof(ADDR2_COMPUTE_PIPEBANKXOR_INPUT); + xout.size = sizeof(ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT); + + xin.surfIndex = p_atomic_inc_return(config->info.surf_index) - 1; + xin.flags = in->flags; + xin.swizzleMode = in->swizzleMode; + xin.resourceType = in->resourceType; + xin.format = in->format; + xin.numSamples = in->numSamples; + xin.numFrags = in->numFrags; + + ret = Addr2ComputePipeBankXor(addrlib, &xin, &xout); + if (ret != ADDR_OK) + return ret; + + assert(xout.pipeBankXor <= + u_bit_consecutive(0, sizeof(surf->tile_swizzle) * 8)); + surf->tile_swizzle = xout.pipeBankXor; + } + /* DCC */ if (!(surf->flags & RADEON_SURF_DISABLE_DCC) && !compressed && in->swizzleMode != ADDR_SW_LINEAR) { ADDR2_COMPUTE_DCCINFO_INPUT din = {0}; ADDR2_COMPUTE_DCCINFO_OUTPUT dout = {0}; ADDR2_META_MIP_INFO meta_mip_info[RADEON_SURF_MAX_LEVELS] = {}; din.size = sizeof(ADDR2_COMPUTE_DCCINFO_INPUT); dout.size = sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT); @@ -1011,20 +1043,48 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib, fin.numFrags = in->numFrags; ret = Addr2ComputeFmaskInfo(addrlib, &fin, &fout); if (ret != ADDR_OK) return ret; surf->u.gfx9.fmask.swizzle_mode = fin.swizzleMode; surf->u.gfx9.fmask.epitch = fout.pitch - 1; surf->u.gfx9.fmask_size = fout.fmaskBytes; surf->u.gfx9.fmask_alignment = fout.baseAlign; + + /* Compute tile swizzle for the FMASK surface. */ + if (config->info.fmask_surf_index && + fin.swizzleMode >= ADDR_SW_64KB_Z_T && + !(surf->flags & RADEON_SURF_SHAREABLE)) { + ADDR2_COMPUTE_PIPEBANKXOR_INPUT xin = {0}; + ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT xout = {0}; + + xin.size = sizeof(ADDR2_COMPUTE_PIPEBANKXOR_INPUT); + xout.size = sizeof(ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT); + + /* This counter starts from 1 instead of 0. */ + xin.surfIndex = p_atomic_inc_return(config->info.fmask_surf_index); + xin.flags = in->flags; + xin.swizzleMode = in->swizzleMode; + xin.resourceType = in->resourceType; + xin.format = in->format; + xin.numSamples = in->numSamples; + xin.numFrags = in->numFrags; + + ret = Addr2ComputePipeBankXor(addrlib, &xin, &xout); + if (ret != ADDR_OK) + return ret; + + assert(xout.pipeBankXor <= + u_bit_consecutive(0, sizeof(surf->u.gfx9.fmask_tile_swizzle) * 8)); + surf->u.gfx9.fmask_tile_swizzle = xout.pipeBankXor; + } } /* CMASK */ if (in->swizzleMode != ADDR_SW_LINEAR) { ADDR2_COMPUTE_CMASK_INFO_INPUT cin = {0}; ADDR2_COMPUTE_CMASK_INFO_OUTPUT cout = {0}; cin.size = sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT); cout.size = sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT); @@ -1077,20 +1137,39 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib, case 8: AddrSurfInfoIn.format = ADDR_FMT_BC1; break; case 16: AddrSurfInfoIn.format = ADDR_FMT_BC3; break; default: assert(0); } } else { + switch (surf->bpe) { + case 1: + AddrSurfInfoIn.format = ADDR_FMT_8; + break; + case 2: + AddrSurfInfoIn.format = ADDR_FMT_16; + break; + case 4: + AddrSurfInfoIn.format = ADDR_FMT_32; + break; + case 8: + AddrSurfInfoIn.format = ADDR_FMT_32_32; + break; + case 16: + AddrSurfInfoIn.format = ADDR_FMT_32_32_32_32; + break; + default: + assert(0); + } AddrSurfInfoIn.bpp = surf->bpe * 8; } AddrSurfInfoIn.flags.color = !(surf->flags & RADEON_SURF_Z_OR_SBUFFER); AddrSurfInfoIn.flags.depth = (surf->flags & RADEON_SURF_ZBUFFER) != 0; AddrSurfInfoIn.flags.display = (surf->flags & RADEON_SURF_SCANOUT) != 0; /* flags.texture currently refers to TC-compatible HTILE */ AddrSurfInfoIn.flags.texture = AddrSurfInfoIn.flags.color || surf->flags & RADEON_SURF_TC_COMPATIBLE_HTILE; AddrSurfInfoIn.flags.opt4space = 1; @@ -1148,38 +1227,40 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib, surf->surf_size = 0; surf->dcc_size = 0; surf->htile_size = 0; surf->htile_slice_size = 0; surf->u.gfx9.surf_offset = 0; surf->u.gfx9.stencil_offset = 0; surf->u.gfx9.fmask_size = 0; surf->u.gfx9.cmask_size = 0; /* Calculate texture layout information. */ - r = gfx9_compute_miptree(addrlib, surf, compressed, &AddrSurfInfoIn); + r = gfx9_compute_miptree(addrlib, config, surf, compressed, + &AddrSurfInfoIn); if (r) return r; /* Calculate texture layout information for stencil. */ if (surf->flags & RADEON_SURF_SBUFFER) { AddrSurfInfoIn.flags.stencil = 1; AddrSurfInfoIn.bpp = 8; if (!AddrSurfInfoIn.flags.depth) { r = gfx9_get_preferred_swizzle_mode(addrlib, &AddrSurfInfoIn, false, &AddrSurfInfoIn.swizzleMode); if (r) return r; } else AddrSurfInfoIn.flags.depth = 0; - r = gfx9_compute_miptree(addrlib, surf, compressed, &AddrSurfInfoIn); + r = gfx9_compute_miptree(addrlib, config, surf, compressed, + &AddrSurfInfoIn); if (r) return r; } surf->is_linear = surf->u.gfx9.surf.swizzle_mode == ADDR_SW_LINEAR; /* Query whether the surface is displayable. */ bool displayable = false; r = Addr2IsValidDisplaySwizzleMode(addrlib, surf->u.gfx9.surf.swizzle_mode, surf->bpe * 8, &displayable); diff --git a/src/amd/common/ac_surface.h b/src/amd/common/ac_surface.h index f18548f..71f320a 100644 --- a/src/amd/common/ac_surface.h +++ b/src/amd/common/ac_surface.h @@ -140,20 +140,22 @@ struct gfx9_surf_layout { uint32_t offset[RADEON_SURF_MAX_LEVELS]; uint16_t dcc_pitch_max; /* (mip chain pitch - 1) */ uint64_t stencil_offset; /* separate stencil */ uint64_t fmask_size; uint64_t cmask_size; uint32_t fmask_alignment; uint32_t cmask_alignment; + + uint8_t fmask_tile_swizzle; }; struct radeon_surf { /* Format properties. */ unsigned blk_w:4; unsigned blk_h:4; unsigned bpe:5; /* Number of mipmap levels where DCC is enabled starting from level 0. * Non-zero levels may be disabled due to alignment constraints, but not * the first level. @@ -168,21 +170,22 @@ struct radeon_surf { uint32_t flags; /* These are return values. Some of them can be set by the caller, but * they will be treated as hints (e.g. bankw, bankh) and might be * changed by the calculator. */ /* Tile swizzle can be OR'd with low bits of the BASE_256B address. * The value is the same for all mipmap levels. Supported tile modes: * - GFX6: Only macro tiling. - * - GFX9: Only *_X swizzle modes. Level 0 must not be in the mip tail. + * - GFX9: Only *_X and *_T swizzle modes. Level 0 must not be in the mip + * tail. * * Only these surfaces are allowed to set it: * - color (if it doesn't have to be displayable) * - DCC (same tile swizzle as color) * - FMASK * - CMASK if it's TC-compatible or if the gen is GFX9 * - depth/stencil if HTILE is not TC-compatible and if the gen is not GFX9 */ uint8_t tile_swizzle; @@ -211,20 +214,21 @@ struct radeon_surf { }; struct ac_surf_info { uint32_t width; uint32_t height; uint32_t depth; uint8_t samples; uint8_t levels; uint16_t array_size; uint32_t *surf_index; /* Set a monotonic counter for tile swizzling. */ + uint32_t *fmask_surf_index; /* GFX9+ */ }; struct ac_surf_config { struct ac_surf_info info; unsigned is_3d : 1; unsigned is_cube : 1; }; ADDR_HANDLE amdgpu_addr_create(const struct radeon_info *info, const struct amdgpu_gpu_info *amdinfo, diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c index 03bc955..1c4e9b7 100644 --- a/src/gallium/drivers/radeon/r600_texture.c +++ b/src/gallium/drivers/radeon/r600_texture.c @@ -833,20 +833,21 @@ void si_texture_get_fmask_info(struct si_screen *sscreen, /* FMASK is allocated like an ordinary texture. */ struct pipe_resource templ = rtex->resource.b.b; struct radeon_surf fmask = {}; unsigned flags, bpe; memset(out, 0, sizeof(*out)); if (sscreen->info.chip_class >= GFX9) { out->alignment = rtex->surface.u.gfx9.fmask_alignment; out->size = rtex->surface.u.gfx9.fmask_size; + out->tile_swizzle = rtex->surface.u.gfx9.fmask_tile_swizzle; return; } templ.nr_samples = 1; flags = rtex->surface.flags | RADEON_SURF_FMASK; switch (nr_samples) { case 2: case 4: bpe = 1; diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c index fabc6cc..fc5c9d5 100644 --- a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c +++ b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c @@ -93,17 +93,19 @@ static int amdgpu_surface_init(struct radeon_winsys *rws, * always use consecutive surface indices when FMASK is allocated between * them. */ if (flags & RADEON_SURF_FMASK) config.info.surf_index = &ws->surf_index_fmask; else if (!(flags & RADEON_SURF_Z_OR_SBUFFER)) config.info.surf_index = &ws->surf_index_color; else config.info.surf_index = NULL; + config.info.fmask_surf_index = &ws->surf_index_fmask; + return ac_compute_surface(ws->addrlib, &ws->info, &config, mode, surf); } void amdgpu_surface_init_functions(struct amdgpu_winsys *ws) { ws->base.surface_init = amdgpu_surface_init; } -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev