summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/amd/common/ac_surface.c85
-rw-r--r--src/amd/common/ac_surface.h6
-rw-r--r--src/gallium/drivers/radeon/r600_texture.c1
-rw-r--r--src/gallium/winsys/amdgpu/drm/amdgpu_surface.c2
4 files changed, 91 insertions, 3 deletions
diff --git a/src/amd/common/ac_surface.c b/src/amd/common/ac_surface.c
index 590920ee2b6..92bdf1dedec 100644
--- a/src/amd/common/ac_surface.c
+++ b/src/amd/common/ac_surface.c
@@ -849,6 +849,7 @@ gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib,
}
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)
{
@@ -923,6 +924,37 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
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 &&
@@ -1018,6 +1050,34 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
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 */
@@ -1084,6 +1144,25 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib,
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;
}
@@ -1155,7 +1234,8 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib,
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;
@@ -1172,7 +1252,8 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib,
} 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;
}
diff --git a/src/amd/common/ac_surface.h b/src/amd/common/ac_surface.h
index f18548f73e4..71f320af8ee 100644
--- a/src/amd/common/ac_surface.h
+++ b/src/amd/common/ac_surface.h
@@ -147,6 +147,8 @@ struct gfx9_surf_layout {
uint32_t fmask_alignment;
uint32_t cmask_alignment;
+
+ uint8_t fmask_tile_swizzle;
};
struct radeon_surf {
@@ -175,7 +177,8 @@ struct radeon_surf {
/* 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)
@@ -218,6 +221,7 @@ struct ac_surf_info {
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 {
diff --git a/src/gallium/drivers/radeon/r600_texture.c b/src/gallium/drivers/radeon/r600_texture.c
index 125e7ef4089..3a0a79187b8 100644
--- a/src/gallium/drivers/radeon/r600_texture.c
+++ b/src/gallium/drivers/radeon/r600_texture.c
@@ -848,6 +848,7 @@ void si_texture_get_fmask_info(struct si_screen *sscreen,
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;
}
diff --git a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
index fabc6ccd93b..fc5c9d5a127 100644
--- a/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
+++ b/src/gallium/winsys/amdgpu/drm/amdgpu_surface.c
@@ -100,6 +100,8 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
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);
}