2 * Copyright © 2011 Red Hat All Rights Reserved.
3 * Copyright © 2017 Advanced Micro Devices, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
18 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 * The above copyright notice and this permission notice (including the
24 * next paragraph) shall be included in all copies or substantial portions
28 #include "ac_surface.h"
29 #include "amd_family.h"
30 #include "addrlib/src/amdgpu_asic_addr.h"
31 #include "ac_gpu_info.h"
32 #include "util/macros.h"
33 #include "util/u_atomic.h"
34 #include "util/u_math.h"
40 #include <amdgpu_drm.h>
42 #include "addrlib/inc/addrinterface.h"
44 #ifndef CIASICIDGFXENGINE_SOUTHERNISLAND
45 #define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A
48 #ifndef CIASICIDGFXENGINE_ARCTICISLAND
49 #define CIASICIDGFXENGINE_ARCTICISLAND 0x0000000D
52 static void *ADDR_API
allocSysMem(const ADDR_ALLOCSYSMEM_INPUT
* pInput
)
54 return malloc(pInput
->sizeInBytes
);
57 static ADDR_E_RETURNCODE ADDR_API
freeSysMem(const ADDR_FREESYSMEM_INPUT
* pInput
)
59 free(pInput
->pVirtAddr
);
63 ADDR_HANDLE
amdgpu_addr_create(const struct radeon_info
*info
,
64 const struct amdgpu_gpu_info
*amdinfo
,
65 uint64_t *max_alignment
)
67 ADDR_CREATE_INPUT addrCreateInput
= {0};
68 ADDR_CREATE_OUTPUT addrCreateOutput
= {0};
69 ADDR_REGISTER_VALUE regValue
= {0};
70 ADDR_CREATE_FLAGS createFlags
= {{0}};
71 ADDR_GET_MAX_ALIGNMENTS_OUTPUT addrGetMaxAlignmentsOutput
= {0};
72 ADDR_E_RETURNCODE addrRet
;
74 addrCreateInput
.size
= sizeof(ADDR_CREATE_INPUT
);
75 addrCreateOutput
.size
= sizeof(ADDR_CREATE_OUTPUT
);
77 regValue
.gbAddrConfig
= amdinfo
->gb_addr_cfg
;
78 createFlags
.value
= 0;
80 addrCreateInput
.chipFamily
= info
->family_id
;
81 addrCreateInput
.chipRevision
= info
->chip_external_rev
;
83 if (addrCreateInput
.chipFamily
== FAMILY_UNKNOWN
)
86 if (addrCreateInput
.chipFamily
>= FAMILY_AI
) {
87 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_ARCTICISLAND
;
89 regValue
.noOfBanks
= amdinfo
->mc_arb_ramcfg
& 0x3;
90 regValue
.noOfRanks
= (amdinfo
->mc_arb_ramcfg
& 0x4) >> 2;
92 regValue
.backendDisables
= amdinfo
->enabled_rb_pipes_mask
;
93 regValue
.pTileConfig
= amdinfo
->gb_tile_mode
;
94 regValue
.noOfEntries
= ARRAY_SIZE(amdinfo
->gb_tile_mode
);
95 if (addrCreateInput
.chipFamily
== FAMILY_SI
) {
96 regValue
.pMacroTileConfig
= NULL
;
97 regValue
.noOfMacroEntries
= 0;
99 regValue
.pMacroTileConfig
= amdinfo
->gb_macro_tile_mode
;
100 regValue
.noOfMacroEntries
= ARRAY_SIZE(amdinfo
->gb_macro_tile_mode
);
103 createFlags
.useTileIndex
= 1;
104 createFlags
.useHtileSliceAlign
= 1;
106 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_SOUTHERNISLAND
;
109 addrCreateInput
.callbacks
.allocSysMem
= allocSysMem
;
110 addrCreateInput
.callbacks
.freeSysMem
= freeSysMem
;
111 addrCreateInput
.callbacks
.debugPrint
= 0;
112 addrCreateInput
.createFlags
= createFlags
;
113 addrCreateInput
.regValue
= regValue
;
115 addrRet
= AddrCreate(&addrCreateInput
, &addrCreateOutput
);
116 if (addrRet
!= ADDR_OK
)
120 addrRet
= AddrGetMaxAlignments(addrCreateOutput
.hLib
, &addrGetMaxAlignmentsOutput
);
121 if (addrRet
== ADDR_OK
){
122 *max_alignment
= addrGetMaxAlignmentsOutput
.baseAlign
;
125 return addrCreateOutput
.hLib
;
128 static int surf_config_sanity(const struct ac_surf_config
*config
,
131 /* FMASK is allocated together with the color surface and can't be
132 * allocated separately.
134 assert(!(flags
& RADEON_SURF_FMASK
));
135 if (flags
& RADEON_SURF_FMASK
)
138 /* all dimension must be at least 1 ! */
139 if (!config
->info
.width
|| !config
->info
.height
|| !config
->info
.depth
||
140 !config
->info
.array_size
|| !config
->info
.levels
)
143 switch (config
->info
.samples
) {
151 if (flags
& RADEON_SURF_Z_OR_SBUFFER
)
158 if (!(flags
& RADEON_SURF_Z_OR_SBUFFER
)) {
159 switch (config
->info
.storage_samples
) {
171 if (config
->is_3d
&& config
->info
.array_size
> 1)
173 if (config
->is_cube
&& config
->info
.depth
> 1)
179 static int gfx6_compute_level(ADDR_HANDLE addrlib
,
180 const struct ac_surf_config
*config
,
181 struct radeon_surf
*surf
, bool is_stencil
,
182 unsigned level
, bool compressed
,
183 ADDR_COMPUTE_SURFACE_INFO_INPUT
*AddrSurfInfoIn
,
184 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
*AddrSurfInfoOut
,
185 ADDR_COMPUTE_DCCINFO_INPUT
*AddrDccIn
,
186 ADDR_COMPUTE_DCCINFO_OUTPUT
*AddrDccOut
,
187 ADDR_COMPUTE_HTILE_INFO_INPUT
*AddrHtileIn
,
188 ADDR_COMPUTE_HTILE_INFO_OUTPUT
*AddrHtileOut
)
190 struct legacy_surf_level
*surf_level
;
191 ADDR_E_RETURNCODE ret
;
193 AddrSurfInfoIn
->mipLevel
= level
;
194 AddrSurfInfoIn
->width
= u_minify(config
->info
.width
, level
);
195 AddrSurfInfoIn
->height
= u_minify(config
->info
.height
, level
);
197 /* Make GFX6 linear surfaces compatible with GFX9 for hybrid graphics,
198 * because GFX9 needs linear alignment of 256 bytes.
200 if (config
->info
.levels
== 1 &&
201 AddrSurfInfoIn
->tileMode
== ADDR_TM_LINEAR_ALIGNED
&&
202 AddrSurfInfoIn
->bpp
&&
203 util_is_power_of_two_or_zero(AddrSurfInfoIn
->bpp
)) {
204 unsigned alignment
= 256 / (AddrSurfInfoIn
->bpp
/ 8);
206 AddrSurfInfoIn
->width
= align(AddrSurfInfoIn
->width
, alignment
);
210 AddrSurfInfoIn
->numSlices
= u_minify(config
->info
.depth
, level
);
211 else if (config
->is_cube
)
212 AddrSurfInfoIn
->numSlices
= 6;
214 AddrSurfInfoIn
->numSlices
= config
->info
.array_size
;
217 /* Set the base level pitch. This is needed for calculation
218 * of non-zero levels. */
220 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.stencil_level
[0].nblk_x
;
222 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.level
[0].nblk_x
;
224 /* Convert blocks to pixels for compressed formats. */
226 AddrSurfInfoIn
->basePitch
*= surf
->blk_w
;
229 ret
= AddrComputeSurfaceInfo(addrlib
,
232 if (ret
!= ADDR_OK
) {
236 surf_level
= is_stencil
? &surf
->u
.legacy
.stencil_level
[level
] : &surf
->u
.legacy
.level
[level
];
237 surf_level
->offset
= align64(surf
->surf_size
, AddrSurfInfoOut
->baseAlign
);
238 surf_level
->slice_size_dw
= AddrSurfInfoOut
->sliceSize
/ 4;
239 surf_level
->nblk_x
= AddrSurfInfoOut
->pitch
;
240 surf_level
->nblk_y
= AddrSurfInfoOut
->height
;
242 switch (AddrSurfInfoOut
->tileMode
) {
243 case ADDR_TM_LINEAR_ALIGNED
:
244 surf_level
->mode
= RADEON_SURF_MODE_LINEAR_ALIGNED
;
246 case ADDR_TM_1D_TILED_THIN1
:
247 surf_level
->mode
= RADEON_SURF_MODE_1D
;
249 case ADDR_TM_2D_TILED_THIN1
:
250 surf_level
->mode
= RADEON_SURF_MODE_2D
;
257 surf
->u
.legacy
.stencil_tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
259 surf
->u
.legacy
.tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
261 surf
->surf_size
= surf_level
->offset
+ AddrSurfInfoOut
->surfSize
;
263 /* Clear DCC fields at the beginning. */
264 surf_level
->dcc_offset
= 0;
266 /* The previous level's flag tells us if we can use DCC for this level. */
267 if (AddrSurfInfoIn
->flags
.dccCompatible
&&
268 (level
== 0 || AddrDccOut
->subLvlCompressible
)) {
269 bool prev_level_clearable
= level
== 0 ||
270 AddrDccOut
->dccRamSizeAligned
;
272 AddrDccIn
->colorSurfSize
= AddrSurfInfoOut
->surfSize
;
273 AddrDccIn
->tileMode
= AddrSurfInfoOut
->tileMode
;
274 AddrDccIn
->tileInfo
= *AddrSurfInfoOut
->pTileInfo
;
275 AddrDccIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
276 AddrDccIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
278 ret
= AddrComputeDccInfo(addrlib
,
282 if (ret
== ADDR_OK
) {
283 surf_level
->dcc_offset
= surf
->dcc_size
;
284 surf
->num_dcc_levels
= level
+ 1;
285 surf
->dcc_size
= surf_level
->dcc_offset
+ AddrDccOut
->dccRamSize
;
286 surf
->dcc_alignment
= MAX2(surf
->dcc_alignment
, AddrDccOut
->dccRamBaseAlign
);
288 /* If the DCC size of a subresource (1 mip level or 1 slice)
289 * is not aligned, the DCC memory layout is not contiguous for
290 * that subresource, which means we can't use fast clear.
292 * We only do fast clears for whole mipmap levels. If we did
293 * per-slice fast clears, the same restriction would apply.
294 * (i.e. only compute the slice size and see if it's aligned)
296 * The last level can be non-contiguous and still be clearable
297 * if it's interleaved with the next level that doesn't exist.
299 if (AddrDccOut
->dccRamSizeAligned
||
300 (prev_level_clearable
&& level
== config
->info
.levels
- 1))
301 surf_level
->dcc_fast_clear_size
= AddrDccOut
->dccFastClearSize
;
303 surf_level
->dcc_fast_clear_size
= 0;
305 /* Compute the DCC slice size because addrlib doesn't
306 * provide this info. As DCC memory is linear (each
307 * slice is the same size) it's easy to compute.
309 surf
->dcc_slice_size
= AddrDccOut
->dccRamSize
/ config
->info
.array_size
;
311 /* For arrays, we have to compute the DCC info again
312 * with one slice size to get a correct fast clear
315 if (config
->info
.array_size
> 1) {
316 AddrDccIn
->colorSurfSize
= AddrSurfInfoOut
->sliceSize
;
317 AddrDccIn
->tileMode
= AddrSurfInfoOut
->tileMode
;
318 AddrDccIn
->tileInfo
= *AddrSurfInfoOut
->pTileInfo
;
319 AddrDccIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
320 AddrDccIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
322 ret
= AddrComputeDccInfo(addrlib
,
323 AddrDccIn
, AddrDccOut
);
324 if (ret
== ADDR_OK
) {
325 /* If the DCC memory isn't properly
326 * aligned, the data are interleaved
329 if (AddrDccOut
->dccRamSizeAligned
)
330 surf_level
->dcc_slice_fast_clear_size
= AddrDccOut
->dccFastClearSize
;
332 surf_level
->dcc_slice_fast_clear_size
= 0;
335 surf_level
->dcc_slice_fast_clear_size
= surf_level
->dcc_fast_clear_size
;
342 AddrSurfInfoIn
->flags
.depth
&&
343 surf_level
->mode
== RADEON_SURF_MODE_2D
&&
345 !(surf
->flags
& RADEON_SURF_NO_HTILE
)) {
346 AddrHtileIn
->flags
.tcCompatible
= AddrSurfInfoOut
->tcCompatible
;
347 AddrHtileIn
->pitch
= AddrSurfInfoOut
->pitch
;
348 AddrHtileIn
->height
= AddrSurfInfoOut
->height
;
349 AddrHtileIn
->numSlices
= AddrSurfInfoOut
->depth
;
350 AddrHtileIn
->blockWidth
= ADDR_HTILE_BLOCKSIZE_8
;
351 AddrHtileIn
->blockHeight
= ADDR_HTILE_BLOCKSIZE_8
;
352 AddrHtileIn
->pTileInfo
= AddrSurfInfoOut
->pTileInfo
;
353 AddrHtileIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
354 AddrHtileIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
356 ret
= AddrComputeHtileInfo(addrlib
,
360 if (ret
== ADDR_OK
) {
361 surf
->htile_size
= AddrHtileOut
->htileBytes
;
362 surf
->htile_slice_size
= AddrHtileOut
->sliceSize
;
363 surf
->htile_alignment
= AddrHtileOut
->baseAlign
;
370 #define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03)
371 #define V_009910_ADDR_SURF_THICK_MICRO_TILING 0x03
372 #define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07)
374 static void gfx6_set_micro_tile_mode(struct radeon_surf
*surf
,
375 const struct radeon_info
*info
)
377 uint32_t tile_mode
= info
->si_tile_mode_array
[surf
->u
.legacy
.tiling_index
[0]];
379 if (info
->chip_class
>= GFX7
)
380 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE_NEW(tile_mode
);
382 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE(tile_mode
);
385 static unsigned cik_get_macro_tile_index(struct radeon_surf
*surf
)
387 unsigned index
, tileb
;
389 tileb
= 8 * 8 * surf
->bpe
;
390 tileb
= MIN2(surf
->u
.legacy
.tile_split
, tileb
);
392 for (index
= 0; tileb
> 64; index
++)
399 static bool get_display_flag(const struct ac_surf_config
*config
,
400 const struct radeon_surf
*surf
)
402 unsigned num_channels
= config
->info
.num_channels
;
403 unsigned bpe
= surf
->bpe
;
405 if (!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
) &&
406 surf
->flags
& RADEON_SURF_SCANOUT
&&
407 config
->info
.samples
<= 1 &&
408 surf
->blk_w
<= 2 && surf
->blk_h
== 1) {
410 if (surf
->blk_w
== 2 && surf
->blk_h
== 1)
413 if (/* RGBA8 or RGBA16F */
414 (bpe
>= 4 && bpe
<= 8 && num_channels
== 4) ||
415 /* R5G6B5 or R5G5B5A1 */
416 (bpe
== 2 && num_channels
>= 3) ||
418 (bpe
== 1 && num_channels
== 1))
425 * This must be called after the first level is computed.
427 * Copy surface-global settings like pipe/bank config from level 0 surface
428 * computation, and compute tile swizzle.
430 static int gfx6_surface_settings(ADDR_HANDLE addrlib
,
431 const struct radeon_info
*info
,
432 const struct ac_surf_config
*config
,
433 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* csio
,
434 struct radeon_surf
*surf
)
436 surf
->surf_alignment
= csio
->baseAlign
;
437 surf
->u
.legacy
.pipe_config
= csio
->pTileInfo
->pipeConfig
- 1;
438 gfx6_set_micro_tile_mode(surf
, info
);
440 /* For 2D modes only. */
441 if (csio
->tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
442 surf
->u
.legacy
.bankw
= csio
->pTileInfo
->bankWidth
;
443 surf
->u
.legacy
.bankh
= csio
->pTileInfo
->bankHeight
;
444 surf
->u
.legacy
.mtilea
= csio
->pTileInfo
->macroAspectRatio
;
445 surf
->u
.legacy
.tile_split
= csio
->pTileInfo
->tileSplitBytes
;
446 surf
->u
.legacy
.num_banks
= csio
->pTileInfo
->banks
;
447 surf
->u
.legacy
.macro_tile_index
= csio
->macroModeIndex
;
449 surf
->u
.legacy
.macro_tile_index
= 0;
452 /* Compute tile swizzle. */
453 /* TODO: fix tile swizzle with mipmapping for GFX6 */
454 if ((info
->chip_class
>= GFX7
|| config
->info
.levels
== 1) &&
455 config
->info
.surf_index
&&
456 surf
->u
.legacy
.level
[0].mode
== RADEON_SURF_MODE_2D
&&
457 !(surf
->flags
& (RADEON_SURF_Z_OR_SBUFFER
| RADEON_SURF_SHAREABLE
)) &&
458 !get_display_flag(config
, surf
)) {
459 ADDR_COMPUTE_BASE_SWIZZLE_INPUT AddrBaseSwizzleIn
= {0};
460 ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT AddrBaseSwizzleOut
= {0};
462 AddrBaseSwizzleIn
.size
= sizeof(ADDR_COMPUTE_BASE_SWIZZLE_INPUT
);
463 AddrBaseSwizzleOut
.size
= sizeof(ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT
);
465 AddrBaseSwizzleIn
.surfIndex
= p_atomic_inc_return(config
->info
.surf_index
) - 1;
466 AddrBaseSwizzleIn
.tileIndex
= csio
->tileIndex
;
467 AddrBaseSwizzleIn
.macroModeIndex
= csio
->macroModeIndex
;
468 AddrBaseSwizzleIn
.pTileInfo
= csio
->pTileInfo
;
469 AddrBaseSwizzleIn
.tileMode
= csio
->tileMode
;
471 int r
= AddrComputeBaseSwizzle(addrlib
, &AddrBaseSwizzleIn
,
472 &AddrBaseSwizzleOut
);
476 assert(AddrBaseSwizzleOut
.tileSwizzle
<=
477 u_bit_consecutive(0, sizeof(surf
->tile_swizzle
) * 8));
478 surf
->tile_swizzle
= AddrBaseSwizzleOut
.tileSwizzle
;
483 static void ac_compute_cmask(const struct radeon_info
*info
,
484 const struct ac_surf_config
*config
,
485 struct radeon_surf
*surf
)
487 unsigned pipe_interleave_bytes
= info
->pipe_interleave_bytes
;
488 unsigned num_pipes
= info
->num_tile_pipes
;
489 unsigned cl_width
, cl_height
;
491 if (surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
||
492 (config
->info
.samples
>= 2 && !surf
->fmask_size
))
495 assert(info
->chip_class
<= GFX8
);
510 case 16: /* Hawaii */
519 unsigned base_align
= num_pipes
* pipe_interleave_bytes
;
521 unsigned width
= align(surf
->u
.legacy
.level
[0].nblk_x
, cl_width
*8);
522 unsigned height
= align(surf
->u
.legacy
.level
[0].nblk_y
, cl_height
*8);
523 unsigned slice_elements
= (width
* height
) / (8*8);
525 /* Each element of CMASK is a nibble. */
526 unsigned slice_bytes
= slice_elements
/ 2;
528 surf
->u
.legacy
.cmask_slice_tile_max
= (width
* height
) / (128*128);
529 if (surf
->u
.legacy
.cmask_slice_tile_max
)
530 surf
->u
.legacy
.cmask_slice_tile_max
-= 1;
534 num_layers
= config
->info
.depth
;
535 else if (config
->is_cube
)
538 num_layers
= config
->info
.array_size
;
540 surf
->cmask_alignment
= MAX2(256, base_align
);
541 surf
->cmask_slice_size
= align(slice_bytes
, base_align
);
542 surf
->cmask_size
= surf
->cmask_slice_size
* num_layers
;
546 * Fill in the tiling information in \p surf based on the given surface config.
548 * The following fields of \p surf must be initialized by the caller:
549 * blk_w, blk_h, bpe, flags.
551 static int gfx6_compute_surface(ADDR_HANDLE addrlib
,
552 const struct radeon_info
*info
,
553 const struct ac_surf_config
*config
,
554 enum radeon_surf_mode mode
,
555 struct radeon_surf
*surf
)
559 ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
560 ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut
= {0};
561 ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn
= {0};
562 ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut
= {0};
563 ADDR_COMPUTE_HTILE_INFO_INPUT AddrHtileIn
= {0};
564 ADDR_COMPUTE_HTILE_INFO_OUTPUT AddrHtileOut
= {0};
565 ADDR_TILEINFO AddrTileInfoIn
= {0};
566 ADDR_TILEINFO AddrTileInfoOut
= {0};
569 AddrSurfInfoIn
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT
);
570 AddrSurfInfoOut
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT
);
571 AddrDccIn
.size
= sizeof(ADDR_COMPUTE_DCCINFO_INPUT
);
572 AddrDccOut
.size
= sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT
);
573 AddrHtileIn
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT
);
574 AddrHtileOut
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT
);
575 AddrSurfInfoOut
.pTileInfo
= &AddrTileInfoOut
;
577 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
579 /* MSAA requires 2D tiling. */
580 if (config
->info
.samples
> 1)
581 mode
= RADEON_SURF_MODE_2D
;
583 /* DB doesn't support linear layouts. */
584 if (surf
->flags
& (RADEON_SURF_Z_OR_SBUFFER
) &&
585 mode
< RADEON_SURF_MODE_1D
)
586 mode
= RADEON_SURF_MODE_1D
;
588 /* Set the requested tiling mode. */
590 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
591 AddrSurfInfoIn
.tileMode
= ADDR_TM_LINEAR_ALIGNED
;
593 case RADEON_SURF_MODE_1D
:
594 AddrSurfInfoIn
.tileMode
= ADDR_TM_1D_TILED_THIN1
;
596 case RADEON_SURF_MODE_2D
:
597 AddrSurfInfoIn
.tileMode
= ADDR_TM_2D_TILED_THIN1
;
603 /* The format must be set correctly for the allocation of compressed
604 * textures to work. In other cases, setting the bpp is sufficient.
609 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
612 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
619 AddrDccIn
.bpp
= AddrSurfInfoIn
.bpp
= surf
->bpe
* 8;
622 AddrDccIn
.numSamples
= AddrSurfInfoIn
.numSamples
=
623 MAX2(1, config
->info
.samples
);
624 AddrSurfInfoIn
.tileIndex
= -1;
626 if (!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
)) {
627 AddrDccIn
.numSamples
= AddrSurfInfoIn
.numFrags
=
628 MAX2(1, config
->info
.storage_samples
);
631 /* Set the micro tile type. */
632 if (surf
->flags
& RADEON_SURF_SCANOUT
)
633 AddrSurfInfoIn
.tileType
= ADDR_DISPLAYABLE
;
634 else if (surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
)
635 AddrSurfInfoIn
.tileType
= ADDR_DEPTH_SAMPLE_ORDER
;
637 AddrSurfInfoIn
.tileType
= ADDR_NON_DISPLAYABLE
;
639 AddrSurfInfoIn
.flags
.color
= !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
);
640 AddrSurfInfoIn
.flags
.depth
= (surf
->flags
& RADEON_SURF_ZBUFFER
) != 0;
641 AddrSurfInfoIn
.flags
.cube
= config
->is_cube
;
642 AddrSurfInfoIn
.flags
.display
= get_display_flag(config
, surf
);
643 AddrSurfInfoIn
.flags
.pow2Pad
= config
->info
.levels
> 1;
644 AddrSurfInfoIn
.flags
.tcCompatible
= (surf
->flags
& RADEON_SURF_TC_COMPATIBLE_HTILE
) != 0;
646 /* Only degrade the tile mode for space if TC-compatible HTILE hasn't been
647 * requested, because TC-compatible HTILE requires 2D tiling.
649 AddrSurfInfoIn
.flags
.opt4Space
= !AddrSurfInfoIn
.flags
.tcCompatible
&&
650 !AddrSurfInfoIn
.flags
.fmask
&&
651 config
->info
.samples
<= 1 &&
652 (surf
->flags
& RADEON_SURF_OPTIMIZE_FOR_SPACE
);
655 * - If we add MSAA support, keep in mind that CB can't decompress 8bpp
657 * - Mipmapped array textures have low performance (discovered by a closed
660 AddrSurfInfoIn
.flags
.dccCompatible
=
661 info
->chip_class
>= GFX8
&&
662 info
->has_graphics
&& /* disable DCC on compute-only chips */
663 !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
) &&
664 !(surf
->flags
& RADEON_SURF_DISABLE_DCC
) &&
666 ((config
->info
.array_size
== 1 && config
->info
.depth
== 1) ||
667 config
->info
.levels
== 1);
669 AddrSurfInfoIn
.flags
.noStencil
= (surf
->flags
& RADEON_SURF_SBUFFER
) == 0;
670 AddrSurfInfoIn
.flags
.compressZ
= !!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
);
672 /* On GFX7-GFX8, the DB uses the same pitch and tile mode (except tilesplit)
673 * for Z and stencil. This can cause a number of problems which we work
676 * - a depth part that is incompatible with mipmapped texturing
677 * - at least on Stoney, entirely incompatible Z/S aspects (e.g.
678 * incorrect tiling applied to the stencil part, stencil buffer
679 * memory accesses that go out of bounds) even without mipmapping
681 * Some piglit tests that are prone to different types of related
683 * ./bin/ext_framebuffer_multisample-upsample 2 stencil
684 * ./bin/framebuffer-blit-levels {draw,read} stencil
685 * ./bin/ext_framebuffer_multisample-unaligned-blit N {depth,stencil} {msaa,upsample,downsample}
686 * ./bin/fbo-depth-array fs-writes-{depth,stencil} / {depth,stencil}-{clear,layered-clear,draw}
687 * ./bin/depthstencil-render-miplevels 1024 d=s=z24_s8
689 int stencil_tile_idx
= -1;
691 if (AddrSurfInfoIn
.flags
.depth
&& !AddrSurfInfoIn
.flags
.noStencil
&&
692 (config
->info
.levels
> 1 || info
->family
== CHIP_STONEY
)) {
693 /* Compute stencilTileIdx that is compatible with the (depth)
694 * tileIdx. This degrades the depth surface if necessary to
695 * ensure that a matching stencilTileIdx exists. */
696 AddrSurfInfoIn
.flags
.matchStencilTileCfg
= 1;
698 /* Keep the depth mip-tail compatible with texturing. */
699 AddrSurfInfoIn
.flags
.noStencil
= 1;
702 /* Set preferred macrotile parameters. This is usually required
703 * for shared resources. This is for 2D tiling only. */
704 if (AddrSurfInfoIn
.tileMode
>= ADDR_TM_2D_TILED_THIN1
&&
705 surf
->u
.legacy
.bankw
&& surf
->u
.legacy
.bankh
&&
706 surf
->u
.legacy
.mtilea
&& surf
->u
.legacy
.tile_split
) {
707 /* If any of these parameters are incorrect, the calculation
709 AddrTileInfoIn
.banks
= surf
->u
.legacy
.num_banks
;
710 AddrTileInfoIn
.bankWidth
= surf
->u
.legacy
.bankw
;
711 AddrTileInfoIn
.bankHeight
= surf
->u
.legacy
.bankh
;
712 AddrTileInfoIn
.macroAspectRatio
= surf
->u
.legacy
.mtilea
;
713 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.tile_split
;
714 AddrTileInfoIn
.pipeConfig
= surf
->u
.legacy
.pipe_config
+ 1; /* +1 compared to GB_TILE_MODE */
715 AddrSurfInfoIn
.flags
.opt4Space
= 0;
716 AddrSurfInfoIn
.pTileInfo
= &AddrTileInfoIn
;
718 /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set
719 * the tile index, because we are expected to know it if
720 * we know the other parameters.
722 * This is something that can easily be fixed in Addrlib.
723 * For now, just figure it out here.
724 * Note that only 2D_TILE_THIN1 is handled here.
726 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
727 assert(AddrSurfInfoIn
.tileMode
== ADDR_TM_2D_TILED_THIN1
);
729 if (info
->chip_class
== GFX6
) {
730 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
) {
732 AddrSurfInfoIn
.tileIndex
= 11; /* 16bpp */
734 AddrSurfInfoIn
.tileIndex
= 12; /* 32bpp */
737 AddrSurfInfoIn
.tileIndex
= 14; /* 8bpp */
738 else if (surf
->bpe
== 2)
739 AddrSurfInfoIn
.tileIndex
= 15; /* 16bpp */
740 else if (surf
->bpe
== 4)
741 AddrSurfInfoIn
.tileIndex
= 16; /* 32bpp */
743 AddrSurfInfoIn
.tileIndex
= 17; /* 64bpp (and 128bpp) */
747 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
)
748 AddrSurfInfoIn
.tileIndex
= 10; /* 2D displayable */
750 AddrSurfInfoIn
.tileIndex
= 14; /* 2D non-displayable */
752 /* Addrlib doesn't set this if tileIndex is forced like above. */
753 AddrSurfInfoOut
.macroModeIndex
= cik_get_macro_tile_index(surf
);
757 surf
->has_stencil
= !!(surf
->flags
& RADEON_SURF_SBUFFER
);
758 surf
->num_dcc_levels
= 0;
761 surf
->dcc_alignment
= 1;
762 surf
->htile_size
= 0;
763 surf
->htile_slice_size
= 0;
764 surf
->htile_alignment
= 1;
766 const bool only_stencil
= (surf
->flags
& RADEON_SURF_SBUFFER
) &&
767 !(surf
->flags
& RADEON_SURF_ZBUFFER
);
769 /* Calculate texture layout information. */
771 for (level
= 0; level
< config
->info
.levels
; level
++) {
772 r
= gfx6_compute_level(addrlib
, config
, surf
, false, level
, compressed
,
773 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
774 &AddrDccIn
, &AddrDccOut
, &AddrHtileIn
, &AddrHtileOut
);
781 if (!AddrSurfInfoOut
.tcCompatible
) {
782 AddrSurfInfoIn
.flags
.tcCompatible
= 0;
783 surf
->flags
&= ~RADEON_SURF_TC_COMPATIBLE_HTILE
;
786 if (AddrSurfInfoIn
.flags
.matchStencilTileCfg
) {
787 AddrSurfInfoIn
.flags
.matchStencilTileCfg
= 0;
788 AddrSurfInfoIn
.tileIndex
= AddrSurfInfoOut
.tileIndex
;
789 stencil_tile_idx
= AddrSurfInfoOut
.stencilTileIdx
;
791 assert(stencil_tile_idx
>= 0);
794 r
= gfx6_surface_settings(addrlib
, info
, config
,
795 &AddrSurfInfoOut
, surf
);
801 /* Calculate texture layout information for stencil. */
802 if (surf
->flags
& RADEON_SURF_SBUFFER
) {
803 AddrSurfInfoIn
.tileIndex
= stencil_tile_idx
;
804 AddrSurfInfoIn
.bpp
= 8;
805 AddrSurfInfoIn
.flags
.depth
= 0;
806 AddrSurfInfoIn
.flags
.stencil
= 1;
807 AddrSurfInfoIn
.flags
.tcCompatible
= 0;
808 /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */
809 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.stencil_tile_split
;
811 for (level
= 0; level
< config
->info
.levels
; level
++) {
812 r
= gfx6_compute_level(addrlib
, config
, surf
, true, level
, compressed
,
813 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
814 &AddrDccIn
, &AddrDccOut
,
819 /* DB uses the depth pitch for both stencil and depth. */
821 if (surf
->u
.legacy
.stencil_level
[level
].nblk_x
!=
822 surf
->u
.legacy
.level
[level
].nblk_x
)
823 surf
->u
.legacy
.stencil_adjusted
= true;
825 surf
->u
.legacy
.level
[level
].nblk_x
=
826 surf
->u
.legacy
.stencil_level
[level
].nblk_x
;
831 r
= gfx6_surface_settings(addrlib
, info
, config
,
832 &AddrSurfInfoOut
, surf
);
837 /* For 2D modes only. */
838 if (AddrSurfInfoOut
.tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
839 surf
->u
.legacy
.stencil_tile_split
=
840 AddrSurfInfoOut
.pTileInfo
->tileSplitBytes
;
847 if (config
->info
.samples
>= 2 && AddrSurfInfoIn
.flags
.color
&&
848 info
->has_graphics
&& !(surf
->flags
& RADEON_SURF_NO_FMASK
)) {
849 ADDR_COMPUTE_FMASK_INFO_INPUT fin
= {0};
850 ADDR_COMPUTE_FMASK_INFO_OUTPUT fout
= {0};
851 ADDR_TILEINFO fmask_tile_info
= {};
853 fin
.size
= sizeof(fin
);
854 fout
.size
= sizeof(fout
);
856 fin
.tileMode
= AddrSurfInfoOut
.tileMode
;
857 fin
.pitch
= AddrSurfInfoOut
.pitch
;
858 fin
.height
= config
->info
.height
;
859 fin
.numSlices
= AddrSurfInfoIn
.numSlices
;
860 fin
.numSamples
= AddrSurfInfoIn
.numSamples
;
861 fin
.numFrags
= AddrSurfInfoIn
.numFrags
;
863 fout
.pTileInfo
= &fmask_tile_info
;
865 r
= AddrComputeFmaskInfo(addrlib
, &fin
, &fout
);
869 surf
->fmask_size
= fout
.fmaskBytes
;
870 surf
->fmask_alignment
= fout
.baseAlign
;
871 surf
->fmask_tile_swizzle
= 0;
873 surf
->u
.legacy
.fmask
.slice_tile_max
=
874 (fout
.pitch
* fout
.height
) / 64;
875 if (surf
->u
.legacy
.fmask
.slice_tile_max
)
876 surf
->u
.legacy
.fmask
.slice_tile_max
-= 1;
878 surf
->u
.legacy
.fmask
.tiling_index
= fout
.tileIndex
;
879 surf
->u
.legacy
.fmask
.bankh
= fout
.pTileInfo
->bankHeight
;
880 surf
->u
.legacy
.fmask
.pitch_in_pixels
= fout
.pitch
;
881 surf
->u
.legacy
.fmask
.slice_size
= fout
.sliceSize
;
883 /* Compute tile swizzle for FMASK. */
884 if (config
->info
.fmask_surf_index
&&
885 !(surf
->flags
& RADEON_SURF_SHAREABLE
)) {
886 ADDR_COMPUTE_BASE_SWIZZLE_INPUT xin
= {0};
887 ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT xout
= {0};
889 xin
.size
= sizeof(ADDR_COMPUTE_BASE_SWIZZLE_INPUT
);
890 xout
.size
= sizeof(ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT
);
892 /* This counter starts from 1 instead of 0. */
893 xin
.surfIndex
= p_atomic_inc_return(config
->info
.fmask_surf_index
);
894 xin
.tileIndex
= fout
.tileIndex
;
895 xin
.macroModeIndex
= fout
.macroModeIndex
;
896 xin
.pTileInfo
= fout
.pTileInfo
;
897 xin
.tileMode
= fin
.tileMode
;
899 int r
= AddrComputeBaseSwizzle(addrlib
, &xin
, &xout
);
903 assert(xout
.tileSwizzle
<=
904 u_bit_consecutive(0, sizeof(surf
->tile_swizzle
) * 8));
905 surf
->fmask_tile_swizzle
= xout
.tileSwizzle
;
909 /* Recalculate the whole DCC miptree size including disabled levels.
910 * This is what addrlib does, but calling addrlib would be a lot more
913 if (surf
->dcc_size
&& config
->info
.levels
> 1) {
914 /* The smallest miplevels that are never compressed by DCC
915 * still read the DCC buffer via TC if the base level uses DCC,
916 * and for some reason the DCC buffer needs to be larger if
917 * the miptree uses non-zero tile_swizzle. Otherwise there are
920 * "dcc_alignment * 4" was determined by trial and error.
922 surf
->dcc_size
= align64(surf
->surf_size
>> 8,
923 surf
->dcc_alignment
* 4);
926 /* Make sure HTILE covers the whole miptree, because the shader reads
927 * TC-compatible HTILE even for levels where it's disabled by DB.
929 if (surf
->htile_size
&& config
->info
.levels
> 1 &&
930 surf
->flags
& RADEON_SURF_TC_COMPATIBLE_HTILE
) {
931 /* MSAA can't occur with levels > 1, so ignore the sample count. */
932 const unsigned total_pixels
= surf
->surf_size
/ surf
->bpe
;
933 const unsigned htile_block_size
= 8 * 8;
934 const unsigned htile_element_size
= 4;
936 surf
->htile_size
= (total_pixels
/ htile_block_size
) *
938 surf
->htile_size
= align(surf
->htile_size
, surf
->htile_alignment
);
941 surf
->is_linear
= surf
->u
.legacy
.level
[0].mode
== RADEON_SURF_MODE_LINEAR_ALIGNED
;
942 surf
->is_displayable
= surf
->is_linear
||
943 surf
->micro_tile_mode
== RADEON_MICRO_MODE_DISPLAY
||
944 surf
->micro_tile_mode
== RADEON_MICRO_MODE_ROTATED
;
946 /* The rotated micro tile mode doesn't work if both CMASK and RB+ are
947 * used at the same time. This case is not currently expected to occur
948 * because we don't use rotated. Enforce this restriction on all chips
949 * to facilitate testing.
951 if (surf
->micro_tile_mode
== RADEON_MICRO_MODE_ROTATED
) {
952 assert(!"rotate micro tile mode is unsupported");
956 ac_compute_cmask(info
, config
, surf
);
960 /* This is only called when expecting a tiled layout. */
962 gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib
,
963 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
,
964 bool is_fmask
, AddrSwizzleMode
*swizzle_mode
)
966 ADDR_E_RETURNCODE ret
;
967 ADDR2_GET_PREFERRED_SURF_SETTING_INPUT sin
= {0};
968 ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT sout
= {0};
970 sin
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_INPUT
);
971 sout
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT
);
973 sin
.flags
= in
->flags
;
974 sin
.resourceType
= in
->resourceType
;
975 sin
.format
= in
->format
;
976 sin
.resourceLoction
= ADDR_RSRC_LOC_INVIS
;
977 /* TODO: We could allow some of these: */
978 sin
.forbiddenBlock
.micro
= 1; /* don't allow the 256B swizzle modes */
979 sin
.forbiddenBlock
.var
= 1; /* don't allow the variable-sized swizzle modes */
981 sin
.width
= in
->width
;
982 sin
.height
= in
->height
;
983 sin
.numSlices
= in
->numSlices
;
984 sin
.numMipLevels
= in
->numMipLevels
;
985 sin
.numSamples
= in
->numSamples
;
986 sin
.numFrags
= in
->numFrags
;
989 sin
.flags
.display
= 0;
994 ret
= Addr2GetPreferredSurfaceSetting(addrlib
, &sin
, &sout
);
998 *swizzle_mode
= sout
.swizzleMode
;
1002 static bool gfx9_is_dcc_capable(const struct radeon_info
*info
, unsigned sw_mode
)
1004 if (info
->chip_class
>= GFX10
)
1005 return sw_mode
== ADDR_SW_64KB_Z_X
|| sw_mode
== ADDR_SW_64KB_R_X
;
1007 return sw_mode
!= ADDR_SW_LINEAR
;
1010 static int gfx9_compute_miptree(ADDR_HANDLE addrlib
,
1011 const struct radeon_info
*info
,
1012 const struct ac_surf_config
*config
,
1013 struct radeon_surf
*surf
, bool compressed
,
1014 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
)
1016 ADDR2_MIP_INFO mip_info
[RADEON_SURF_MAX_LEVELS
] = {};
1017 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT out
= {0};
1018 ADDR_E_RETURNCODE ret
;
1020 out
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT
);
1021 out
.pMipInfo
= mip_info
;
1023 ret
= Addr2ComputeSurfaceInfo(addrlib
, in
, &out
);
1027 if (in
->flags
.stencil
) {
1028 surf
->u
.gfx9
.stencil
.swizzle_mode
= in
->swizzleMode
;
1029 surf
->u
.gfx9
.stencil
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
1030 out
.mipChainPitch
- 1;
1031 surf
->surf_alignment
= MAX2(surf
->surf_alignment
, out
.baseAlign
);
1032 surf
->u
.gfx9
.stencil_offset
= align(surf
->surf_size
, out
.baseAlign
);
1033 surf
->surf_size
= surf
->u
.gfx9
.stencil_offset
+ out
.surfSize
;
1037 surf
->u
.gfx9
.surf
.swizzle_mode
= in
->swizzleMode
;
1038 surf
->u
.gfx9
.surf
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
1039 out
.mipChainPitch
- 1;
1041 /* CMASK fast clear uses these even if FMASK isn't allocated.
1042 * FMASK only supports the Z swizzle modes, whose numbers are multiples of 4.
1044 surf
->u
.gfx9
.fmask
.swizzle_mode
= surf
->u
.gfx9
.surf
.swizzle_mode
& ~0x3;
1045 surf
->u
.gfx9
.fmask
.epitch
= surf
->u
.gfx9
.surf
.epitch
;
1047 surf
->u
.gfx9
.surf_slice_size
= out
.sliceSize
;
1048 surf
->u
.gfx9
.surf_pitch
= out
.pitch
;
1049 surf
->u
.gfx9
.surf_height
= out
.height
;
1050 surf
->surf_size
= out
.surfSize
;
1051 surf
->surf_alignment
= out
.baseAlign
;
1053 if (in
->swizzleMode
== ADDR_SW_LINEAR
) {
1054 for (unsigned i
= 0; i
< in
->numMipLevels
; i
++)
1055 surf
->u
.gfx9
.offset
[i
] = mip_info
[i
].offset
;
1058 if (in
->flags
.depth
) {
1059 assert(in
->swizzleMode
!= ADDR_SW_LINEAR
);
1061 if (surf
->flags
& RADEON_SURF_NO_HTILE
)
1065 ADDR2_COMPUTE_HTILE_INFO_INPUT hin
= {0};
1066 ADDR2_COMPUTE_HTILE_INFO_OUTPUT hout
= {0};
1068 hin
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT
);
1069 hout
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT
);
1071 hin
.hTileFlags
.pipeAligned
= !in
->flags
.metaPipeUnaligned
;
1072 hin
.hTileFlags
.rbAligned
= !in
->flags
.metaRbUnaligned
;
1073 hin
.depthFlags
= in
->flags
;
1074 hin
.swizzleMode
= in
->swizzleMode
;
1075 hin
.unalignedWidth
= in
->width
;
1076 hin
.unalignedHeight
= in
->height
;
1077 hin
.numSlices
= in
->numSlices
;
1078 hin
.numMipLevels
= in
->numMipLevels
;
1079 hin
.firstMipIdInTail
= out
.firstMipIdInTail
;
1081 ret
= Addr2ComputeHtileInfo(addrlib
, &hin
, &hout
);
1085 surf
->u
.gfx9
.htile
.rb_aligned
= hin
.hTileFlags
.rbAligned
;
1086 surf
->u
.gfx9
.htile
.pipe_aligned
= hin
.hTileFlags
.pipeAligned
;
1087 surf
->htile_size
= hout
.htileBytes
;
1088 surf
->htile_slice_size
= hout
.sliceSize
;
1089 surf
->htile_alignment
= hout
.baseAlign
;
1094 /* Compute tile swizzle for the color surface.
1095 * All *_X and *_T modes can use the swizzle.
1097 if (config
->info
.surf_index
&&
1098 in
->swizzleMode
>= ADDR_SW_64KB_Z_T
&&
1099 !out
.mipChainInTail
&&
1100 !(surf
->flags
& RADEON_SURF_SHAREABLE
) &&
1101 !in
->flags
.display
) {
1102 ADDR2_COMPUTE_PIPEBANKXOR_INPUT xin
= {0};
1103 ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT xout
= {0};
1105 xin
.size
= sizeof(ADDR2_COMPUTE_PIPEBANKXOR_INPUT
);
1106 xout
.size
= sizeof(ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT
);
1108 xin
.surfIndex
= p_atomic_inc_return(config
->info
.surf_index
) - 1;
1109 xin
.flags
= in
->flags
;
1110 xin
.swizzleMode
= in
->swizzleMode
;
1111 xin
.resourceType
= in
->resourceType
;
1112 xin
.format
= in
->format
;
1113 xin
.numSamples
= in
->numSamples
;
1114 xin
.numFrags
= in
->numFrags
;
1116 ret
= Addr2ComputePipeBankXor(addrlib
, &xin
, &xout
);
1120 assert(xout
.pipeBankXor
<=
1121 u_bit_consecutive(0, sizeof(surf
->tile_swizzle
) * 8));
1122 surf
->tile_swizzle
= xout
.pipeBankXor
;
1126 if (info
->has_graphics
&&
1127 !(surf
->flags
& RADEON_SURF_DISABLE_DCC
) &&
1129 gfx9_is_dcc_capable(info
, in
->swizzleMode
)) {
1130 ADDR2_COMPUTE_DCCINFO_INPUT din
= {0};
1131 ADDR2_COMPUTE_DCCINFO_OUTPUT dout
= {0};
1132 ADDR2_META_MIP_INFO meta_mip_info
[RADEON_SURF_MAX_LEVELS
] = {};
1134 din
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_INPUT
);
1135 dout
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT
);
1136 dout
.pMipInfo
= meta_mip_info
;
1138 din
.dccKeyFlags
.pipeAligned
= !in
->flags
.metaPipeUnaligned
;
1139 din
.dccKeyFlags
.rbAligned
= !in
->flags
.metaRbUnaligned
;
1140 din
.colorFlags
= in
->flags
;
1141 din
.resourceType
= in
->resourceType
;
1142 din
.swizzleMode
= in
->swizzleMode
;
1144 din
.unalignedWidth
= in
->width
;
1145 din
.unalignedHeight
= in
->height
;
1146 din
.numSlices
= in
->numSlices
;
1147 din
.numFrags
= in
->numFrags
;
1148 din
.numMipLevels
= in
->numMipLevels
;
1149 din
.dataSurfaceSize
= out
.surfSize
;
1150 din
.firstMipIdInTail
= out
.firstMipIdInTail
;
1152 ret
= Addr2ComputeDccInfo(addrlib
, &din
, &dout
);
1156 surf
->u
.gfx9
.dcc
.rb_aligned
= din
.dccKeyFlags
.rbAligned
;
1157 surf
->u
.gfx9
.dcc
.pipe_aligned
= din
.dccKeyFlags
.pipeAligned
;
1158 surf
->dcc_size
= dout
.dccRamSize
;
1159 surf
->dcc_alignment
= dout
.dccRamBaseAlign
;
1160 surf
->num_dcc_levels
= in
->numMipLevels
;
1162 /* Disable DCC for levels that are in the mip tail.
1164 * There are two issues that this is intended to
1167 * 1. Multiple mip levels may share a cache line. This
1168 * can lead to corruption when switching between
1169 * rendering to different mip levels because the
1170 * RBs don't maintain coherency.
1172 * 2. Texturing with metadata after rendering sometimes
1173 * fails with corruption, probably for a similar
1176 * Working around these issues for all levels in the
1177 * mip tail may be overly conservative, but it's what
1180 * Alternative solutions that also work but are worse:
1181 * - Disable DCC entirely.
1182 * - Flush TC L2 after rendering.
1184 for (unsigned i
= 0; i
< in
->numMipLevels
; i
++) {
1185 if (meta_mip_info
[i
].inMiptail
) {
1186 surf
->num_dcc_levels
= i
;
1191 if (!surf
->num_dcc_levels
)
1194 surf
->u
.gfx9
.display_dcc_size
= surf
->dcc_size
;
1195 surf
->u
.gfx9
.display_dcc_alignment
= surf
->dcc_alignment
;
1196 surf
->u
.gfx9
.display_dcc_pitch_max
= dout
.pitch
- 1;
1198 /* Compute displayable DCC. */
1199 if (in
->flags
.display
&&
1200 surf
->num_dcc_levels
&&
1201 info
->use_display_dcc_with_retile_blit
) {
1202 /* Compute displayable DCC info. */
1203 din
.dccKeyFlags
.pipeAligned
= 0;
1204 din
.dccKeyFlags
.rbAligned
= 0;
1206 assert(din
.numSlices
== 1);
1207 assert(din
.numMipLevels
== 1);
1208 assert(din
.numFrags
== 1);
1209 assert(surf
->tile_swizzle
== 0);
1210 assert(surf
->u
.gfx9
.dcc
.pipe_aligned
||
1211 surf
->u
.gfx9
.dcc
.rb_aligned
);
1213 ret
= Addr2ComputeDccInfo(addrlib
, &din
, &dout
);
1217 surf
->u
.gfx9
.display_dcc_size
= dout
.dccRamSize
;
1218 surf
->u
.gfx9
.display_dcc_alignment
= dout
.dccRamBaseAlign
;
1219 surf
->u
.gfx9
.display_dcc_pitch_max
= dout
.pitch
- 1;
1220 assert(surf
->u
.gfx9
.display_dcc_size
<= surf
->dcc_size
);
1222 /* Compute address mapping from non-displayable to displayable DCC. */
1223 ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT addrin
= {};
1224 addrin
.size
= sizeof(addrin
);
1225 addrin
.colorFlags
.color
= 1;
1226 addrin
.swizzleMode
= din
.swizzleMode
;
1227 addrin
.resourceType
= din
.resourceType
;
1228 addrin
.bpp
= din
.bpp
;
1229 addrin
.unalignedWidth
= din
.unalignedWidth
;
1230 addrin
.unalignedHeight
= din
.unalignedHeight
;
1231 addrin
.numSlices
= 1;
1232 addrin
.numMipLevels
= 1;
1233 addrin
.numFrags
= 1;
1235 ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT addrout
= {};
1236 addrout
.size
= sizeof(addrout
);
1238 surf
->u
.gfx9
.dcc_retile_num_elements
=
1239 DIV_ROUND_UP(in
->width
, dout
.compressBlkWidth
) *
1240 DIV_ROUND_UP(in
->height
, dout
.compressBlkHeight
) * 2;
1241 /* Align the size to 4 (for the compute shader). */
1242 surf
->u
.gfx9
.dcc_retile_num_elements
=
1243 align(surf
->u
.gfx9
.dcc_retile_num_elements
, 4);
1245 surf
->u
.gfx9
.dcc_retile_map
=
1246 malloc(surf
->u
.gfx9
.dcc_retile_num_elements
* 4);
1247 if (!surf
->u
.gfx9
.dcc_retile_map
)
1248 return ADDR_OUTOFMEMORY
;
1251 surf
->u
.gfx9
.dcc_retile_use_uint16
= true;
1253 for (unsigned y
= 0; y
< in
->height
; y
+= dout
.compressBlkHeight
) {
1256 for (unsigned x
= 0; x
< in
->width
; x
+= dout
.compressBlkWidth
) {
1259 /* Compute src DCC address */
1260 addrin
.dccKeyFlags
.pipeAligned
= surf
->u
.gfx9
.dcc
.pipe_aligned
;
1261 addrin
.dccKeyFlags
.rbAligned
= surf
->u
.gfx9
.dcc
.rb_aligned
;
1264 ret
= Addr2ComputeDccAddrFromCoord(addrlib
, &addrin
, &addrout
);
1268 surf
->u
.gfx9
.dcc_retile_map
[index
* 2] = addrout
.addr
;
1269 if (addrout
.addr
> UINT16_MAX
)
1270 surf
->u
.gfx9
.dcc_retile_use_uint16
= false;
1272 /* Compute dst DCC address */
1273 addrin
.dccKeyFlags
.pipeAligned
= 0;
1274 addrin
.dccKeyFlags
.rbAligned
= 0;
1277 ret
= Addr2ComputeDccAddrFromCoord(addrlib
, &addrin
, &addrout
);
1281 surf
->u
.gfx9
.dcc_retile_map
[index
* 2 + 1] = addrout
.addr
;
1282 if (addrout
.addr
> UINT16_MAX
)
1283 surf
->u
.gfx9
.dcc_retile_use_uint16
= false;
1285 assert(index
* 2 + 1 < surf
->u
.gfx9
.dcc_retile_num_elements
);
1289 /* Fill the remaining pairs with the last one (for the compute shader). */
1290 for (unsigned i
= index
* 2; i
< surf
->u
.gfx9
.dcc_retile_num_elements
; i
++)
1291 surf
->u
.gfx9
.dcc_retile_map
[i
] = surf
->u
.gfx9
.dcc_retile_map
[i
- 2];
1296 if (in
->numSamples
> 1 && info
->has_graphics
&&
1297 !(surf
->flags
& RADEON_SURF_NO_FMASK
)) {
1298 ADDR2_COMPUTE_FMASK_INFO_INPUT fin
= {0};
1299 ADDR2_COMPUTE_FMASK_INFO_OUTPUT fout
= {0};
1301 fin
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT
);
1302 fout
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT
);
1304 ret
= gfx9_get_preferred_swizzle_mode(addrlib
, in
,
1305 true, &fin
.swizzleMode
);
1309 fin
.unalignedWidth
= in
->width
;
1310 fin
.unalignedHeight
= in
->height
;
1311 fin
.numSlices
= in
->numSlices
;
1312 fin
.numSamples
= in
->numSamples
;
1313 fin
.numFrags
= in
->numFrags
;
1315 ret
= Addr2ComputeFmaskInfo(addrlib
, &fin
, &fout
);
1319 surf
->u
.gfx9
.fmask
.swizzle_mode
= fin
.swizzleMode
;
1320 surf
->u
.gfx9
.fmask
.epitch
= fout
.pitch
- 1;
1321 surf
->fmask_size
= fout
.fmaskBytes
;
1322 surf
->fmask_alignment
= fout
.baseAlign
;
1324 /* Compute tile swizzle for the FMASK surface. */
1325 if (config
->info
.fmask_surf_index
&&
1326 fin
.swizzleMode
>= ADDR_SW_64KB_Z_T
&&
1327 !(surf
->flags
& RADEON_SURF_SHAREABLE
)) {
1328 ADDR2_COMPUTE_PIPEBANKXOR_INPUT xin
= {0};
1329 ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT xout
= {0};
1331 xin
.size
= sizeof(ADDR2_COMPUTE_PIPEBANKXOR_INPUT
);
1332 xout
.size
= sizeof(ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT
);
1334 /* This counter starts from 1 instead of 0. */
1335 xin
.surfIndex
= p_atomic_inc_return(config
->info
.fmask_surf_index
);
1336 xin
.flags
= in
->flags
;
1337 xin
.swizzleMode
= fin
.swizzleMode
;
1338 xin
.resourceType
= in
->resourceType
;
1339 xin
.format
= in
->format
;
1340 xin
.numSamples
= in
->numSamples
;
1341 xin
.numFrags
= in
->numFrags
;
1343 ret
= Addr2ComputePipeBankXor(addrlib
, &xin
, &xout
);
1347 assert(xout
.pipeBankXor
<=
1348 u_bit_consecutive(0, sizeof(surf
->fmask_tile_swizzle
) * 8));
1349 surf
->fmask_tile_swizzle
= xout
.pipeBankXor
;
1353 /* CMASK -- on GFX10 only for FMASK */
1354 if (in
->swizzleMode
!= ADDR_SW_LINEAR
&&
1355 in
->resourceType
== ADDR_RSRC_TEX_2D
&&
1356 ((info
->chip_class
<= GFX9
&& in
->numSamples
== 1) ||
1357 (surf
->fmask_size
&& in
->numSamples
>= 2))) {
1358 ADDR2_COMPUTE_CMASK_INFO_INPUT cin
= {0};
1359 ADDR2_COMPUTE_CMASK_INFO_OUTPUT cout
= {0};
1361 cin
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT
);
1362 cout
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT
);
1364 if (in
->numSamples
> 1) {
1365 /* FMASK is always aligned. */
1366 cin
.cMaskFlags
.pipeAligned
= 1;
1367 cin
.cMaskFlags
.rbAligned
= 1;
1369 cin
.cMaskFlags
.pipeAligned
= !in
->flags
.metaPipeUnaligned
;
1370 cin
.cMaskFlags
.rbAligned
= !in
->flags
.metaRbUnaligned
;
1372 cin
.colorFlags
= in
->flags
;
1373 cin
.resourceType
= in
->resourceType
;
1374 cin
.unalignedWidth
= in
->width
;
1375 cin
.unalignedHeight
= in
->height
;
1376 cin
.numSlices
= in
->numSlices
;
1378 if (in
->numSamples
> 1)
1379 cin
.swizzleMode
= surf
->u
.gfx9
.fmask
.swizzle_mode
;
1381 cin
.swizzleMode
= in
->swizzleMode
;
1383 ret
= Addr2ComputeCmaskInfo(addrlib
, &cin
, &cout
);
1387 surf
->u
.gfx9
.cmask
.rb_aligned
= cin
.cMaskFlags
.rbAligned
;
1388 surf
->u
.gfx9
.cmask
.pipe_aligned
= cin
.cMaskFlags
.pipeAligned
;
1389 surf
->cmask_size
= cout
.cmaskBytes
;
1390 surf
->cmask_alignment
= cout
.baseAlign
;
1397 static int gfx9_compute_surface(ADDR_HANDLE addrlib
,
1398 const struct radeon_info
*info
,
1399 const struct ac_surf_config
*config
,
1400 enum radeon_surf_mode mode
,
1401 struct radeon_surf
*surf
)
1404 ADDR2_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
1407 AddrSurfInfoIn
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT
);
1409 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
1411 /* The format must be set correctly for the allocation of compressed
1412 * textures to work. In other cases, setting the bpp is sufficient. */
1414 switch (surf
->bpe
) {
1416 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
1419 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
1425 switch (surf
->bpe
) {
1427 assert(!(surf
->flags
& RADEON_SURF_ZBUFFER
));
1428 AddrSurfInfoIn
.format
= ADDR_FMT_8
;
1431 assert(surf
->flags
& RADEON_SURF_ZBUFFER
||
1432 !(surf
->flags
& RADEON_SURF_SBUFFER
));
1433 AddrSurfInfoIn
.format
= ADDR_FMT_16
;
1436 assert(surf
->flags
& RADEON_SURF_ZBUFFER
||
1437 !(surf
->flags
& RADEON_SURF_SBUFFER
));
1438 AddrSurfInfoIn
.format
= ADDR_FMT_32
;
1441 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
1442 AddrSurfInfoIn
.format
= ADDR_FMT_32_32
;
1445 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
1446 AddrSurfInfoIn
.format
= ADDR_FMT_32_32_32
;
1449 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
1450 AddrSurfInfoIn
.format
= ADDR_FMT_32_32_32_32
;
1455 AddrSurfInfoIn
.bpp
= surf
->bpe
* 8;
1458 bool is_color_surface
= !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
);
1459 AddrSurfInfoIn
.flags
.color
= is_color_surface
&&
1460 !(surf
->flags
& RADEON_SURF_NO_RENDER_TARGET
);
1461 AddrSurfInfoIn
.flags
.depth
= (surf
->flags
& RADEON_SURF_ZBUFFER
) != 0;
1462 AddrSurfInfoIn
.flags
.display
= get_display_flag(config
, surf
);
1463 /* flags.texture currently refers to TC-compatible HTILE */
1464 AddrSurfInfoIn
.flags
.texture
= is_color_surface
||
1465 surf
->flags
& RADEON_SURF_TC_COMPATIBLE_HTILE
;
1466 AddrSurfInfoIn
.flags
.opt4space
= 1;
1468 AddrSurfInfoIn
.numMipLevels
= config
->info
.levels
;
1469 AddrSurfInfoIn
.numSamples
= MAX2(1, config
->info
.samples
);
1470 AddrSurfInfoIn
.numFrags
= AddrSurfInfoIn
.numSamples
;
1472 if (!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
))
1473 AddrSurfInfoIn
.numFrags
= MAX2(1, config
->info
.storage_samples
);
1475 /* GFX9 doesn't support 1D depth textures, so allocate all 1D textures
1476 * as 2D to avoid having shader variants for 1D vs 2D, so all shaders
1477 * must sample 1D textures as 2D. */
1479 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_3D
;
1480 else if (info
->chip_class
!= GFX9
&& config
->is_1d
)
1481 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_1D
;
1483 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_2D
;
1485 AddrSurfInfoIn
.width
= config
->info
.width
;
1486 AddrSurfInfoIn
.height
= config
->info
.height
;
1489 AddrSurfInfoIn
.numSlices
= config
->info
.depth
;
1490 else if (config
->is_cube
)
1491 AddrSurfInfoIn
.numSlices
= 6;
1493 AddrSurfInfoIn
.numSlices
= config
->info
.array_size
;
1495 /* This is propagated to HTILE/DCC/CMASK. */
1496 AddrSurfInfoIn
.flags
.metaPipeUnaligned
= 0;
1497 AddrSurfInfoIn
.flags
.metaRbUnaligned
= 0;
1499 /* The display hardware can only read DCC with RB_ALIGNED=0 and
1500 * PIPE_ALIGNED=0. PIPE_ALIGNED really means L2CACHE_ALIGNED.
1502 * The CB block requires RB_ALIGNED=1 except 1 RB chips.
1503 * PIPE_ALIGNED is optional, but PIPE_ALIGNED=0 requires L2 flushes
1504 * after rendering, so PIPE_ALIGNED=1 is recommended.
1506 if (info
->use_display_dcc_unaligned
&& is_color_surface
&&
1507 AddrSurfInfoIn
.flags
.display
) {
1508 AddrSurfInfoIn
.flags
.metaPipeUnaligned
= 1;
1509 AddrSurfInfoIn
.flags
.metaRbUnaligned
= 1;
1513 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
1514 assert(config
->info
.samples
<= 1);
1515 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
1516 AddrSurfInfoIn
.swizzleMode
= ADDR_SW_LINEAR
;
1519 case RADEON_SURF_MODE_1D
:
1520 case RADEON_SURF_MODE_2D
:
1521 if (surf
->flags
& (RADEON_SURF_IMPORTED
| RADEON_SURF_FORCE_SWIZZLE_MODE
)) {
1522 AddrSurfInfoIn
.swizzleMode
= surf
->u
.gfx9
.surf
.swizzle_mode
;
1526 r
= gfx9_get_preferred_swizzle_mode(addrlib
, &AddrSurfInfoIn
,
1527 false, &AddrSurfInfoIn
.swizzleMode
);
1536 surf
->u
.gfx9
.resource_type
= AddrSurfInfoIn
.resourceType
;
1537 surf
->has_stencil
= !!(surf
->flags
& RADEON_SURF_SBUFFER
);
1539 surf
->num_dcc_levels
= 0;
1540 surf
->surf_size
= 0;
1541 surf
->fmask_size
= 0;
1543 surf
->htile_size
= 0;
1544 surf
->htile_slice_size
= 0;
1545 surf
->u
.gfx9
.surf_offset
= 0;
1546 surf
->u
.gfx9
.stencil_offset
= 0;
1547 surf
->cmask_size
= 0;
1548 surf
->u
.gfx9
.dcc_retile_use_uint16
= false;
1549 surf
->u
.gfx9
.dcc_retile_num_elements
= 0;
1550 surf
->u
.gfx9
.dcc_retile_map
= NULL
;
1552 /* Calculate texture layout information. */
1553 r
= gfx9_compute_miptree(addrlib
, info
, config
, surf
, compressed
,
1558 /* Calculate texture layout information for stencil. */
1559 if (surf
->flags
& RADEON_SURF_SBUFFER
) {
1560 AddrSurfInfoIn
.flags
.stencil
= 1;
1561 AddrSurfInfoIn
.bpp
= 8;
1562 AddrSurfInfoIn
.format
= ADDR_FMT_8
;
1564 if (!AddrSurfInfoIn
.flags
.depth
) {
1565 r
= gfx9_get_preferred_swizzle_mode(addrlib
, &AddrSurfInfoIn
,
1566 false, &AddrSurfInfoIn
.swizzleMode
);
1570 AddrSurfInfoIn
.flags
.depth
= 0;
1572 r
= gfx9_compute_miptree(addrlib
, info
, config
, surf
, compressed
,
1578 surf
->is_linear
= surf
->u
.gfx9
.surf
.swizzle_mode
== ADDR_SW_LINEAR
;
1580 /* Query whether the surface is displayable. */
1581 bool displayable
= false;
1582 if (!config
->is_3d
&& !config
->is_cube
) {
1583 r
= Addr2IsValidDisplaySwizzleMode(addrlib
, surf
->u
.gfx9
.surf
.swizzle_mode
,
1584 surf
->bpe
* 8, &displayable
);
1588 /* Display needs unaligned DCC. */
1589 if (info
->use_display_dcc_unaligned
&&
1590 surf
->num_dcc_levels
&&
1591 (surf
->u
.gfx9
.dcc
.pipe_aligned
||
1592 surf
->u
.gfx9
.dcc
.rb_aligned
))
1593 displayable
= false;
1595 surf
->is_displayable
= displayable
;
1597 switch (surf
->u
.gfx9
.surf
.swizzle_mode
) {
1599 case ADDR_SW_256B_S
:
1601 case ADDR_SW_64KB_S
:
1602 case ADDR_SW_64KB_S_T
:
1603 case ADDR_SW_4KB_S_X
:
1604 case ADDR_SW_64KB_S_X
:
1605 surf
->micro_tile_mode
= RADEON_MICRO_MODE_THIN
;
1609 case ADDR_SW_LINEAR
:
1610 case ADDR_SW_256B_D
:
1612 case ADDR_SW_64KB_D
:
1613 case ADDR_SW_64KB_D_T
:
1614 case ADDR_SW_4KB_D_X
:
1615 case ADDR_SW_64KB_D_X
:
1616 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DISPLAY
;
1619 /* R = rotated (gfx9), render target (gfx10). */
1620 case ADDR_SW_256B_R
:
1622 case ADDR_SW_64KB_R
:
1623 case ADDR_SW_64KB_R_T
:
1624 case ADDR_SW_4KB_R_X
:
1625 case ADDR_SW_64KB_R_X
:
1626 case ADDR_SW_VAR_R_X
:
1627 /* The rotated micro tile mode doesn't work if both CMASK and RB+ are
1628 * used at the same time. We currently do not use rotated
1631 assert(info
->chip_class
>= GFX10
||
1632 !"rotate micro tile mode is unsupported");
1633 surf
->micro_tile_mode
= RADEON_MICRO_MODE_ROTATED
;
1638 case ADDR_SW_64KB_Z
:
1639 case ADDR_SW_64KB_Z_T
:
1640 case ADDR_SW_4KB_Z_X
:
1641 case ADDR_SW_64KB_Z_X
:
1642 case ADDR_SW_VAR_Z_X
:
1643 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DEPTH
;
1653 free(surf
->u
.gfx9
.dcc_retile_map
);
1654 surf
->u
.gfx9
.dcc_retile_map
= NULL
;
1658 int ac_compute_surface(ADDR_HANDLE addrlib
, const struct radeon_info
*info
,
1659 const struct ac_surf_config
*config
,
1660 enum radeon_surf_mode mode
,
1661 struct radeon_surf
*surf
)
1665 r
= surf_config_sanity(config
, surf
->flags
);
1669 if (info
->chip_class
>= GFX9
)
1670 r
= gfx9_compute_surface(addrlib
, info
, config
, mode
, surf
);
1672 r
= gfx6_compute_surface(addrlib
, info
, config
, mode
, surf
);
1677 /* Determine the memory layout of multiple allocations in one buffer. */
1678 surf
->total_size
= surf
->surf_size
;
1680 if (surf
->htile_size
) {
1681 surf
->htile_offset
= align64(surf
->total_size
, surf
->htile_alignment
);
1682 surf
->total_size
= surf
->htile_offset
+ surf
->htile_size
;
1685 if (surf
->fmask_size
) {
1686 assert(config
->info
.samples
>= 2);
1687 surf
->fmask_offset
= align64(surf
->total_size
, surf
->fmask_alignment
);
1688 surf
->total_size
= surf
->fmask_offset
+ surf
->fmask_size
;
1691 /* Single-sample CMASK is in a separate buffer. */
1692 if (surf
->cmask_size
&& config
->info
.samples
>= 2) {
1693 surf
->cmask_offset
= align64(surf
->total_size
, surf
->cmask_alignment
);
1694 surf
->total_size
= surf
->cmask_offset
+ surf
->cmask_size
;
1697 if (surf
->dcc_size
&&
1698 (info
->use_display_dcc_unaligned
||
1699 info
->use_display_dcc_with_retile_blit
||
1700 !(surf
->flags
& RADEON_SURF_SCANOUT
))) {
1701 surf
->dcc_offset
= align64(surf
->total_size
, surf
->dcc_alignment
);
1702 surf
->total_size
= surf
->dcc_offset
+ surf
->dcc_size
;
1704 if (info
->chip_class
>= GFX9
&&
1705 surf
->u
.gfx9
.dcc_retile_num_elements
) {
1706 /* Add space for the displayable DCC buffer. */
1707 surf
->display_dcc_offset
=
1708 align64(surf
->total_size
, surf
->u
.gfx9
.display_dcc_alignment
);
1709 surf
->total_size
= surf
->display_dcc_offset
+
1710 surf
->u
.gfx9
.display_dcc_size
;
1712 /* Add space for the DCC retile buffer. (16-bit or 32-bit elements) */
1713 surf
->dcc_retile_map_offset
=
1714 align64(surf
->total_size
, info
->tcc_cache_line_size
);
1716 if (surf
->u
.gfx9
.dcc_retile_use_uint16
) {
1717 surf
->total_size
= surf
->dcc_retile_map_offset
+
1718 surf
->u
.gfx9
.dcc_retile_num_elements
* 2;
1720 surf
->total_size
= surf
->dcc_retile_map_offset
+
1721 surf
->u
.gfx9
.dcc_retile_num_elements
* 4;