Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
    }