static void surf_drm_to_winsys(struct radeon_drm_winsys *ws, struct radeon_surf *surf_ws, const struct radeon_surface *surf_drm) { int i; memset(surf_ws, 0, sizeof(*surf_ws)); surf_ws->blk_w = surf_drm->blk_w; surf_ws->blk_h = surf_drm->blk_h; surf_ws->bpe = surf_drm->bpe; surf_ws->is_linear = surf_drm->level[0].mode <= RADEON_SURF_MODE_LINEAR_ALIGNED; surf_ws->has_stencil = !!(surf_drm->flags & RADEON_SURF_SBUFFER); surf_ws->flags = surf_drm->flags; surf_ws->surf_size = surf_drm->bo_size; surf_ws->surf_alignment = surf_drm->bo_alignment; surf_ws->u.legacy.bankw = surf_drm->bankw; surf_ws->u.legacy.bankh = surf_drm->bankh; surf_ws->u.legacy.mtilea = surf_drm->mtilea; surf_ws->u.legacy.tile_split = surf_drm->tile_split; surf_ws->u.legacy.macro_tile_index = cik_get_macro_tile_index(surf_ws); for (i = 0; i <= surf_drm->last_level; i++) { surf_level_drm_to_winsys(&surf_ws->u.legacy.level[i], &surf_drm->level[i], surf_drm->bpe * surf_drm->nsamples); surf_ws->u.legacy.tiling_index[i] = surf_drm->tiling_index[i]; } if (surf_ws->flags & RADEON_SURF_SBUFFER) { surf_ws->u.legacy.stencil_tile_split = surf_drm->stencil_tile_split; for (i = 0; i <= surf_drm->last_level; i++) { surf_level_drm_to_winsys(&surf_ws->u.legacy.stencil_level[i], &surf_drm->stencil_level[i], surf_drm->nsamples); surf_ws->u.legacy.stencil_tiling_index[i] = surf_drm->stencil_tiling_index[i]; } } set_micro_tile_mode(surf_ws, &ws->info); surf_ws->is_displayable = surf_ws->is_linear || surf_ws->micro_tile_mode == RADEON_MICRO_MODE_DISPLAY || surf_ws->micro_tile_mode == RADEON_MICRO_MODE_ROTATED; }
static int amdgpu_surface_init(struct radeon_winsys *rws, const struct pipe_resource *tex, unsigned flags, unsigned bpe, enum radeon_surf_mode mode, struct radeon_surf *surf) { struct amdgpu_winsys *ws = (struct amdgpu_winsys*)rws; unsigned level; bool compressed; ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn = {0}; ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut = {0}; ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn = {0}; ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut = {0}; ADDR_COMPUTE_HTILE_INFO_INPUT AddrHtileIn = {0}; ADDR_COMPUTE_HTILE_INFO_OUTPUT AddrHtileOut = {0}; ADDR_TILEINFO AddrTileInfoIn = {0}; ADDR_TILEINFO AddrTileInfoOut = {0}; int r; r = amdgpu_surface_sanity(tex); if (r) return r; AddrSurfInfoIn.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT); AddrSurfInfoOut.size = sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT); AddrDccIn.size = sizeof(ADDR_COMPUTE_DCCINFO_INPUT); AddrDccOut.size = sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT); AddrHtileIn.size = sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT); AddrHtileOut.size = sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT); AddrSurfInfoOut.pTileInfo = &AddrTileInfoOut; surf->blk_w = util_format_get_blockwidth(tex->format); surf->blk_h = util_format_get_blockheight(tex->format); surf->bpe = bpe; surf->flags = flags; compressed = surf->blk_w == 4 && surf->blk_h == 4; /* MSAA and FMASK require 2D tiling. */ if (tex->nr_samples > 1 || (flags & RADEON_SURF_FMASK)) mode = RADEON_SURF_MODE_2D; /* DB doesn't support linear layouts. */ if (flags & (RADEON_SURF_Z_OR_SBUFFER) && mode < RADEON_SURF_MODE_1D) mode = RADEON_SURF_MODE_1D; /* Set the requested tiling mode. */ switch (mode) { case RADEON_SURF_MODE_LINEAR_ALIGNED: AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_ALIGNED; break; case RADEON_SURF_MODE_1D: AddrSurfInfoIn.tileMode = ADDR_TM_1D_TILED_THIN1; break; case RADEON_SURF_MODE_2D: AddrSurfInfoIn.tileMode = ADDR_TM_2D_TILED_THIN1; break; default: assert(0); } /* The format must be set correctly for the allocation of compressed * textures to work. In other cases, setting the bpp is sufficient. */ if (compressed) { switch (bpe) { case 8: AddrSurfInfoIn.format = ADDR_FMT_BC1; break; case 16: AddrSurfInfoIn.format = ADDR_FMT_BC3; break; default: assert(0); } } else { AddrDccIn.bpp = AddrSurfInfoIn.bpp = bpe * 8; } AddrDccIn.numSamples = AddrSurfInfoIn.numSamples = tex->nr_samples ? tex->nr_samples : 1; AddrSurfInfoIn.tileIndex = -1; /* Set the micro tile type. */ if (flags & RADEON_SURF_SCANOUT) AddrSurfInfoIn.tileType = ADDR_DISPLAYABLE; else if (flags & (RADEON_SURF_Z_OR_SBUFFER | RADEON_SURF_FMASK)) AddrSurfInfoIn.tileType = ADDR_DEPTH_SAMPLE_ORDER; else AddrSurfInfoIn.tileType = ADDR_NON_DISPLAYABLE; AddrSurfInfoIn.flags.color = !(flags & RADEON_SURF_Z_OR_SBUFFER); AddrSurfInfoIn.flags.depth = (flags & RADEON_SURF_ZBUFFER) != 0; AddrSurfInfoIn.flags.cube = tex->target == PIPE_TEXTURE_CUBE; AddrSurfInfoIn.flags.fmask = (flags & RADEON_SURF_FMASK) != 0; AddrSurfInfoIn.flags.display = (flags & RADEON_SURF_SCANOUT) != 0; AddrSurfInfoIn.flags.pow2Pad = tex->last_level > 0; AddrSurfInfoIn.flags.tcCompatible = (flags & RADEON_SURF_TC_COMPATIBLE_HTILE) != 0; /* Only degrade the tile mode for space if TC-compatible HTILE hasn't been * requested, because TC-compatible HTILE requires 2D tiling. */ AddrSurfInfoIn.flags.degrade4Space = !AddrSurfInfoIn.flags.tcCompatible && !AddrSurfInfoIn.flags.fmask && tex->nr_samples <= 1 && (flags & RADEON_SURF_OPTIMIZE_FOR_SPACE); AddrSurfInfoIn.flags.opt4Space = AddrSurfInfoIn.flags.degrade4Space; /* DCC notes: * - If we add MSAA support, keep in mind that CB can't decompress 8bpp * with samples >= 4. * - Mipmapped array textures have low performance (discovered by a closed * driver team). */ AddrSurfInfoIn.flags.dccCompatible = ws->info.chip_class >= VI && !(flags & RADEON_SURF_Z_OR_SBUFFER) && !(flags & RADEON_SURF_DISABLE_DCC) && !compressed && AddrDccIn.numSamples <= 1 && ((tex->array_size == 1 && tex->depth0 == 1) || tex->last_level == 0); AddrSurfInfoIn.flags.noStencil = (flags & RADEON_SURF_SBUFFER) == 0; AddrSurfInfoIn.flags.compressZ = AddrSurfInfoIn.flags.depth; /* noStencil = 0 can result in a depth part that is incompatible with * mipmapped texturing. So set noStencil = 1 when mipmaps are requested (in * this case, we may end up setting stencil_adjusted). * * TODO: update addrlib to a newer version, remove this, and * use flags.matchStencilTileCfg = 1 as an alternative fix. */ if (tex->last_level > 0) AddrSurfInfoIn.flags.noStencil = 1; /* Set preferred macrotile parameters. This is usually required * for shared resources. This is for 2D tiling only. */ if (AddrSurfInfoIn.tileMode >= ADDR_TM_2D_TILED_THIN1 && surf->bankw && surf->bankh && surf->mtilea && surf->tile_split) { assert(!(flags & RADEON_SURF_FMASK)); /* If any of these parameters are incorrect, the calculation * will fail. */ AddrTileInfoIn.banks = surf->num_banks; AddrTileInfoIn.bankWidth = surf->bankw; AddrTileInfoIn.bankHeight = surf->bankh; AddrTileInfoIn.macroAspectRatio = surf->mtilea; AddrTileInfoIn.tileSplitBytes = surf->tile_split; AddrTileInfoIn.pipeConfig = surf->pipe_config + 1; /* +1 compared to GB_TILE_MODE */ AddrSurfInfoIn.flags.degrade4Space = 0; AddrSurfInfoIn.pTileInfo = &AddrTileInfoIn; /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set * the tile index, because we are expected to know it if * we know the other parameters. * * This is something that can easily be fixed in Addrlib. * For now, just figure it out here. * Note that only 2D_TILE_THIN1 is handled here. */ assert(!(flags & RADEON_SURF_Z_OR_SBUFFER)); assert(AddrSurfInfoIn.tileMode == ADDR_TM_2D_TILED_THIN1); if (ws->info.chip_class == SI) { if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) { if (bpe == 2) AddrSurfInfoIn.tileIndex = 11; /* 16bpp */ else AddrSurfInfoIn.tileIndex = 12; /* 32bpp */ } else { if (bpe == 1) AddrSurfInfoIn.tileIndex = 14; /* 8bpp */ else if (bpe == 2) AddrSurfInfoIn.tileIndex = 15; /* 16bpp */ else if (bpe == 4) AddrSurfInfoIn.tileIndex = 16; /* 32bpp */ else AddrSurfInfoIn.tileIndex = 17; /* 64bpp (and 128bpp) */ } } else { /* CIK - VI */ if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE) AddrSurfInfoIn.tileIndex = 10; /* 2D displayable */ else AddrSurfInfoIn.tileIndex = 14; /* 2D non-displayable */ /* Addrlib doesn't set this if tileIndex is forced like above. */ AddrSurfInfoOut.macroModeIndex = cik_get_macro_tile_index(surf); } } surf->num_dcc_levels = 0; surf->surf_size = 0; surf->dcc_size = 0; surf->dcc_alignment = 1; surf->htile_size = 0; surf->htile_alignment = 1; /* Calculate texture layout information. */ for (level = 0; level <= tex->last_level; level++) { r = compute_level(ws, tex, surf, false, level, compressed, &AddrSurfInfoIn, &AddrSurfInfoOut, &AddrDccIn, &AddrDccOut, &AddrHtileIn, &AddrHtileOut); if (r) return r; if (level == 0) { surf->surf_alignment = AddrSurfInfoOut.baseAlign; surf->pipe_config = AddrSurfInfoOut.pTileInfo->pipeConfig - 1; set_micro_tile_mode(surf, &ws->info); /* For 2D modes only. */ if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { surf->bankw = AddrSurfInfoOut.pTileInfo->bankWidth; surf->bankh = AddrSurfInfoOut.pTileInfo->bankHeight; surf->mtilea = AddrSurfInfoOut.pTileInfo->macroAspectRatio; surf->tile_split = AddrSurfInfoOut.pTileInfo->tileSplitBytes; surf->num_banks = AddrSurfInfoOut.pTileInfo->banks; surf->macro_tile_index = AddrSurfInfoOut.macroModeIndex; } else { surf->macro_tile_index = 0; } } } /* Calculate texture layout information for stencil. */ if (flags & RADEON_SURF_SBUFFER) { AddrSurfInfoIn.bpp = 8; AddrSurfInfoIn.flags.depth = 0; AddrSurfInfoIn.flags.stencil = 1; AddrSurfInfoIn.flags.tcCompatible = 0; /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */ AddrTileInfoIn.tileSplitBytes = surf->stencil_tile_split; for (level = 0; level <= tex->last_level; level++) { r = compute_level(ws, tex, surf, true, level, compressed, &AddrSurfInfoIn, &AddrSurfInfoOut, &AddrDccIn, &AddrDccOut, NULL, NULL); if (r) return r; /* DB uses the depth pitch for both stencil and depth. */ if (surf->stencil_level[level].nblk_x != surf->level[level].nblk_x) surf->stencil_adjusted = true; if (level == 0) { /* For 2D modes only. */ if (AddrSurfInfoOut.tileMode >= ADDR_TM_2D_TILED_THIN1) { surf->stencil_tile_split = AddrSurfInfoOut.pTileInfo->tileSplitBytes; } } } } /* Recalculate the whole DCC miptree size including disabled levels. * This is what addrlib does, but calling addrlib would be a lot more * complicated. */ if (surf->dcc_size && tex->last_level > 0) { surf->dcc_size = align64(surf->surf_size >> 8, ws->info.pipe_interleave_bytes * ws->info.num_tile_pipes); }