winsys/amdgpu: set addrlib flag opt4Space
[mesa.git] / src / gallium / winsys / amdgpu / drm / amdgpu_surface.c
index 1164a3058c507616be6ebabbd185dbde183427e7..08989b5cf531106a6cdac0a2761b341aaaa2826b 100644 (file)
  */
 
 #include "amdgpu_winsys.h"
-
-#ifndef NO_ENTRIES
-#define NO_ENTRIES 32
-#endif
-
-#ifndef NO_MACRO_ENTRIES
-#define NO_MACRO_ENTRIES 16
-#endif
+#include "util/u_format.h"
 
 #ifndef CIASICIDGFXENGINE_SOUTHERNISLAND
 #define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A
 #endif
 
 
-static int amdgpu_surface_sanity(const struct radeon_surf *surf)
+static int amdgpu_surface_sanity(const struct pipe_resource *tex)
 {
-   unsigned type = RADEON_SURF_GET(surf->flags, TYPE);
-
-   if (!(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))
-      return -EINVAL;
-
    /* all dimension must be at least 1 ! */
-   if (!surf->npix_x || !surf->npix_y || !surf->npix_z ||
-       !surf->array_size)
+   if (!tex->width0 || !tex->height0 || !tex->depth0 ||
+       !tex->array_size)
       return -EINVAL;
 
-   if (!surf->blk_w || !surf->blk_h || !surf->blk_d)
-      return -EINVAL;
-
-   switch (surf->nsamples) {
+   switch (tex->nr_samples) {
+   case 0:
    case 1:
    case 2:
    case 4:
@@ -69,26 +55,28 @@ static int amdgpu_surface_sanity(const struct radeon_surf *surf)
       return -EINVAL;
    }
 
-   switch (type) {
-   case RADEON_SURF_TYPE_1D:
-      if (surf->npix_y > 1)
+   switch (tex->target) {
+   case PIPE_TEXTURE_1D:
+      if (tex->height0 > 1)
          return -EINVAL;
       /* fall through */
-   case RADEON_SURF_TYPE_2D:
-   case RADEON_SURF_TYPE_CUBEMAP:
-      if (surf->npix_z > 1 || surf->array_size > 1)
+   case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
+      if (tex->depth0 > 1 || tex->array_size > 1)
          return -EINVAL;
       break;
-   case RADEON_SURF_TYPE_3D:
-      if (surf->array_size > 1)
+   case PIPE_TEXTURE_3D:
+      if (tex->array_size > 1)
          return -EINVAL;
       break;
-   case RADEON_SURF_TYPE_1D_ARRAY:
-      if (surf->npix_y > 1)
+   case PIPE_TEXTURE_1D_ARRAY:
+      if (tex->height0 > 1)
          return -EINVAL;
       /* fall through */
-   case RADEON_SURF_TYPE_2D_ARRAY:
-      if (surf->npix_z > 1)
+   case PIPE_TEXTURE_CUBE:
+   case PIPE_TEXTURE_2D_ARRAY:
+   case PIPE_TEXTURE_CUBE_ARRAY:
+      if (tex->depth0 > 1)
          return -EINVAL;
       break;
    default:
@@ -108,26 +96,6 @@ static ADDR_E_RETURNCODE ADDR_API freeSysMem(const ADDR_FREESYSMEM_INPUT * pInpu
    return ADDR_OK;
 }
 
-/**
- * This returns the number of banks for the surface.
- * Possible values: 2, 4, 8, 16.
- */
-static uint32_t cik_num_banks(struct amdgpu_winsys *ws,
-                              struct radeon_surf *surf)
-{
-   unsigned index, tileb;
-
-   tileb = 8 * 8 * surf->bpe;
-   tileb = MIN2(surf->tile_split, tileb);
-
-   for (index = 0; tileb > 64; index++) {
-      tileb >>= 1;
-   }
-   assert(index < 16);
-
-   return 2 << ((ws->amdinfo.gb_macro_tile_mode[index] >> 6) & 0x3);
-}
-
 ADDR_HANDLE amdgpu_addr_create(struct amdgpu_winsys *ws)
 {
    ADDR_CREATE_INPUT addrCreateInput = {0};
@@ -146,12 +114,18 @@ ADDR_HANDLE amdgpu_addr_create(struct amdgpu_winsys *ws)
    regValue.backendDisables = ws->amdinfo.backend_disable[0];
    regValue.pTileConfig = ws->amdinfo.gb_tile_mode;
    regValue.noOfEntries = ARRAY_SIZE(ws->amdinfo.gb_tile_mode);
-   regValue.pMacroTileConfig = ws->amdinfo.gb_macro_tile_mode;
-   regValue.noOfMacroEntries = ARRAY_SIZE(ws->amdinfo.gb_macro_tile_mode);
+   if (ws->info.chip_class == SI) {
+      regValue.pMacroTileConfig = NULL;
+      regValue.noOfMacroEntries = 0;
+   } else {
+      regValue.pMacroTileConfig = ws->amdinfo.gb_macro_tile_mode;
+      regValue.noOfMacroEntries = ARRAY_SIZE(ws->amdinfo.gb_macro_tile_mode);
+   }
 
    createFlags.value = 0;
    createFlags.useTileIndex = 1;
    createFlags.degradeBaseLevel = 1;
+   createFlags.useHtileSliceAlign = 1;
 
    addrCreateInput.chipEngine = CIASICIDGFXENGINE_SOUTHERNISLAND;
    addrCreateInput.chipFamily = ws->family;
@@ -170,26 +144,29 @@ ADDR_HANDLE amdgpu_addr_create(struct amdgpu_winsys *ws)
 }
 
 static int compute_level(struct amdgpu_winsys *ws,
+                         const struct pipe_resource *tex,
                          struct radeon_surf *surf, bool is_stencil,
-                         unsigned level, unsigned type, bool compressed,
+                         unsigned level, bool compressed,
                          ADDR_COMPUTE_SURFACE_INFO_INPUT *AddrSurfInfoIn,
                          ADDR_COMPUTE_SURFACE_INFO_OUTPUT *AddrSurfInfoOut,
                          ADDR_COMPUTE_DCCINFO_INPUT *AddrDccIn,
-                         ADDR_COMPUTE_DCCINFO_OUTPUT *AddrDccOut)
+                         ADDR_COMPUTE_DCCINFO_OUTPUT *AddrDccOut,
+                         ADDR_COMPUTE_HTILE_INFO_INPUT *AddrHtileIn,
+                         ADDR_COMPUTE_HTILE_INFO_OUTPUT *AddrHtileOut)
 {
    struct radeon_surf_level *surf_level;
    ADDR_E_RETURNCODE ret;
 
    AddrSurfInfoIn->mipLevel = level;
-   AddrSurfInfoIn->width = u_minify(surf->npix_x, level);
-   AddrSurfInfoIn->height = u_minify(surf->npix_y, level);
+   AddrSurfInfoIn->width = u_minify(tex->width0, level);
+   AddrSurfInfoIn->height = u_minify(tex->height0, level);
 
-   if (type == RADEON_SURF_TYPE_3D)
-      AddrSurfInfoIn->numSlices = u_minify(surf->npix_z, level);
-   else if (type == RADEON_SURF_TYPE_CUBEMAP)
+   if (tex->target == PIPE_TEXTURE_3D)
+      AddrSurfInfoIn->numSlices = u_minify(tex->depth0, level);
+   else if (tex->target == PIPE_TEXTURE_CUBE)
       AddrSurfInfoIn->numSlices = 6;
    else
-      AddrSurfInfoIn->numSlices = surf->array_size;
+      AddrSurfInfoIn->numSlices = tex->array_size;
 
    if (level > 0) {
       /* Set the base level pitch. This is needed for calculation
@@ -212,23 +189,12 @@ static int compute_level(struct amdgpu_winsys *ws,
    }
 
    surf_level = is_stencil ? &surf->stencil_level[level] : &surf->level[level];
-   surf_level->offset = align64(surf->bo_size, AddrSurfInfoOut->baseAlign);
+   surf_level->offset = align64(surf->surf_size, AddrSurfInfoOut->baseAlign);
    surf_level->slice_size = AddrSurfInfoOut->sliceSize;
-   surf_level->pitch_bytes = AddrSurfInfoOut->pitch * (is_stencil ? 1 : surf->bpe);
-   surf_level->npix_x = u_minify(surf->npix_x, level);
-   surf_level->npix_y = u_minify(surf->npix_y, level);
-   surf_level->npix_z = u_minify(surf->npix_z, level);
    surf_level->nblk_x = AddrSurfInfoOut->pitch;
    surf_level->nblk_y = AddrSurfInfoOut->height;
-   if (type == RADEON_SURF_TYPE_3D)
-      surf_level->nblk_z = AddrSurfInfoOut->depth;
-   else
-      surf_level->nblk_z = 1;
 
    switch (AddrSurfInfoOut->tileMode) {
-   case ADDR_TM_LINEAR_GENERAL:
-      surf_level->mode = RADEON_SURF_MODE_LINEAR;
-      break;
    case ADDR_TM_LINEAR_ALIGNED:
       surf_level->mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
       break;
@@ -247,9 +213,14 @@ static int compute_level(struct amdgpu_winsys *ws,
    else
       surf->tiling_index[level] = AddrSurfInfoOut->tileIndex;
 
-   surf->bo_size = surf_level->offset + AddrSurfInfoOut->surfSize;
+   surf->surf_size = surf_level->offset + AddrSurfInfoOut->surfSize;
+
+   /* Clear DCC fields at the beginning. */
+   surf_level->dcc_offset = 0;
 
-   if (AddrSurfInfoIn->flags.dccCompatible) {
+   /* The previous level's flag tells us if we can use DCC for this level. */
+   if (AddrSurfInfoIn->flags.dccCompatible &&
+       (level == 0 || AddrDccOut->subLvlCompressible)) {
       AddrDccIn->colorSurfSize = AddrSurfInfoOut->surfSize;
       AddrDccIn->tileMode = AddrSurfInfoOut->tileMode;
       AddrDccIn->tileInfo = *AddrSurfInfoOut->pTileInfo;
@@ -262,35 +233,90 @@ static int compute_level(struct amdgpu_winsys *ws,
 
       if (ret == ADDR_OK) {
          surf_level->dcc_offset = surf->dcc_size;
+         surf_level->dcc_fast_clear_size = AddrDccOut->dccFastClearSize;
+         surf->num_dcc_levels = level + 1;
          surf->dcc_size = surf_level->dcc_offset + AddrDccOut->dccRamSize;
          surf->dcc_alignment = MAX2(surf->dcc_alignment, AddrDccOut->dccRamBaseAlign);
-      } else {
-         surf->dcc_size = 0;
-         surf_level->dcc_offset = 0;
       }
-   } else {
-      surf->dcc_size = 0;
-      surf_level->dcc_offset = 0;
+   }
+
+   /* TC-compatible HTILE. */
+   if (!is_stencil &&
+       AddrSurfInfoIn->flags.depth &&
+       AddrSurfInfoIn->flags.tcCompatible &&
+       surf_level->mode == RADEON_SURF_MODE_2D &&
+       level == 0) {
+      AddrHtileIn->flags.tcCompatible = 1;
+      AddrHtileIn->pitch = AddrSurfInfoOut->pitch;
+      AddrHtileIn->height = AddrSurfInfoOut->height;
+      AddrHtileIn->numSlices = AddrSurfInfoOut->depth;
+      AddrHtileIn->blockWidth = ADDR_HTILE_BLOCKSIZE_8;
+      AddrHtileIn->blockHeight = ADDR_HTILE_BLOCKSIZE_8;
+      AddrHtileIn->pTileInfo = AddrSurfInfoOut->pTileInfo;
+      AddrHtileIn->tileIndex = AddrSurfInfoOut->tileIndex;
+      AddrHtileIn->macroModeIndex = AddrSurfInfoOut->macroModeIndex;
+
+      ret = AddrComputeHtileInfo(ws->addrlib,
+                                 AddrHtileIn,
+                                 AddrHtileOut);
+
+      if (ret == ADDR_OK) {
+         surf->htile_size = AddrHtileOut->htileBytes;
+         surf->htile_alignment = AddrHtileOut->baseAlign;
+      }
    }
 
    return 0;
 }
 
+#define   G_009910_MICRO_TILE_MODE(x)          (((x) >> 0) & 0x03)
+#define   G_009910_MICRO_TILE_MODE_NEW(x)      (((x) >> 22) & 0x07)
+
+static void set_micro_tile_mode(struct radeon_surf *surf,
+                                struct radeon_info *info)
+{
+   uint32_t tile_mode = info->si_tile_mode_array[surf->tiling_index[0]];
+
+   if (info->chip_class >= CIK)
+      surf->micro_tile_mode = G_009910_MICRO_TILE_MODE_NEW(tile_mode);
+   else
+      surf->micro_tile_mode = G_009910_MICRO_TILE_MODE(tile_mode);
+}
+
+static unsigned cik_get_macro_tile_index(struct radeon_surf *surf)
+{
+       unsigned index, tileb;
+
+       tileb = 8 * 8 * surf->bpe;
+       tileb = MIN2(surf->tile_split, tileb);
+
+       for (index = 0; tileb > 64; index++)
+               tileb >>= 1;
+
+       assert(index < 16);
+       return index;
+}
+
 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, mode, type;
+   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(surf);
+   r = amdgpu_surface_sanity(tex);
    if (r)
       return r;
 
@@ -298,27 +324,29 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
    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;
 
-   type = RADEON_SURF_GET(surf->flags, TYPE);
-   mode = RADEON_SURF_GET(surf->flags, MODE);
+   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 (surf->nsamples > 1 ||
-       (surf->flags & RADEON_SURF_FMASK))
+   if (tex->nr_samples > 1 ||
+       (flags & RADEON_SURF_FMASK))
       mode = RADEON_SURF_MODE_2D;
 
    /* DB doesn't support linear layouts. */
-   if (surf->flags & (RADEON_SURF_Z_OR_SBUFFER) &&
+   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:
-      AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_GENERAL;
-      break;
    case RADEON_SURF_MODE_LINEAR_ALIGNED:
       AddrSurfInfoIn.tileMode = ADDR_TM_LINEAR_ALIGNED;
       break;
@@ -335,7 +363,7 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
    /* 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 (surf->bpe) {
+      switch (bpe) {
       case 8:
          AddrSurfInfoIn.format = ADDR_FMT_BC1;
          break;
@@ -347,45 +375,78 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
       }
    }
    else {
-      AddrDccIn.bpp = AddrSurfInfoIn.bpp = surf->bpe * 8;
+      AddrDccIn.bpp = AddrSurfInfoIn.bpp = bpe * 8;
    }
 
-   AddrDccIn.numSamples = AddrSurfInfoIn.numSamples = surf->nsamples;
+   AddrDccIn.numSamples = AddrSurfInfoIn.numSamples =
+      tex->nr_samples ? tex->nr_samples : 1;
    AddrSurfInfoIn.tileIndex = -1;
 
    /* Set the micro tile type. */
-   if (surf->flags & RADEON_SURF_SCANOUT)
+   if (flags & RADEON_SURF_SCANOUT)
       AddrSurfInfoIn.tileType = ADDR_DISPLAYABLE;
-   else if (surf->flags & RADEON_SURF_Z_OR_SBUFFER)
+   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 = !(surf->flags & RADEON_SURF_Z_OR_SBUFFER);
-   AddrSurfInfoIn.flags.depth = (surf->flags & RADEON_SURF_ZBUFFER) != 0;
-   AddrSurfInfoIn.flags.stencil = (surf->flags & RADEON_SURF_SBUFFER) != 0;
-   AddrSurfInfoIn.flags.cube = type == RADEON_SURF_TYPE_CUBEMAP;
-   AddrSurfInfoIn.flags.display = (surf->flags & RADEON_SURF_SCANOUT) != 0;
-   AddrSurfInfoIn.flags.pow2Pad = surf->last_level > 0;
-   AddrSurfInfoIn.flags.degrade4Space = 1;
-   AddrSurfInfoIn.flags.dccCompatible = !(surf->flags & RADEON_SURF_Z_OR_SBUFFER) &&
-                                        !(surf->flags & RADEON_SURF_SCANOUT) &&
-                                        !compressed && AddrDccIn.numSamples <= 1;
-
-   /* This disables incorrect calculations (hacks) in addrlib. */
-   AddrSurfInfoIn.flags.noStencil = 1;
+   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 = cik_num_banks(ws, surf);
+      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;
 
@@ -397,29 +458,56 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
        * For now, just figure it out here.
        * Note that only 2D_TILE_THIN1 is handled here.
        */
-      assert(!(surf->flags & RADEON_SURF_Z_OR_SBUFFER));
+      assert(!(flags & RADEON_SURF_Z_OR_SBUFFER));
       assert(AddrSurfInfoIn.tileMode == ADDR_TM_2D_TILED_THIN1);
 
-      if (AddrSurfInfoIn.tileType == ADDR_DISPLAYABLE)
-         AddrSurfInfoIn.tileIndex = 10; /* 2D displayable */
-      else
-         AddrSurfInfoIn.tileIndex = 14; /* 2D non-displayable */
+      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->bo_size = 0;
+   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 <= surf->last_level; level++) {
-      r = compute_level(ws, surf, false, level, type, compressed,
-                        &AddrSurfInfoIn, &AddrSurfInfoOut, &AddrDccIn, &AddrDccOut);
+   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->bo_alignment = AddrSurfInfoOut.baseAlign;
+         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) {
@@ -428,25 +516,34 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
             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 (surf->flags & RADEON_SURF_SBUFFER) {
+   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 <= surf->last_level; level++) {
-         r = compute_level(ws, surf, true, level, type, compressed,
-                           &AddrSurfInfoIn, &AddrSurfInfoOut, &AddrDccIn, &AddrDccOut);
+      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;
 
-         if (level == 0) {
-            surf->stencil_offset = surf->stencil_level[0].offset;
+         /* 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 =
@@ -456,17 +553,27 @@ static int amdgpu_surface_init(struct radeon_winsys *rws,
       }
    }
 
-   return 0;
-}
+   /* 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);
+   }
 
-static int amdgpu_surface_best(struct radeon_winsys *rws,
-                               struct radeon_surf *surf)
-{
+   /* Make sure HTILE covers the whole miptree, because the shader reads
+    * TC-compatible HTILE even for levels where it's disabled by DB.
+    */
+   if (surf->htile_size && tex->last_level)
+          surf->htile_size *= 2;
+
+   surf->is_linear = surf->level[0].mode == RADEON_SURF_MODE_LINEAR_ALIGNED;
    return 0;
 }
 
 void amdgpu_surface_init_functions(struct amdgpu_winsys *ws)
 {
    ws->base.surface_init = amdgpu_surface_init;
-   ws->base.surface_best = amdgpu_surface_best;
 }