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 "amdgpu_id.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/addrinterface.h"
44 #ifndef CIASICIDGFXENGINE_SOUTHERNISLAND
45 #define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A
48 #ifndef CIASICIDGFXENGINE_ARCTICISLAND
49 #define CIASICIDGFXENGINE_ARCTICISLAND 0x0000000D
52 static void addrlib_family_rev_id(enum radeon_family family
,
53 unsigned *addrlib_family
,
54 unsigned *addrlib_revid
)
58 *addrlib_family
= FAMILY_SI
;
59 *addrlib_revid
= SI_TAHITI_P_A0
;
62 *addrlib_family
= FAMILY_SI
;
63 *addrlib_revid
= SI_PITCAIRN_PM_A0
;
66 *addrlib_family
= FAMILY_SI
;
67 *addrlib_revid
= SI_CAPEVERDE_M_A0
;
70 *addrlib_family
= FAMILY_SI
;
71 *addrlib_revid
= SI_OLAND_M_A0
;
74 *addrlib_family
= FAMILY_SI
;
75 *addrlib_revid
= SI_HAINAN_V_A0
;
78 *addrlib_family
= FAMILY_CI
;
79 *addrlib_revid
= CI_BONAIRE_M_A0
;
82 *addrlib_family
= FAMILY_KV
;
83 *addrlib_revid
= KV_SPECTRE_A0
;
86 *addrlib_family
= FAMILY_KV
;
87 *addrlib_revid
= KB_KALINDI_A0
;
90 *addrlib_family
= FAMILY_CI
;
91 *addrlib_revid
= CI_HAWAII_P_A0
;
94 *addrlib_family
= FAMILY_KV
;
95 *addrlib_revid
= ML_GODAVARI_A0
;
98 *addrlib_family
= FAMILY_VI
;
99 *addrlib_revid
= VI_TONGA_P_A0
;
102 *addrlib_family
= FAMILY_VI
;
103 *addrlib_revid
= VI_ICELAND_M_A0
;
106 *addrlib_family
= FAMILY_CZ
;
107 *addrlib_revid
= CARRIZO_A0
;
110 *addrlib_family
= FAMILY_CZ
;
111 *addrlib_revid
= STONEY_A0
;
114 *addrlib_family
= FAMILY_VI
;
115 *addrlib_revid
= VI_FIJI_P_A0
;
118 *addrlib_family
= FAMILY_VI
;
119 *addrlib_revid
= VI_POLARIS10_P_A0
;
122 *addrlib_family
= FAMILY_VI
;
123 *addrlib_revid
= VI_POLARIS11_M_A0
;
126 *addrlib_family
= FAMILY_VI
;
127 *addrlib_revid
= VI_POLARIS12_V_A0
;
130 *addrlib_family
= FAMILY_AI
;
131 *addrlib_revid
= AI_VEGA10_P_A0
;
134 *addrlib_family
= FAMILY_RV
;
135 *addrlib_revid
= RAVEN_A0
;
138 fprintf(stderr
, "amdgpu: Unknown family.\n");
142 static void *ADDR_API
allocSysMem(const ADDR_ALLOCSYSMEM_INPUT
* pInput
)
144 return malloc(pInput
->sizeInBytes
);
147 static ADDR_E_RETURNCODE ADDR_API
freeSysMem(const ADDR_FREESYSMEM_INPUT
* pInput
)
149 free(pInput
->pVirtAddr
);
153 ADDR_HANDLE
amdgpu_addr_create(const struct radeon_info
*info
,
154 const struct amdgpu_gpu_info
*amdinfo
,
155 uint64_t *max_alignment
)
157 ADDR_CREATE_INPUT addrCreateInput
= {0};
158 ADDR_CREATE_OUTPUT addrCreateOutput
= {0};
159 ADDR_REGISTER_VALUE regValue
= {0};
160 ADDR_CREATE_FLAGS createFlags
= {{0}};
161 ADDR_GET_MAX_ALIGNMENTS_OUTPUT addrGetMaxAlignmentsOutput
= {0};
162 ADDR_E_RETURNCODE addrRet
;
164 addrCreateInput
.size
= sizeof(ADDR_CREATE_INPUT
);
165 addrCreateOutput
.size
= sizeof(ADDR_CREATE_OUTPUT
);
167 regValue
.gbAddrConfig
= amdinfo
->gb_addr_cfg
;
168 createFlags
.value
= 0;
170 addrlib_family_rev_id(info
->family
, &addrCreateInput
.chipFamily
, &addrCreateInput
.chipRevision
);
171 if (addrCreateInput
.chipFamily
== FAMILY_UNKNOWN
)
174 if (addrCreateInput
.chipFamily
>= FAMILY_AI
) {
175 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_ARCTICISLAND
;
176 regValue
.blockVarSizeLog2
= 0;
178 regValue
.noOfBanks
= amdinfo
->mc_arb_ramcfg
& 0x3;
179 regValue
.noOfRanks
= (amdinfo
->mc_arb_ramcfg
& 0x4) >> 2;
181 regValue
.backendDisables
= amdinfo
->enabled_rb_pipes_mask
;
182 regValue
.pTileConfig
= amdinfo
->gb_tile_mode
;
183 regValue
.noOfEntries
= ARRAY_SIZE(amdinfo
->gb_tile_mode
);
184 if (addrCreateInput
.chipFamily
== FAMILY_SI
) {
185 regValue
.pMacroTileConfig
= NULL
;
186 regValue
.noOfMacroEntries
= 0;
188 regValue
.pMacroTileConfig
= amdinfo
->gb_macro_tile_mode
;
189 regValue
.noOfMacroEntries
= ARRAY_SIZE(amdinfo
->gb_macro_tile_mode
);
192 createFlags
.useTileIndex
= 1;
193 createFlags
.useHtileSliceAlign
= 1;
195 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_SOUTHERNISLAND
;
198 addrCreateInput
.callbacks
.allocSysMem
= allocSysMem
;
199 addrCreateInput
.callbacks
.freeSysMem
= freeSysMem
;
200 addrCreateInput
.callbacks
.debugPrint
= 0;
201 addrCreateInput
.createFlags
= createFlags
;
202 addrCreateInput
.regValue
= regValue
;
204 addrRet
= AddrCreate(&addrCreateInput
, &addrCreateOutput
);
205 if (addrRet
!= ADDR_OK
)
209 addrRet
= AddrGetMaxAlignments(addrCreateOutput
.hLib
, &addrGetMaxAlignmentsOutput
);
210 if (addrRet
== ADDR_OK
){
211 *max_alignment
= addrGetMaxAlignmentsOutput
.baseAlign
;
214 return addrCreateOutput
.hLib
;
217 static int surf_config_sanity(const struct ac_surf_config
*config
)
219 /* all dimension must be at least 1 ! */
220 if (!config
->info
.width
|| !config
->info
.height
|| !config
->info
.depth
||
221 !config
->info
.array_size
|| !config
->info
.levels
)
224 switch (config
->info
.samples
) {
235 if (config
->is_3d
&& config
->info
.array_size
> 1)
237 if (config
->is_cube
&& config
->info
.depth
> 1)
243 static int gfx6_compute_level(ADDR_HANDLE addrlib
,
244 const struct ac_surf_config
*config
,
245 struct radeon_surf
*surf
, bool is_stencil
,
246 unsigned level
, bool compressed
,
247 ADDR_COMPUTE_SURFACE_INFO_INPUT
*AddrSurfInfoIn
,
248 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
*AddrSurfInfoOut
,
249 ADDR_COMPUTE_DCCINFO_INPUT
*AddrDccIn
,
250 ADDR_COMPUTE_DCCINFO_OUTPUT
*AddrDccOut
,
251 ADDR_COMPUTE_HTILE_INFO_INPUT
*AddrHtileIn
,
252 ADDR_COMPUTE_HTILE_INFO_OUTPUT
*AddrHtileOut
)
254 struct legacy_surf_level
*surf_level
;
255 ADDR_E_RETURNCODE ret
;
257 AddrSurfInfoIn
->mipLevel
= level
;
258 AddrSurfInfoIn
->width
= u_minify(config
->info
.width
, level
);
259 AddrSurfInfoIn
->height
= u_minify(config
->info
.height
, level
);
261 /* Make GFX6 linear surfaces compatible with GFX9 for hybrid graphics,
262 * because GFX9 needs linear alignment of 256 bytes.
264 if (config
->info
.levels
== 1 &&
265 AddrSurfInfoIn
->tileMode
== ADDR_TM_LINEAR_ALIGNED
&&
266 AddrSurfInfoIn
->bpp
) {
267 unsigned alignment
= 256 / (AddrSurfInfoIn
->bpp
/ 8);
269 assert(util_is_power_of_two(AddrSurfInfoIn
->bpp
));
270 AddrSurfInfoIn
->width
= align(AddrSurfInfoIn
->width
, alignment
);
274 AddrSurfInfoIn
->numSlices
= u_minify(config
->info
.depth
, level
);
275 else if (config
->is_cube
)
276 AddrSurfInfoIn
->numSlices
= 6;
278 AddrSurfInfoIn
->numSlices
= config
->info
.array_size
;
281 /* Set the base level pitch. This is needed for calculation
282 * of non-zero levels. */
284 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.stencil_level
[0].nblk_x
;
286 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.level
[0].nblk_x
;
288 /* Convert blocks to pixels for compressed formats. */
290 AddrSurfInfoIn
->basePitch
*= surf
->blk_w
;
293 ret
= AddrComputeSurfaceInfo(addrlib
,
296 if (ret
!= ADDR_OK
) {
300 surf_level
= is_stencil
? &surf
->u
.legacy
.stencil_level
[level
] : &surf
->u
.legacy
.level
[level
];
301 surf_level
->offset
= align64(surf
->surf_size
, AddrSurfInfoOut
->baseAlign
);
302 surf_level
->slice_size
= AddrSurfInfoOut
->sliceSize
;
303 surf_level
->nblk_x
= AddrSurfInfoOut
->pitch
;
304 surf_level
->nblk_y
= AddrSurfInfoOut
->height
;
306 switch (AddrSurfInfoOut
->tileMode
) {
307 case ADDR_TM_LINEAR_ALIGNED
:
308 surf_level
->mode
= RADEON_SURF_MODE_LINEAR_ALIGNED
;
310 case ADDR_TM_1D_TILED_THIN1
:
311 surf_level
->mode
= RADEON_SURF_MODE_1D
;
313 case ADDR_TM_2D_TILED_THIN1
:
314 surf_level
->mode
= RADEON_SURF_MODE_2D
;
321 surf
->u
.legacy
.stencil_tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
323 surf
->u
.legacy
.tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
325 surf
->surf_size
= surf_level
->offset
+ AddrSurfInfoOut
->surfSize
;
327 /* Clear DCC fields at the beginning. */
328 surf_level
->dcc_offset
= 0;
330 /* The previous level's flag tells us if we can use DCC for this level. */
331 if (AddrSurfInfoIn
->flags
.dccCompatible
&&
332 (level
== 0 || AddrDccOut
->subLvlCompressible
)) {
333 AddrDccIn
->colorSurfSize
= AddrSurfInfoOut
->surfSize
;
334 AddrDccIn
->tileMode
= AddrSurfInfoOut
->tileMode
;
335 AddrDccIn
->tileInfo
= *AddrSurfInfoOut
->pTileInfo
;
336 AddrDccIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
337 AddrDccIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
339 ret
= AddrComputeDccInfo(addrlib
,
343 if (ret
== ADDR_OK
) {
344 surf_level
->dcc_offset
= surf
->dcc_size
;
345 surf_level
->dcc_fast_clear_size
= AddrDccOut
->dccFastClearSize
;
346 surf
->num_dcc_levels
= level
+ 1;
347 surf
->dcc_size
= surf_level
->dcc_offset
+ AddrDccOut
->dccRamSize
;
348 surf
->dcc_alignment
= MAX2(surf
->dcc_alignment
, AddrDccOut
->dccRamBaseAlign
);
352 /* TC-compatible HTILE. */
354 AddrSurfInfoIn
->flags
.depth
&&
355 surf_level
->mode
== RADEON_SURF_MODE_2D
&&
357 AddrHtileIn
->flags
.tcCompatible
= AddrSurfInfoIn
->flags
.tcCompatible
;
358 AddrHtileIn
->pitch
= AddrSurfInfoOut
->pitch
;
359 AddrHtileIn
->height
= AddrSurfInfoOut
->height
;
360 AddrHtileIn
->numSlices
= AddrSurfInfoOut
->depth
;
361 AddrHtileIn
->blockWidth
= ADDR_HTILE_BLOCKSIZE_8
;
362 AddrHtileIn
->blockHeight
= ADDR_HTILE_BLOCKSIZE_8
;
363 AddrHtileIn
->pTileInfo
= AddrSurfInfoOut
->pTileInfo
;
364 AddrHtileIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
365 AddrHtileIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
367 ret
= AddrComputeHtileInfo(addrlib
,
371 if (ret
== ADDR_OK
) {
372 surf
->htile_size
= AddrHtileOut
->htileBytes
;
373 surf
->htile_slice_size
= AddrHtileOut
->sliceSize
;
374 surf
->htile_alignment
= AddrHtileOut
->baseAlign
;
381 #define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03)
382 #define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07)
384 static void gfx6_set_micro_tile_mode(struct radeon_surf
*surf
,
385 const struct radeon_info
*info
)
387 uint32_t tile_mode
= info
->si_tile_mode_array
[surf
->u
.legacy
.tiling_index
[0]];
389 if (info
->chip_class
>= CIK
)
390 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE_NEW(tile_mode
);
392 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE(tile_mode
);
395 static unsigned cik_get_macro_tile_index(struct radeon_surf
*surf
)
397 unsigned index
, tileb
;
399 tileb
= 8 * 8 * surf
->bpe
;
400 tileb
= MIN2(surf
->u
.legacy
.tile_split
, tileb
);
402 for (index
= 0; tileb
> 64; index
++)
410 * This must be called after the first level is computed.
412 * Copy surface-global settings like pipe/bank config from level 0 surface
413 * computation, and compute tile swizzle.
415 static int gfx6_surface_settings(ADDR_HANDLE addrlib
,
416 const struct radeon_info
*info
,
417 const struct ac_surf_config
*config
,
418 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
* csio
,
419 struct radeon_surf
*surf
)
421 surf
->surf_alignment
= csio
->baseAlign
;
422 surf
->u
.legacy
.pipe_config
= csio
->pTileInfo
->pipeConfig
- 1;
423 gfx6_set_micro_tile_mode(surf
, info
);
425 /* For 2D modes only. */
426 if (csio
->tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
427 surf
->u
.legacy
.bankw
= csio
->pTileInfo
->bankWidth
;
428 surf
->u
.legacy
.bankh
= csio
->pTileInfo
->bankHeight
;
429 surf
->u
.legacy
.mtilea
= csio
->pTileInfo
->macroAspectRatio
;
430 surf
->u
.legacy
.tile_split
= csio
->pTileInfo
->tileSplitBytes
;
431 surf
->u
.legacy
.num_banks
= csio
->pTileInfo
->banks
;
432 surf
->u
.legacy
.macro_tile_index
= csio
->macroModeIndex
;
434 surf
->u
.legacy
.macro_tile_index
= 0;
437 /* Compute tile swizzle. */
438 /* TODO: fix tile swizzle with mipmapping for SI */
439 if ((info
->chip_class
>= CIK
|| config
->info
.levels
== 1) &&
440 config
->info
.surf_index
&&
441 surf
->u
.legacy
.level
[0].mode
== RADEON_SURF_MODE_2D
&&
442 !(surf
->flags
& (RADEON_SURF_Z_OR_SBUFFER
| RADEON_SURF_SHAREABLE
)) &&
443 (config
->info
.samples
> 1 || !(surf
->flags
& RADEON_SURF_SCANOUT
))) {
444 ADDR_COMPUTE_BASE_SWIZZLE_INPUT AddrBaseSwizzleIn
= {0};
445 ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT AddrBaseSwizzleOut
= {0};
447 AddrBaseSwizzleIn
.size
= sizeof(ADDR_COMPUTE_BASE_SWIZZLE_INPUT
);
448 AddrBaseSwizzleOut
.size
= sizeof(ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT
);
450 AddrBaseSwizzleIn
.surfIndex
= p_atomic_inc_return(config
->info
.surf_index
) - 1;
451 AddrBaseSwizzleIn
.tileIndex
= csio
->tileIndex
;
452 AddrBaseSwizzleIn
.macroModeIndex
= csio
->macroModeIndex
;
453 AddrBaseSwizzleIn
.pTileInfo
= csio
->pTileInfo
;
454 AddrBaseSwizzleIn
.tileMode
= csio
->tileMode
;
456 int r
= AddrComputeBaseSwizzle(addrlib
, &AddrBaseSwizzleIn
,
457 &AddrBaseSwizzleOut
);
461 assert(AddrBaseSwizzleOut
.tileSwizzle
<=
462 u_bit_consecutive(0, sizeof(surf
->tile_swizzle
) * 8));
463 surf
->tile_swizzle
= AddrBaseSwizzleOut
.tileSwizzle
;
469 * Fill in the tiling information in \p surf based on the given surface config.
471 * The following fields of \p surf must be initialized by the caller:
472 * blk_w, blk_h, bpe, flags.
474 static int gfx6_compute_surface(ADDR_HANDLE addrlib
,
475 const struct radeon_info
*info
,
476 const struct ac_surf_config
*config
,
477 enum radeon_surf_mode mode
,
478 struct radeon_surf
*surf
)
482 ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
483 ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut
= {0};
484 ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn
= {0};
485 ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut
= {0};
486 ADDR_COMPUTE_HTILE_INFO_INPUT AddrHtileIn
= {0};
487 ADDR_COMPUTE_HTILE_INFO_OUTPUT AddrHtileOut
= {0};
488 ADDR_TILEINFO AddrTileInfoIn
= {0};
489 ADDR_TILEINFO AddrTileInfoOut
= {0};
492 AddrSurfInfoIn
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT
);
493 AddrSurfInfoOut
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT
);
494 AddrDccIn
.size
= sizeof(ADDR_COMPUTE_DCCINFO_INPUT
);
495 AddrDccOut
.size
= sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT
);
496 AddrHtileIn
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT
);
497 AddrHtileOut
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT
);
498 AddrSurfInfoOut
.pTileInfo
= &AddrTileInfoOut
;
500 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
502 /* MSAA and FMASK require 2D tiling. */
503 if (config
->info
.samples
> 1 ||
504 (surf
->flags
& RADEON_SURF_FMASK
))
505 mode
= RADEON_SURF_MODE_2D
;
507 /* DB doesn't support linear layouts. */
508 if (surf
->flags
& (RADEON_SURF_Z_OR_SBUFFER
) &&
509 mode
< RADEON_SURF_MODE_1D
)
510 mode
= RADEON_SURF_MODE_1D
;
512 /* Set the requested tiling mode. */
514 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
515 AddrSurfInfoIn
.tileMode
= ADDR_TM_LINEAR_ALIGNED
;
517 case RADEON_SURF_MODE_1D
:
518 AddrSurfInfoIn
.tileMode
= ADDR_TM_1D_TILED_THIN1
;
520 case RADEON_SURF_MODE_2D
:
521 AddrSurfInfoIn
.tileMode
= ADDR_TM_2D_TILED_THIN1
;
527 /* The format must be set correctly for the allocation of compressed
528 * textures to work. In other cases, setting the bpp is sufficient.
533 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
536 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
543 AddrDccIn
.bpp
= AddrSurfInfoIn
.bpp
= surf
->bpe
* 8;
546 AddrDccIn
.numSamples
= AddrSurfInfoIn
.numSamples
=
547 config
->info
.samples
? config
->info
.samples
: 1;
548 AddrSurfInfoIn
.tileIndex
= -1;
550 /* Set the micro tile type. */
551 if (surf
->flags
& RADEON_SURF_SCANOUT
)
552 AddrSurfInfoIn
.tileType
= ADDR_DISPLAYABLE
;
553 else if (surf
->flags
& (RADEON_SURF_Z_OR_SBUFFER
| RADEON_SURF_FMASK
))
554 AddrSurfInfoIn
.tileType
= ADDR_DEPTH_SAMPLE_ORDER
;
556 AddrSurfInfoIn
.tileType
= ADDR_NON_DISPLAYABLE
;
558 AddrSurfInfoIn
.flags
.color
= !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
);
559 AddrSurfInfoIn
.flags
.depth
= (surf
->flags
& RADEON_SURF_ZBUFFER
) != 0;
560 AddrSurfInfoIn
.flags
.cube
= config
->is_cube
;
561 AddrSurfInfoIn
.flags
.fmask
= (surf
->flags
& RADEON_SURF_FMASK
) != 0;
562 AddrSurfInfoIn
.flags
.display
= (surf
->flags
& RADEON_SURF_SCANOUT
) != 0;
563 AddrSurfInfoIn
.flags
.pow2Pad
= config
->info
.levels
> 1;
564 AddrSurfInfoIn
.flags
.tcCompatible
= (surf
->flags
& RADEON_SURF_TC_COMPATIBLE_HTILE
) != 0;
566 /* Only degrade the tile mode for space if TC-compatible HTILE hasn't been
567 * requested, because TC-compatible HTILE requires 2D tiling.
569 AddrSurfInfoIn
.flags
.opt4Space
= !AddrSurfInfoIn
.flags
.tcCompatible
&&
570 !AddrSurfInfoIn
.flags
.fmask
&&
571 config
->info
.samples
<= 1 &&
572 (surf
->flags
& RADEON_SURF_OPTIMIZE_FOR_SPACE
);
575 * - If we add MSAA support, keep in mind that CB can't decompress 8bpp
577 * - Mipmapped array textures have low performance (discovered by a closed
580 AddrSurfInfoIn
.flags
.dccCompatible
=
581 info
->chip_class
>= VI
&&
582 !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
) &&
583 !(surf
->flags
& RADEON_SURF_DISABLE_DCC
) &&
584 !compressed
&& AddrDccIn
.numSamples
<= 1 &&
585 ((config
->info
.array_size
== 1 && config
->info
.depth
== 1) ||
586 config
->info
.levels
== 1);
588 AddrSurfInfoIn
.flags
.noStencil
= (surf
->flags
& RADEON_SURF_SBUFFER
) == 0;
589 AddrSurfInfoIn
.flags
.compressZ
= AddrSurfInfoIn
.flags
.depth
;
591 /* On CI/VI, the DB uses the same pitch and tile mode (except tilesplit)
592 * for Z and stencil. This can cause a number of problems which we work
595 * - a depth part that is incompatible with mipmapped texturing
596 * - at least on Stoney, entirely incompatible Z/S aspects (e.g.
597 * incorrect tiling applied to the stencil part, stencil buffer
598 * memory accesses that go out of bounds) even without mipmapping
600 * Some piglit tests that are prone to different types of related
602 * ./bin/ext_framebuffer_multisample-upsample 2 stencil
603 * ./bin/framebuffer-blit-levels {draw,read} stencil
604 * ./bin/ext_framebuffer_multisample-unaligned-blit N {depth,stencil} {msaa,upsample,downsample}
605 * ./bin/fbo-depth-array fs-writes-{depth,stencil} / {depth,stencil}-{clear,layered-clear,draw}
606 * ./bin/depthstencil-render-miplevels 1024 d=s=z24_s8
608 int stencil_tile_idx
= -1;
610 if (AddrSurfInfoIn
.flags
.depth
&& !AddrSurfInfoIn
.flags
.noStencil
&&
611 (config
->info
.levels
> 1 || info
->family
== CHIP_STONEY
)) {
612 /* Compute stencilTileIdx that is compatible with the (depth)
613 * tileIdx. This degrades the depth surface if necessary to
614 * ensure that a matching stencilTileIdx exists. */
615 AddrSurfInfoIn
.flags
.matchStencilTileCfg
= 1;
617 /* Keep the depth mip-tail compatible with texturing. */
618 AddrSurfInfoIn
.flags
.noStencil
= 1;
621 /* Set preferred macrotile parameters. This is usually required
622 * for shared resources. This is for 2D tiling only. */
623 if (AddrSurfInfoIn
.tileMode
>= ADDR_TM_2D_TILED_THIN1
&&
624 surf
->u
.legacy
.bankw
&& surf
->u
.legacy
.bankh
&&
625 surf
->u
.legacy
.mtilea
&& surf
->u
.legacy
.tile_split
) {
626 assert(!(surf
->flags
& RADEON_SURF_FMASK
));
628 /* If any of these parameters are incorrect, the calculation
630 AddrTileInfoIn
.banks
= surf
->u
.legacy
.num_banks
;
631 AddrTileInfoIn
.bankWidth
= surf
->u
.legacy
.bankw
;
632 AddrTileInfoIn
.bankHeight
= surf
->u
.legacy
.bankh
;
633 AddrTileInfoIn
.macroAspectRatio
= surf
->u
.legacy
.mtilea
;
634 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.tile_split
;
635 AddrTileInfoIn
.pipeConfig
= surf
->u
.legacy
.pipe_config
+ 1; /* +1 compared to GB_TILE_MODE */
636 AddrSurfInfoIn
.flags
.opt4Space
= 0;
637 AddrSurfInfoIn
.pTileInfo
= &AddrTileInfoIn
;
639 /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set
640 * the tile index, because we are expected to know it if
641 * we know the other parameters.
643 * This is something that can easily be fixed in Addrlib.
644 * For now, just figure it out here.
645 * Note that only 2D_TILE_THIN1 is handled here.
647 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
648 assert(AddrSurfInfoIn
.tileMode
== ADDR_TM_2D_TILED_THIN1
);
650 if (info
->chip_class
== SI
) {
651 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
) {
653 AddrSurfInfoIn
.tileIndex
= 11; /* 16bpp */
655 AddrSurfInfoIn
.tileIndex
= 12; /* 32bpp */
658 AddrSurfInfoIn
.tileIndex
= 14; /* 8bpp */
659 else if (surf
->bpe
== 2)
660 AddrSurfInfoIn
.tileIndex
= 15; /* 16bpp */
661 else if (surf
->bpe
== 4)
662 AddrSurfInfoIn
.tileIndex
= 16; /* 32bpp */
664 AddrSurfInfoIn
.tileIndex
= 17; /* 64bpp (and 128bpp) */
668 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
)
669 AddrSurfInfoIn
.tileIndex
= 10; /* 2D displayable */
671 AddrSurfInfoIn
.tileIndex
= 14; /* 2D non-displayable */
673 /* Addrlib doesn't set this if tileIndex is forced like above. */
674 AddrSurfInfoOut
.macroModeIndex
= cik_get_macro_tile_index(surf
);
678 surf
->has_stencil
= !!(surf
->flags
& RADEON_SURF_SBUFFER
);
679 surf
->num_dcc_levels
= 0;
682 surf
->dcc_alignment
= 1;
683 surf
->htile_size
= 0;
684 surf
->htile_slice_size
= 0;
685 surf
->htile_alignment
= 1;
687 const bool only_stencil
= (surf
->flags
& RADEON_SURF_SBUFFER
) &&
688 !(surf
->flags
& RADEON_SURF_ZBUFFER
);
690 /* Calculate texture layout information. */
692 for (level
= 0; level
< config
->info
.levels
; level
++) {
693 r
= gfx6_compute_level(addrlib
, config
, surf
, false, level
, compressed
,
694 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
695 &AddrDccIn
, &AddrDccOut
, &AddrHtileIn
, &AddrHtileOut
);
702 /* Check that we actually got a TC-compatible HTILE if
703 * we requested it (only for level 0, since we're not
704 * supporting HTILE on higher mip levels anyway). */
705 assert(AddrSurfInfoOut
.tcCompatible
||
706 !AddrSurfInfoIn
.flags
.tcCompatible
||
707 AddrSurfInfoIn
.flags
.matchStencilTileCfg
);
709 if (AddrSurfInfoIn
.flags
.matchStencilTileCfg
) {
710 if (!AddrSurfInfoOut
.tcCompatible
) {
711 AddrSurfInfoIn
.flags
.tcCompatible
= 0;
712 surf
->flags
&= ~RADEON_SURF_TC_COMPATIBLE_HTILE
;
715 AddrSurfInfoIn
.flags
.matchStencilTileCfg
= 0;
716 AddrSurfInfoIn
.tileIndex
= AddrSurfInfoOut
.tileIndex
;
717 stencil_tile_idx
= AddrSurfInfoOut
.stencilTileIdx
;
719 assert(stencil_tile_idx
>= 0);
722 r
= gfx6_surface_settings(addrlib
, info
, config
,
723 &AddrSurfInfoOut
, surf
);
729 /* Calculate texture layout information for stencil. */
730 if (surf
->flags
& RADEON_SURF_SBUFFER
) {
731 AddrSurfInfoIn
.tileIndex
= stencil_tile_idx
;
732 AddrSurfInfoIn
.bpp
= 8;
733 AddrSurfInfoIn
.flags
.depth
= 0;
734 AddrSurfInfoIn
.flags
.stencil
= 1;
735 AddrSurfInfoIn
.flags
.tcCompatible
= 0;
736 /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */
737 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.stencil_tile_split
;
739 for (level
= 0; level
< config
->info
.levels
; level
++) {
740 r
= gfx6_compute_level(addrlib
, config
, surf
, true, level
, compressed
,
741 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
742 &AddrDccIn
, &AddrDccOut
,
747 /* DB uses the depth pitch for both stencil and depth. */
749 if (surf
->u
.legacy
.stencil_level
[level
].nblk_x
!=
750 surf
->u
.legacy
.level
[level
].nblk_x
)
751 surf
->u
.legacy
.stencil_adjusted
= true;
753 surf
->u
.legacy
.level
[level
].nblk_x
=
754 surf
->u
.legacy
.stencil_level
[level
].nblk_x
;
759 r
= gfx6_surface_settings(addrlib
, info
, config
,
760 &AddrSurfInfoOut
, surf
);
765 /* For 2D modes only. */
766 if (AddrSurfInfoOut
.tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
767 surf
->u
.legacy
.stencil_tile_split
=
768 AddrSurfInfoOut
.pTileInfo
->tileSplitBytes
;
774 /* Recalculate the whole DCC miptree size including disabled levels.
775 * This is what addrlib does, but calling addrlib would be a lot more
778 if (surf
->dcc_size
&& config
->info
.levels
> 1) {
779 /* The smallest miplevels that are never compressed by DCC
780 * still read the DCC buffer via TC if the base level uses DCC,
781 * and for some reason the DCC buffer needs to be larger if
782 * the miptree uses non-zero tile_swizzle. Otherwise there are
785 * "dcc_alignment * 4" was determined by trial and error.
787 surf
->dcc_size
= align64(surf
->surf_size
>> 8,
788 surf
->dcc_alignment
* 4);
791 /* Make sure HTILE covers the whole miptree, because the shader reads
792 * TC-compatible HTILE even for levels where it's disabled by DB.
794 if (surf
->htile_size
&& config
->info
.levels
> 1)
795 surf
->htile_size
*= 2;
797 surf
->is_linear
= surf
->u
.legacy
.level
[0].mode
== RADEON_SURF_MODE_LINEAR_ALIGNED
;
798 surf
->is_displayable
= surf
->is_linear
||
799 surf
->micro_tile_mode
== RADEON_MICRO_MODE_DISPLAY
||
800 surf
->micro_tile_mode
== RADEON_MICRO_MODE_ROTATED
;
804 /* This is only called when expecting a tiled layout. */
806 gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib
,
807 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
,
808 bool is_fmask
, AddrSwizzleMode
*swizzle_mode
)
810 ADDR_E_RETURNCODE ret
;
811 ADDR2_GET_PREFERRED_SURF_SETTING_INPUT sin
= {0};
812 ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT sout
= {0};
814 sin
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_INPUT
);
815 sout
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT
);
817 sin
.flags
= in
->flags
;
818 sin
.resourceType
= in
->resourceType
;
819 sin
.format
= in
->format
;
820 sin
.resourceLoction
= ADDR_RSRC_LOC_INVIS
;
821 /* TODO: We could allow some of these: */
822 sin
.forbiddenBlock
.micro
= 1; /* don't allow the 256B swizzle modes */
823 sin
.forbiddenBlock
.var
= 1; /* don't allow the variable-sized swizzle modes */
824 sin
.forbiddenBlock
.linear
= 1; /* don't allow linear swizzle modes */
826 sin
.width
= in
->width
;
827 sin
.height
= in
->height
;
828 sin
.numSlices
= in
->numSlices
;
829 sin
.numMipLevels
= in
->numMipLevels
;
830 sin
.numSamples
= in
->numSamples
;
831 sin
.numFrags
= in
->numFrags
;
838 ret
= Addr2GetPreferredSurfaceSetting(addrlib
, &sin
, &sout
);
842 *swizzle_mode
= sout
.swizzleMode
;
846 static int gfx9_compute_miptree(ADDR_HANDLE addrlib
,
847 struct radeon_surf
*surf
, bool compressed
,
848 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
)
850 ADDR2_MIP_INFO mip_info
[RADEON_SURF_MAX_LEVELS
] = {};
851 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT out
= {0};
852 ADDR_E_RETURNCODE ret
;
854 out
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT
);
855 out
.pMipInfo
= mip_info
;
857 ret
= Addr2ComputeSurfaceInfo(addrlib
, in
, &out
);
861 if (in
->flags
.stencil
) {
862 surf
->u
.gfx9
.stencil
.swizzle_mode
= in
->swizzleMode
;
863 surf
->u
.gfx9
.stencil
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
864 out
.mipChainPitch
- 1;
865 surf
->surf_alignment
= MAX2(surf
->surf_alignment
, out
.baseAlign
);
866 surf
->u
.gfx9
.stencil_offset
= align(surf
->surf_size
, out
.baseAlign
);
867 surf
->surf_size
= surf
->u
.gfx9
.stencil_offset
+ out
.surfSize
;
871 surf
->u
.gfx9
.surf
.swizzle_mode
= in
->swizzleMode
;
872 surf
->u
.gfx9
.surf
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
873 out
.mipChainPitch
- 1;
875 /* CMASK fast clear uses these even if FMASK isn't allocated.
876 * FMASK only supports the Z swizzle modes, whose numbers are multiples of 4.
878 surf
->u
.gfx9
.fmask
.swizzle_mode
= surf
->u
.gfx9
.surf
.swizzle_mode
& ~0x3;
879 surf
->u
.gfx9
.fmask
.epitch
= surf
->u
.gfx9
.surf
.epitch
;
881 surf
->u
.gfx9
.surf_slice_size
= out
.sliceSize
;
882 surf
->u
.gfx9
.surf_pitch
= out
.pitch
;
883 surf
->u
.gfx9
.surf_height
= out
.height
;
884 surf
->surf_size
= out
.surfSize
;
885 surf
->surf_alignment
= out
.baseAlign
;
887 if (in
->swizzleMode
== ADDR_SW_LINEAR
) {
888 for (unsigned i
= 0; i
< in
->numMipLevels
; i
++)
889 surf
->u
.gfx9
.offset
[i
] = mip_info
[i
].offset
;
892 if (in
->flags
.depth
) {
893 assert(in
->swizzleMode
!= ADDR_SW_LINEAR
);
896 ADDR2_COMPUTE_HTILE_INFO_INPUT hin
= {0};
897 ADDR2_COMPUTE_HTILE_INFO_OUTPUT hout
= {0};
899 hin
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT
);
900 hout
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT
);
902 hin
.hTileFlags
.pipeAligned
= 1;
903 hin
.hTileFlags
.rbAligned
= 1;
904 hin
.depthFlags
= in
->flags
;
905 hin
.swizzleMode
= in
->swizzleMode
;
906 hin
.unalignedWidth
= in
->width
;
907 hin
.unalignedHeight
= in
->height
;
908 hin
.numSlices
= in
->numSlices
;
909 hin
.numMipLevels
= in
->numMipLevels
;
911 ret
= Addr2ComputeHtileInfo(addrlib
, &hin
, &hout
);
915 surf
->u
.gfx9
.htile
.rb_aligned
= hin
.hTileFlags
.rbAligned
;
916 surf
->u
.gfx9
.htile
.pipe_aligned
= hin
.hTileFlags
.pipeAligned
;
917 surf
->htile_size
= hout
.htileBytes
;
918 surf
->htile_slice_size
= hout
.sliceSize
;
919 surf
->htile_alignment
= hout
.baseAlign
;
922 if (!(surf
->flags
& RADEON_SURF_DISABLE_DCC
) &&
923 !(surf
->flags
& RADEON_SURF_SCANOUT
) &&
925 in
->swizzleMode
!= ADDR_SW_LINEAR
&&
926 /* TODO: We could support DCC with MSAA. */
927 in
->numSamples
== 1) {
928 ADDR2_COMPUTE_DCCINFO_INPUT din
= {0};
929 ADDR2_COMPUTE_DCCINFO_OUTPUT dout
= {0};
930 ADDR2_META_MIP_INFO meta_mip_info
[RADEON_SURF_MAX_LEVELS
] = {};
932 din
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_INPUT
);
933 dout
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT
);
934 dout
.pMipInfo
= meta_mip_info
;
936 din
.dccKeyFlags
.pipeAligned
= 1;
937 din
.dccKeyFlags
.rbAligned
= 1;
938 din
.colorFlags
= in
->flags
;
939 din
.resourceType
= in
->resourceType
;
940 din
.swizzleMode
= in
->swizzleMode
;
942 din
.unalignedWidth
= in
->width
;
943 din
.unalignedHeight
= in
->height
;
944 din
.numSlices
= in
->numSlices
;
945 din
.numFrags
= in
->numFrags
;
946 din
.numMipLevels
= in
->numMipLevels
;
947 din
.dataSurfaceSize
= out
.surfSize
;
949 ret
= Addr2ComputeDccInfo(addrlib
, &din
, &dout
);
953 surf
->u
.gfx9
.dcc
.rb_aligned
= din
.dccKeyFlags
.rbAligned
;
954 surf
->u
.gfx9
.dcc
.pipe_aligned
= din
.dccKeyFlags
.pipeAligned
;
955 surf
->u
.gfx9
.dcc_pitch_max
= dout
.pitch
- 1;
956 surf
->dcc_size
= dout
.dccRamSize
;
957 surf
->dcc_alignment
= dout
.dccRamBaseAlign
;
958 surf
->num_dcc_levels
= in
->numMipLevels
;
960 /* Disable DCC for levels that are in the mip tail.
962 * There are two issues that this is intended to
965 * 1. Multiple mip levels may share a cache line. This
966 * can lead to corruption when switching between
967 * rendering to different mip levels because the
968 * RBs don't maintain coherency.
970 * 2. Texturing with metadata after rendering sometimes
971 * fails with corruption, probably for a similar
974 * Working around these issues for all levels in the
975 * mip tail may be overly conservative, but it's what
978 * Alternative solutions that also work but are worse:
979 * - Disable DCC entirely.
980 * - Flush TC L2 after rendering.
982 for (unsigned i
= 0; i
< in
->numMipLevels
; i
++) {
983 if (meta_mip_info
[i
].inMiptail
) {
984 surf
->num_dcc_levels
= i
;
989 if (!surf
->num_dcc_levels
)
994 if (in
->numSamples
> 1) {
995 ADDR2_COMPUTE_FMASK_INFO_INPUT fin
= {0};
996 ADDR2_COMPUTE_FMASK_INFO_OUTPUT fout
= {0};
998 fin
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT
);
999 fout
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT
);
1001 ret
= gfx9_get_preferred_swizzle_mode(addrlib
, in
, true, &fin
.swizzleMode
);
1005 fin
.unalignedWidth
= in
->width
;
1006 fin
.unalignedHeight
= in
->height
;
1007 fin
.numSlices
= in
->numSlices
;
1008 fin
.numSamples
= in
->numSamples
;
1009 fin
.numFrags
= in
->numFrags
;
1011 ret
= Addr2ComputeFmaskInfo(addrlib
, &fin
, &fout
);
1015 surf
->u
.gfx9
.fmask
.swizzle_mode
= fin
.swizzleMode
;
1016 surf
->u
.gfx9
.fmask
.epitch
= fout
.pitch
- 1;
1017 surf
->u
.gfx9
.fmask_size
= fout
.fmaskBytes
;
1018 surf
->u
.gfx9
.fmask_alignment
= fout
.baseAlign
;
1022 if (in
->swizzleMode
!= ADDR_SW_LINEAR
) {
1023 ADDR2_COMPUTE_CMASK_INFO_INPUT cin
= {0};
1024 ADDR2_COMPUTE_CMASK_INFO_OUTPUT cout
= {0};
1026 cin
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT
);
1027 cout
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT
);
1029 cin
.cMaskFlags
.pipeAligned
= 1;
1030 cin
.cMaskFlags
.rbAligned
= 1;
1031 cin
.colorFlags
= in
->flags
;
1032 cin
.resourceType
= in
->resourceType
;
1033 cin
.unalignedWidth
= in
->width
;
1034 cin
.unalignedHeight
= in
->height
;
1035 cin
.numSlices
= in
->numSlices
;
1037 if (in
->numSamples
> 1)
1038 cin
.swizzleMode
= surf
->u
.gfx9
.fmask
.swizzle_mode
;
1040 cin
.swizzleMode
= in
->swizzleMode
;
1042 ret
= Addr2ComputeCmaskInfo(addrlib
, &cin
, &cout
);
1046 surf
->u
.gfx9
.cmask
.rb_aligned
= cin
.cMaskFlags
.rbAligned
;
1047 surf
->u
.gfx9
.cmask
.pipe_aligned
= cin
.cMaskFlags
.pipeAligned
;
1048 surf
->u
.gfx9
.cmask_size
= cout
.cmaskBytes
;
1049 surf
->u
.gfx9
.cmask_alignment
= cout
.baseAlign
;
1056 static int gfx9_compute_surface(ADDR_HANDLE addrlib
,
1057 const struct ac_surf_config
*config
,
1058 enum radeon_surf_mode mode
,
1059 struct radeon_surf
*surf
)
1062 ADDR2_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
1065 assert(!(surf
->flags
& RADEON_SURF_FMASK
));
1067 AddrSurfInfoIn
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT
);
1069 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
1071 /* The format must be set correctly for the allocation of compressed
1072 * textures to work. In other cases, setting the bpp is sufficient. */
1074 switch (surf
->bpe
) {
1076 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
1079 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
1085 AddrSurfInfoIn
.bpp
= surf
->bpe
* 8;
1088 AddrSurfInfoIn
.flags
.color
= !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
);
1089 AddrSurfInfoIn
.flags
.depth
= (surf
->flags
& RADEON_SURF_ZBUFFER
) != 0;
1090 AddrSurfInfoIn
.flags
.display
= (surf
->flags
& RADEON_SURF_SCANOUT
) != 0;
1091 /* flags.texture currently refers to TC-compatible HTILE */
1092 AddrSurfInfoIn
.flags
.texture
= AddrSurfInfoIn
.flags
.color
||
1093 surf
->flags
& RADEON_SURF_TC_COMPATIBLE_HTILE
;
1094 AddrSurfInfoIn
.flags
.opt4space
= 1;
1096 AddrSurfInfoIn
.numMipLevels
= config
->info
.levels
;
1097 AddrSurfInfoIn
.numSamples
= config
->info
.samples
? config
->info
.samples
: 1;
1098 AddrSurfInfoIn
.numFrags
= AddrSurfInfoIn
.numSamples
;
1100 /* GFX9 doesn't support 1D depth textures, so allocate all 1D textures
1101 * as 2D to avoid having shader variants for 1D vs 2D, so all shaders
1102 * must sample 1D textures as 2D. */
1104 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_3D
;
1106 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_2D
;
1108 AddrSurfInfoIn
.width
= config
->info
.width
;
1109 AddrSurfInfoIn
.height
= config
->info
.height
;
1112 AddrSurfInfoIn
.numSlices
= config
->info
.depth
;
1113 else if (config
->is_cube
)
1114 AddrSurfInfoIn
.numSlices
= 6;
1116 AddrSurfInfoIn
.numSlices
= config
->info
.array_size
;
1119 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
1120 assert(config
->info
.samples
<= 1);
1121 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
1122 AddrSurfInfoIn
.swizzleMode
= ADDR_SW_LINEAR
;
1125 case RADEON_SURF_MODE_1D
:
1126 case RADEON_SURF_MODE_2D
:
1127 if (surf
->flags
& RADEON_SURF_IMPORTED
) {
1128 AddrSurfInfoIn
.swizzleMode
= surf
->u
.gfx9
.surf
.swizzle_mode
;
1132 r
= gfx9_get_preferred_swizzle_mode(addrlib
, &AddrSurfInfoIn
, false,
1133 &AddrSurfInfoIn
.swizzleMode
);
1142 surf
->u
.gfx9
.resource_type
= AddrSurfInfoIn
.resourceType
;
1143 surf
->has_stencil
= !!(surf
->flags
& RADEON_SURF_SBUFFER
);
1145 surf
->num_dcc_levels
= 0;
1146 surf
->surf_size
= 0;
1148 surf
->htile_size
= 0;
1149 surf
->htile_slice_size
= 0;
1150 surf
->u
.gfx9
.surf_offset
= 0;
1151 surf
->u
.gfx9
.stencil_offset
= 0;
1152 surf
->u
.gfx9
.fmask_size
= 0;
1153 surf
->u
.gfx9
.cmask_size
= 0;
1155 /* Calculate texture layout information. */
1156 r
= gfx9_compute_miptree(addrlib
, surf
, compressed
, &AddrSurfInfoIn
);
1160 /* Calculate texture layout information for stencil. */
1161 if (surf
->flags
& RADEON_SURF_SBUFFER
) {
1162 AddrSurfInfoIn
.flags
.stencil
= 1;
1163 AddrSurfInfoIn
.bpp
= 8;
1165 if (!AddrSurfInfoIn
.flags
.depth
) {
1166 r
= gfx9_get_preferred_swizzle_mode(addrlib
, &AddrSurfInfoIn
, false,
1167 &AddrSurfInfoIn
.swizzleMode
);
1171 AddrSurfInfoIn
.flags
.depth
= 0;
1173 r
= gfx9_compute_miptree(addrlib
, surf
, compressed
, &AddrSurfInfoIn
);
1178 surf
->is_linear
= surf
->u
.gfx9
.surf
.swizzle_mode
== ADDR_SW_LINEAR
;
1180 /* Query whether the surface is displayable. */
1181 bool displayable
= false;
1182 r
= Addr2IsValidDisplaySwizzleMode(addrlib
, surf
->u
.gfx9
.surf
.swizzle_mode
,
1183 surf
->bpe
* 8, &displayable
);
1186 surf
->is_displayable
= displayable
;
1188 switch (surf
->u
.gfx9
.surf
.swizzle_mode
) {
1190 case ADDR_SW_256B_S
:
1192 case ADDR_SW_64KB_S
:
1194 case ADDR_SW_64KB_S_T
:
1195 case ADDR_SW_4KB_S_X
:
1196 case ADDR_SW_64KB_S_X
:
1197 case ADDR_SW_VAR_S_X
:
1198 surf
->micro_tile_mode
= RADEON_MICRO_MODE_THIN
;
1202 case ADDR_SW_LINEAR
:
1203 case ADDR_SW_256B_D
:
1205 case ADDR_SW_64KB_D
:
1207 case ADDR_SW_64KB_D_T
:
1208 case ADDR_SW_4KB_D_X
:
1209 case ADDR_SW_64KB_D_X
:
1210 case ADDR_SW_VAR_D_X
:
1211 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DISPLAY
;
1215 case ADDR_SW_256B_R
:
1217 case ADDR_SW_64KB_R
:
1219 case ADDR_SW_64KB_R_T
:
1220 case ADDR_SW_4KB_R_X
:
1221 case ADDR_SW_64KB_R_X
:
1222 case ADDR_SW_VAR_R_X
:
1223 surf
->micro_tile_mode
= RADEON_MICRO_MODE_ROTATED
;
1228 case ADDR_SW_64KB_Z
:
1230 case ADDR_SW_64KB_Z_T
:
1231 case ADDR_SW_4KB_Z_X
:
1232 case ADDR_SW_64KB_Z_X
:
1233 case ADDR_SW_VAR_Z_X
:
1234 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DEPTH
;
1244 int ac_compute_surface(ADDR_HANDLE addrlib
, const struct radeon_info
*info
,
1245 const struct ac_surf_config
*config
,
1246 enum radeon_surf_mode mode
,
1247 struct radeon_surf
*surf
)
1251 r
= surf_config_sanity(config
);
1255 if (info
->chip_class
>= GFX9
)
1256 return gfx9_compute_surface(addrlib
, config
, mode
, surf
);
1258 return gfx6_compute_surface(addrlib
, info
, config
, mode
, surf
);