ADDR_CREATE_OUTPUT addrCreateOutput = {0};
ADDR_REGISTER_VALUE regValue = {0};
ADDR_CREATE_FLAGS createFlags = {{0}};
- ADDR_GET_MAX_ALINGMENTS_OUTPUT addrGetMaxAlignmentsOutput = {0};
+ ADDR_GET_MAX_ALIGNMENTS_OUTPUT addrGetMaxAlignmentsOutput = {0};
ADDR_E_RETURNCODE addrRet;
addrCreateInput.size = sizeof(ADDR_CREATE_INPUT);
surf_level->dcc_fast_clear_size = AddrDccOut->dccFastClearSize;
else
surf_level->dcc_fast_clear_size = 0;
+
+ /* Compute the DCC slice size because addrlib doesn't
+ * provide this info. As DCC memory is linear (each
+ * slice is the same size) it's easy to compute.
+ */
+ surf->dcc_slice_size = AddrDccOut->dccRamSize / config->info.array_size;
+
+ /* For arrays, we have to compute the DCC info again
+ * with one slice size to get a correct fast clear
+ * size.
+ */
+ if (config->info.array_size > 1) {
+ AddrDccIn->colorSurfSize = AddrSurfInfoOut->sliceSize;
+ AddrDccIn->tileMode = AddrSurfInfoOut->tileMode;
+ AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo;
+ AddrDccIn->tileIndex = AddrSurfInfoOut->tileIndex;
+ AddrDccIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex;
+
+ ret = AddrComputeDccInfo(addrlib,
+ AddrDccIn, AddrDccOut);
+ if (ret == ADDR_OK) {
+ /* If the DCC memory isn't properly
+ * aligned, the data are interleaved
+ * accross slices.
+ */
+ if (AddrDccOut->dccRamSizeAligned)
+ surf_level->dcc_slice_fast_clear_size = AddrDccOut->dccFastClearSize;
+ else
+ surf_level->dcc_slice_fast_clear_size = 0;
+ }
+ } else {
+ surf_level->dcc_slice_fast_clear_size = surf_level->dcc_fast_clear_size;
+ }
}
}
- /* TC-compatible HTILE. */
+ /* HTILE. */
if (!is_stencil &&
AddrSurfInfoIn->flags.depth &&
surf_level->mode == RADEON_SURF_MODE_2D &&
- level == 0) {
+ level == 0 &&
+ !(surf->flags & RADEON_SURF_NO_HTILE)) {
AddrHtileIn->flags.tcCompatible = AddrSurfInfoIn->flags.tcCompatible;
AddrHtileIn->pitch = AddrSurfInfoOut->pitch;
AddrHtileIn->height = AddrSurfInfoOut->height;
unsigned num_pipes = info->num_tile_pipes;
unsigned cl_width, cl_height;
- if (surf->flags & RADEON_SURF_Z_OR_SBUFFER)
+ if (surf->flags & RADEON_SURF_Z_OR_SBUFFER ||
+ (config->info.samples >= 2 && !surf->fmask_size))
return;
assert(info->chip_class <= GFX8);
num_layers = config->info.array_size;
surf->cmask_alignment = MAX2(256, base_align);
- surf->cmask_size = align(slice_bytes, base_align) * num_layers;
+ surf->cmask_slice_size = align(slice_bytes, base_align);
+ surf->cmask_size = surf->cmask_slice_size * num_layers;
}
/**
*/
AddrSurfInfoIn.flags.dccCompatible =
info->chip_class >= GFX8 &&
+ info->has_graphics && /* disable DCC on compute-only chips */
!(surf->flags & RADEON_SURF_Z_OR_SBUFFER) &&
!(surf->flags & RADEON_SURF_DISABLE_DCC) &&
!compressed &&
}
/* Compute FMASK. */
- if (config->info.samples >= 2 && AddrSurfInfoIn.flags.color) {
+ if (config->info.samples >= 2 && AddrSurfInfoIn.flags.color &&
+ info->has_graphics && !(surf->flags & RADEON_SURF_NO_FMASK)) {
ADDR_COMPUTE_FMASK_INFO_INPUT fin = {0};
ADDR_COMPUTE_FMASK_INFO_OUTPUT fout = {0};
ADDR_TILEINFO fmask_tile_info = {};
/* TODO: We could allow some of these: */
sin.forbiddenBlock.micro = 1; /* don't allow the 256B swizzle modes */
sin.forbiddenBlock.var = 1; /* don't allow the variable-sized swizzle modes */
- sin.forbiddenBlock.linear = 1; /* don't allow linear swizzle modes */
sin.bpp = in->bpp;
sin.width = in->width;
sin.height = in->height;
return 0;
}
+static bool gfx9_is_dcc_capable(const struct radeon_info *info, unsigned sw_mode)
+{
+ if (info->chip_class >= GFX10)
+ return sw_mode == ADDR_SW_64KB_Z_X || sw_mode == ADDR_SW_64KB_R_X;
+
+ return sw_mode != ADDR_SW_LINEAR;
+}
+
static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
const struct radeon_info *info,
const struct ac_surf_config *config,
if (in->flags.depth) {
assert(in->swizzleMode != ADDR_SW_LINEAR);
+ if (surf->flags & RADEON_SURF_NO_HTILE)
+ return 0;
+
/* HTILE */
ADDR2_COMPUTE_HTILE_INFO_INPUT hin = {0};
ADDR2_COMPUTE_HTILE_INFO_OUTPUT hout = {0};
surf->htile_size = hout.htileBytes;
surf->htile_slice_size = hout.sliceSize;
surf->htile_alignment = hout.baseAlign;
- } else {
+ return 0;
+ }
+
+ {
/* Compute tile swizzle for the color surface.
* All *_X and *_T modes can use the swizzle.
*/
}
/* DCC */
- if (!(surf->flags & RADEON_SURF_DISABLE_DCC) &&
+ if (info->has_graphics &&
+ !(surf->flags & RADEON_SURF_DISABLE_DCC) &&
!compressed &&
- in->swizzleMode != ADDR_SW_LINEAR) {
+ gfx9_is_dcc_capable(info, in->swizzleMode)) {
ADDR2_COMPUTE_DCCINFO_INPUT din = {0};
ADDR2_COMPUTE_DCCINFO_OUTPUT dout = {0};
ADDR2_META_MIP_INFO meta_mip_info[RADEON_SURF_MAX_LEVELS] = {};
return ret;
surf->u.gfx9.dcc_retile_map[index * 2] = addrout.addr;
- if (addrout.addr > USHRT_MAX)
+ if (addrout.addr > UINT16_MAX)
surf->u.gfx9.dcc_retile_use_uint16 = false;
/* Compute dst DCC address */
return ret;
surf->u.gfx9.dcc_retile_map[index * 2 + 1] = addrout.addr;
- if (addrout.addr > USHRT_MAX)
+ if (addrout.addr > UINT16_MAX)
surf->u.gfx9.dcc_retile_use_uint16 = false;
assert(index * 2 + 1 < surf->u.gfx9.dcc_retile_num_elements);
}
/* FMASK */
- if (in->numSamples > 1) {
+ if (in->numSamples > 1 && info->has_graphics &&
+ !(surf->flags & RADEON_SURF_NO_FMASK)) {
ADDR2_COMPUTE_FMASK_INFO_INPUT fin = {0};
ADDR2_COMPUTE_FMASK_INFO_OUTPUT fout = {0};
}
}
- /* CMASK */
- if (in->swizzleMode != ADDR_SW_LINEAR) {
+ /* CMASK -- on GFX10 only for FMASK */
+ if (in->swizzleMode != ADDR_SW_LINEAR &&
+ ((info->chip_class <= GFX9 && in->numSamples == 1) ||
+ (surf->fmask_size && in->numSamples >= 2))) {
ADDR2_COMPUTE_CMASK_INFO_INPUT cin = {0};
ADDR2_COMPUTE_CMASK_INFO_OUTPUT cout = {0};
* must sample 1D textures as 2D. */
if (config->is_3d)
AddrSurfInfoIn.resourceType = ADDR_RSRC_TEX_3D;
+ else if (info->chip_class != GFX9 && config->is_1d)
+ AddrSurfInfoIn.resourceType = ADDR_RSRC_TEX_1D;
else
AddrSurfInfoIn.resourceType = ADDR_RSRC_TEX_2D;
case RADEON_SURF_MODE_1D:
case RADEON_SURF_MODE_2D:
- if (surf->flags & RADEON_SURF_IMPORTED) {
+ if (surf->flags & (RADEON_SURF_IMPORTED | RADEON_SURF_FORCE_SWIZZLE_MODE)) {
AddrSurfInfoIn.swizzleMode = surf->u.gfx9.surf.swizzle_mode;
break;
}
surf->micro_tile_mode = RADEON_MICRO_MODE_DISPLAY;
break;
- /* R = rotated. */
+ /* R = rotated (gfx9), render target (gfx10). */
case ADDR_SW_256B_R:
case ADDR_SW_4KB_R:
case ADDR_SW_64KB_R:
case ADDR_SW_64KB_R_X:
case ADDR_SW_VAR_R_X:
/* The rotated micro tile mode doesn't work if both CMASK and RB+ are
- * used at the same time. This case is not currently expected to occur
- * because we don't use rotated. Enforce this restriction on all chips
- * to facilitate testing.
+ * used at the same time. We currently do not use rotated
+ * in gfx9.
*/
- assert(!"rotate micro tile mode is unsupported");
- r = ADDR_ERROR;
- goto error;
+ assert(info->chip_class >= GFX10 ||
+ !"rotate micro tile mode is unsupported");
+ surf->micro_tile_mode = RADEON_MICRO_MODE_ROTATED;
+ break;
/* Z = depth. */
case ADDR_SW_4KB_Z:
return r;
if (info->chip_class >= GFX9)
- return gfx9_compute_surface(addrlib, info, config, mode, surf);
+ r = gfx9_compute_surface(addrlib, info, config, mode, surf);
else
- return gfx6_compute_surface(addrlib, info, config, mode, surf);
+ r = gfx6_compute_surface(addrlib, info, config, mode, surf);
+
+ if (r)
+ return r;
+
+ /* Determine the memory layout of multiple allocations in one buffer. */
+ surf->total_size = surf->surf_size;
+
+ if (surf->htile_size) {
+ surf->htile_offset = align64(surf->total_size, surf->htile_alignment);
+ surf->total_size = surf->htile_offset + surf->htile_size;
+ }
+
+ if (surf->fmask_size) {
+ assert(config->info.samples >= 2);
+ surf->fmask_offset = align64(surf->total_size, surf->fmask_alignment);
+ surf->total_size = surf->fmask_offset + surf->fmask_size;
+ }
+
+ /* Single-sample CMASK is in a separate buffer. */
+ if (surf->cmask_size && config->info.samples >= 2) {
+ surf->cmask_offset = align64(surf->total_size, surf->cmask_alignment);
+ surf->total_size = surf->cmask_offset + surf->cmask_size;
+ }
+
+ if (surf->dcc_size &&
+ (info->use_display_dcc_unaligned ||
+ info->use_display_dcc_with_retile_blit ||
+ !(surf->flags & RADEON_SURF_SCANOUT))) {
+ surf->dcc_offset = align64(surf->total_size, surf->dcc_alignment);
+ surf->total_size = surf->dcc_offset + surf->dcc_size;
+
+ if (info->chip_class >= GFX9 &&
+ surf->u.gfx9.dcc_retile_num_elements) {
+ /* Add space for the displayable DCC buffer. */
+ surf->display_dcc_offset =
+ align64(surf->total_size, surf->u.gfx9.display_dcc_alignment);
+ surf->total_size = surf->display_dcc_offset +
+ surf->u.gfx9.display_dcc_size;
+
+ /* Add space for the DCC retile buffer. (16-bit or 32-bit elements) */
+ surf->dcc_retile_map_offset =
+ align64(surf->total_size, info->tcc_cache_line_size);
+
+ if (surf->u.gfx9.dcc_retile_use_uint16) {
+ surf->total_size = surf->dcc_retile_map_offset +
+ surf->u.gfx9.dcc_retile_num_elements * 2;
+ } else {
+ surf->total_size = surf->dcc_retile_map_offset +
+ surf->u.gfx9.dcc_retile_num_elements * 4;
+ }
+ }
+ }
+
+ return 0;
}