Revert "amd/common: Always initialize gfx9 mipmap offset/pitch."
[mesa.git] / src / amd / common / ac_surface.c
index f8b9d2b70f8aa7a22767d4018e1f99128b08ca81..92aab57920a35feda4c678389f177c3f63a74aeb 100644 (file)
@@ -68,7 +68,7 @@ ADDR_HANDLE amdgpu_addr_create(const struct radeon_info *info,
        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);
@@ -85,7 +85,6 @@ ADDR_HANDLE amdgpu_addr_create(const struct radeon_info *info,
 
        if (addrCreateInput.chipFamily >= FAMILY_AI) {
                addrCreateInput.chipEngine = CIASICIDGFXENGINE_ARCTICISLAND;
-               regValue.blockVarSizeLog2 = 0;
        } else {
                regValue.noOfBanks = amdinfo->mc_arb_ramcfg & 0x3;
                regValue.noOfRanks = (amdinfo->mc_arb_ramcfg & 0x4) >> 2;
@@ -207,6 +206,17 @@ static int gfx6_compute_level(ADDR_HANDLE addrlib,
                AddrSurfInfoIn->width = align(AddrSurfInfoIn->width, alignment);
        }
 
+       /* addrlib assumes the bytes/pixel is a divisor of 64, which is not
+        * true for r32g32b32 formats. */
+       if (AddrSurfInfoIn->bpp == 96) {
+               assert(config->info.levels == 1);
+               assert(AddrSurfInfoIn->tileMode == ADDR_TM_LINEAR_ALIGNED);
+
+               /* The least common multiple of 64 bytes and 12 bytes/pixel is
+                * 192 bytes, or 16 pixels. */
+               AddrSurfInfoIn->width = align(AddrSurfInfoIn->width, 16);
+       }
+
        if (config->is_3d)
                AddrSurfInfoIn->numSlices = u_minify(config->info.depth, level);
        else if (config->is_cube)
@@ -302,15 +312,49 @@ static int gfx6_compute_level(ADDR_HANDLE addrlib,
                                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) {
-               AddrHtileIn->flags.tcCompatible = AddrSurfInfoIn->flags.tcCompatible;
+           level == 0 &&
+           !(surf->flags & RADEON_SURF_NO_HTILE)) {
+               AddrHtileIn->flags.tcCompatible = AddrSurfInfoOut->tcCompatible;
                AddrHtileIn->pitch = AddrSurfInfoOut->pitch;
                AddrHtileIn->height = AddrSurfInfoOut->height;
                AddrHtileIn->numSlices = AddrSurfInfoOut->depth;
@@ -455,7 +499,8 @@ static void ac_compute_cmask(const struct radeon_info *info,
        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);
@@ -625,6 +670,7 @@ static int gfx6_compute_surface(ADDR_HANDLE addrlib,
         */
        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 &&
@@ -743,19 +789,12 @@ static int gfx6_compute_surface(ADDR_HANDLE addrlib,
                        if (level > 0)
                                continue;
 
-                       /* Check that we actually got a TC-compatible HTILE if
-                        * we requested it (only for level 0, since we're not
-                        * supporting HTILE on higher mip levels anyway). */
-                       assert(AddrSurfInfoOut.tcCompatible ||
-                              !AddrSurfInfoIn.flags.tcCompatible ||
-                              AddrSurfInfoIn.flags.matchStencilTileCfg);
+                       if (!AddrSurfInfoOut.tcCompatible) {
+                               AddrSurfInfoIn.flags.tcCompatible = 0;
+                               surf->flags &= ~RADEON_SURF_TC_COMPATIBLE_HTILE;
+                       }
 
                        if (AddrSurfInfoIn.flags.matchStencilTileCfg) {
-                               if (!AddrSurfInfoOut.tcCompatible) {
-                                       AddrSurfInfoIn.flags.tcCompatible = 0;
-                                       surf->flags &= ~RADEON_SURF_TC_COMPATIBLE_HTILE;
-                               }
-
                                AddrSurfInfoIn.flags.matchStencilTileCfg = 0;
                                AddrSurfInfoIn.tileIndex = AddrSurfInfoOut.tileIndex;
                                stencil_tile_idx = AddrSurfInfoOut.stencilTileIdx;
@@ -816,7 +855,8 @@ static int gfx6_compute_surface(ADDR_HANDLE addrlib,
        }
 
        /* 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 = {};
@@ -948,7 +988,6 @@ gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib,
        /* 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;
@@ -971,6 +1010,14 @@ gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib,
        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,
@@ -1015,13 +1062,18 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
        surf->surf_alignment = out.baseAlign;
 
        if (in->swizzleMode == ADDR_SW_LINEAR) {
-               for (unsigned i = 0; i < in->numMipLevels; i++)
+               for (unsigned i = 0; i < in->numMipLevels; i++) {
                        surf->u.gfx9.offset[i] = mip_info[i].offset;
+                       surf->u.gfx9.pitch[i] = mip_info[i].pitch;
+               }
        }
 
        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};
@@ -1048,7 +1100,10 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
                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.
                 */
@@ -1081,9 +1136,10 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
                }
 
                /* 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] = {};
@@ -1223,7 +1279,7 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
                                                        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 */
@@ -1236,7 +1292,7 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
                                                        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);
@@ -1250,7 +1306,8 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
                }
 
                /* 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};
 
@@ -1306,8 +1363,11 @@ static int gfx9_compute_miptree(ADDR_HANDLE addrlib,
                        }
                }
 
-               /* CMASK */
-               if (in->swizzleMode != ADDR_SW_LINEAR) {
+               /* CMASK -- on GFX10 only for FMASK */
+               if (in->swizzleMode != ADDR_SW_LINEAR &&
+                   in->resourceType == ADDR_RSRC_TEX_2D &&
+                   ((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};
 
@@ -1430,6 +1490,8 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib,
         * 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;
 
@@ -1469,7 +1531,7 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib,
 
        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;
                }
@@ -1550,11 +1612,9 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib,
                case ADDR_SW_256B_S:
                case ADDR_SW_4KB_S:
                case ADDR_SW_64KB_S:
-               case ADDR_SW_VAR_S:
                case ADDR_SW_64KB_S_T:
                case ADDR_SW_4KB_S_X:
                case ADDR_SW_64KB_S_X:
-               case ADDR_SW_VAR_S_X:
                        surf->micro_tile_mode = RADEON_MICRO_MODE_THIN;
                        break;
 
@@ -1563,36 +1623,32 @@ static int gfx9_compute_surface(ADDR_HANDLE addrlib,
                case ADDR_SW_256B_D:
                case ADDR_SW_4KB_D:
                case ADDR_SW_64KB_D:
-               case ADDR_SW_VAR_D:
                case ADDR_SW_64KB_D_T:
                case ADDR_SW_4KB_D_X:
                case ADDR_SW_64KB_D_X:
-               case ADDR_SW_VAR_D_X:
                        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_VAR_R:
                case ADDR_SW_64KB_R_T:
                case ADDR_SW_4KB_R_X:
                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:
                case ADDR_SW_64KB_Z:
-               case ADDR_SW_VAR_Z:
                case ADDR_SW_64KB_Z_T:
                case ADDR_SW_4KB_Z_X:
                case ADDR_SW_64KB_Z_X:
@@ -1624,7 +1680,61 @@ int ac_compute_surface(ADDR_HANDLE addrlib, const struct radeon_info *info,
                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;
 }