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 "amdgpu_id.h"
30 #include "util/macros.h"
31 #include "util/u_math.h"
37 #include <amdgpu_drm.h>
39 #include "addrlib/addrinterface.h"
41 #ifndef CIASICIDGFXENGINE_SOUTHERNISLAND
42 #define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A
45 #ifndef CIASICIDGFXENGINE_ARCTICISLAND
46 #define CIASICIDGFXENGINE_ARCTICISLAND 0x0000000D
49 static void addrlib_family_rev_id(enum radeon_family family
,
50 unsigned *addrlib_family
,
51 unsigned *addrlib_revid
)
55 *addrlib_family
= FAMILY_SI
;
56 *addrlib_revid
= SI_TAHITI_P_A0
;
59 *addrlib_family
= FAMILY_SI
;
60 *addrlib_revid
= SI_PITCAIRN_PM_A0
;
63 *addrlib_family
= FAMILY_SI
;
64 *addrlib_revid
= SI_CAPEVERDE_M_A0
;
67 *addrlib_family
= FAMILY_SI
;
68 *addrlib_revid
= SI_OLAND_M_A0
;
71 *addrlib_family
= FAMILY_SI
;
72 *addrlib_revid
= SI_HAINAN_V_A0
;
75 *addrlib_family
= FAMILY_CI
;
76 *addrlib_revid
= CI_BONAIRE_M_A0
;
79 *addrlib_family
= FAMILY_KV
;
80 *addrlib_revid
= KV_SPECTRE_A0
;
83 *addrlib_family
= FAMILY_KV
;
84 *addrlib_revid
= KB_KALINDI_A0
;
87 *addrlib_family
= FAMILY_CI
;
88 *addrlib_revid
= CI_HAWAII_P_A0
;
91 *addrlib_family
= FAMILY_KV
;
92 *addrlib_revid
= ML_GODAVARI_A0
;
95 *addrlib_family
= FAMILY_VI
;
96 *addrlib_revid
= VI_TONGA_P_A0
;
99 *addrlib_family
= FAMILY_VI
;
100 *addrlib_revid
= VI_ICELAND_M_A0
;
103 *addrlib_family
= FAMILY_CZ
;
104 *addrlib_revid
= CARRIZO_A0
;
107 *addrlib_family
= FAMILY_CZ
;
108 *addrlib_revid
= STONEY_A0
;
111 *addrlib_family
= FAMILY_VI
;
112 *addrlib_revid
= VI_FIJI_P_A0
;
115 *addrlib_family
= FAMILY_VI
;
116 *addrlib_revid
= VI_POLARIS10_P_A0
;
119 *addrlib_family
= FAMILY_VI
;
120 *addrlib_revid
= VI_POLARIS11_M_A0
;
123 *addrlib_family
= FAMILY_VI
;
124 *addrlib_revid
= VI_POLARIS12_V_A0
;
127 *addrlib_family
= FAMILY_AI
;
128 *addrlib_revid
= AI_VEGA10_P_A0
;
131 *addrlib_family
= FAMILY_RV
;
132 *addrlib_revid
= RAVEN_A0
;
135 fprintf(stderr
, "amdgpu: Unknown family.\n");
139 static void *ADDR_API
allocSysMem(const ADDR_ALLOCSYSMEM_INPUT
* pInput
)
141 return malloc(pInput
->sizeInBytes
);
144 static ADDR_E_RETURNCODE ADDR_API
freeSysMem(const ADDR_FREESYSMEM_INPUT
* pInput
)
146 free(pInput
->pVirtAddr
);
150 ADDR_HANDLE
amdgpu_addr_create(enum radeon_family family
,
151 const struct amdgpu_gpu_info
*info
)
153 ADDR_CREATE_INPUT addrCreateInput
= {0};
154 ADDR_CREATE_OUTPUT addrCreateOutput
= {0};
155 ADDR_REGISTER_VALUE regValue
= {0};
156 ADDR_CREATE_FLAGS createFlags
= {{0}};
157 ADDR_E_RETURNCODE addrRet
;
159 addrCreateInput
.size
= sizeof(ADDR_CREATE_INPUT
);
160 addrCreateOutput
.size
= sizeof(ADDR_CREATE_OUTPUT
);
162 regValue
.gbAddrConfig
= info
->gb_addr_cfg
;
163 createFlags
.value
= 0;
165 addrlib_family_rev_id(family
, &addrCreateInput
.chipFamily
, &addrCreateInput
.chipRevision
);
166 if (addrCreateInput
.chipFamily
== FAMILY_UNKNOWN
)
169 if (addrCreateInput
.chipFamily
>= FAMILY_AI
) {
170 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_ARCTICISLAND
;
171 regValue
.blockVarSizeLog2
= 0;
173 regValue
.noOfBanks
= info
->mc_arb_ramcfg
& 0x3;
174 regValue
.noOfRanks
= (info
->mc_arb_ramcfg
& 0x4) >> 2;
176 regValue
.backendDisables
= info
->enabled_rb_pipes_mask
;
177 regValue
.pTileConfig
= info
->gb_tile_mode
;
178 regValue
.noOfEntries
= ARRAY_SIZE(info
->gb_tile_mode
);
179 if (addrCreateInput
.chipFamily
== FAMILY_SI
) {
180 regValue
.pMacroTileConfig
= NULL
;
181 regValue
.noOfMacroEntries
= 0;
183 regValue
.pMacroTileConfig
= info
->gb_macro_tile_mode
;
184 regValue
.noOfMacroEntries
= ARRAY_SIZE(info
->gb_macro_tile_mode
);
187 createFlags
.useTileIndex
= 1;
188 createFlags
.useHtileSliceAlign
= 1;
190 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_SOUTHERNISLAND
;
193 addrCreateInput
.callbacks
.allocSysMem
= allocSysMem
;
194 addrCreateInput
.callbacks
.freeSysMem
= freeSysMem
;
195 addrCreateInput
.callbacks
.debugPrint
= 0;
196 addrCreateInput
.createFlags
= createFlags
;
197 addrCreateInput
.regValue
= regValue
;
199 addrRet
= AddrCreate(&addrCreateInput
, &addrCreateOutput
);
200 if (addrRet
!= ADDR_OK
)
203 return addrCreateOutput
.hLib
;
206 static int surf_config_sanity(const struct ac_surf_config
*config
)
208 /* all dimension must be at least 1 ! */
209 if (!config
->info
.width
|| !config
->info
.height
|| !config
->info
.depth
||
210 !config
->info
.array_size
|| !config
->info
.levels
)
213 switch (config
->info
.samples
) {
224 if (config
->is_3d
&& config
->info
.array_size
> 1)
226 if (config
->is_cube
&& config
->info
.depth
> 1)
232 static int gfx6_compute_level(ADDR_HANDLE addrlib
,
233 const struct ac_surf_config
*config
,
234 struct radeon_surf
*surf
, bool is_stencil
,
235 unsigned level
, bool compressed
,
236 ADDR_COMPUTE_SURFACE_INFO_INPUT
*AddrSurfInfoIn
,
237 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
*AddrSurfInfoOut
,
238 ADDR_COMPUTE_DCCINFO_INPUT
*AddrDccIn
,
239 ADDR_COMPUTE_DCCINFO_OUTPUT
*AddrDccOut
,
240 ADDR_COMPUTE_HTILE_INFO_INPUT
*AddrHtileIn
,
241 ADDR_COMPUTE_HTILE_INFO_OUTPUT
*AddrHtileOut
)
243 struct legacy_surf_level
*surf_level
;
244 ADDR_E_RETURNCODE ret
;
246 AddrSurfInfoIn
->mipLevel
= level
;
247 AddrSurfInfoIn
->width
= u_minify(config
->info
.width
, level
);
248 AddrSurfInfoIn
->height
= u_minify(config
->info
.height
, level
);
251 AddrSurfInfoIn
->numSlices
= u_minify(config
->info
.depth
, level
);
252 else if (config
->is_cube
)
253 AddrSurfInfoIn
->numSlices
= 6;
255 AddrSurfInfoIn
->numSlices
= config
->info
.array_size
;
258 /* Set the base level pitch. This is needed for calculation
259 * of non-zero levels. */
261 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.stencil_level
[0].nblk_x
;
263 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.level
[0].nblk_x
;
265 /* Convert blocks to pixels for compressed formats. */
267 AddrSurfInfoIn
->basePitch
*= surf
->blk_w
;
270 ret
= AddrComputeSurfaceInfo(addrlib
,
273 if (ret
!= ADDR_OK
) {
277 surf_level
= is_stencil
? &surf
->u
.legacy
.stencil_level
[level
] : &surf
->u
.legacy
.level
[level
];
278 surf_level
->offset
= align64(surf
->surf_size
, AddrSurfInfoOut
->baseAlign
);
279 surf_level
->slice_size
= AddrSurfInfoOut
->sliceSize
;
280 surf_level
->nblk_x
= AddrSurfInfoOut
->pitch
;
281 surf_level
->nblk_y
= AddrSurfInfoOut
->height
;
283 switch (AddrSurfInfoOut
->tileMode
) {
284 case ADDR_TM_LINEAR_ALIGNED
:
285 surf_level
->mode
= RADEON_SURF_MODE_LINEAR_ALIGNED
;
287 case ADDR_TM_1D_TILED_THIN1
:
288 surf_level
->mode
= RADEON_SURF_MODE_1D
;
290 case ADDR_TM_2D_TILED_THIN1
:
291 surf_level
->mode
= RADEON_SURF_MODE_2D
;
298 surf
->u
.legacy
.stencil_tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
300 surf
->u
.legacy
.tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
302 surf
->surf_size
= surf_level
->offset
+ AddrSurfInfoOut
->surfSize
;
304 /* Clear DCC fields at the beginning. */
305 surf_level
->dcc_offset
= 0;
307 /* The previous level's flag tells us if we can use DCC for this level. */
308 if (AddrSurfInfoIn
->flags
.dccCompatible
&&
309 (level
== 0 || AddrDccOut
->subLvlCompressible
)) {
310 AddrDccIn
->colorSurfSize
= AddrSurfInfoOut
->surfSize
;
311 AddrDccIn
->tileMode
= AddrSurfInfoOut
->tileMode
;
312 AddrDccIn
->tileInfo
= *AddrSurfInfoOut
->pTileInfo
;
313 AddrDccIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
314 AddrDccIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
316 ret
= AddrComputeDccInfo(addrlib
,
320 if (ret
== ADDR_OK
) {
321 surf_level
->dcc_offset
= surf
->dcc_size
;
322 surf_level
->dcc_fast_clear_size
= AddrDccOut
->dccFastClearSize
;
323 surf
->num_dcc_levels
= level
+ 1;
324 surf
->dcc_size
= surf_level
->dcc_offset
+ AddrDccOut
->dccRamSize
;
325 surf
->dcc_alignment
= MAX2(surf
->dcc_alignment
, AddrDccOut
->dccRamBaseAlign
);
329 /* TC-compatible HTILE. */
331 AddrSurfInfoIn
->flags
.depth
&&
332 AddrSurfInfoIn
->flags
.tcCompatible
&&
333 surf_level
->mode
== RADEON_SURF_MODE_2D
&&
335 AddrHtileIn
->flags
.tcCompatible
= 1;
336 AddrHtileIn
->pitch
= AddrSurfInfoOut
->pitch
;
337 AddrHtileIn
->height
= AddrSurfInfoOut
->height
;
338 AddrHtileIn
->numSlices
= AddrSurfInfoOut
->depth
;
339 AddrHtileIn
->blockWidth
= ADDR_HTILE_BLOCKSIZE_8
;
340 AddrHtileIn
->blockHeight
= ADDR_HTILE_BLOCKSIZE_8
;
341 AddrHtileIn
->pTileInfo
= AddrSurfInfoOut
->pTileInfo
;
342 AddrHtileIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
343 AddrHtileIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
345 ret
= AddrComputeHtileInfo(addrlib
,
349 if (ret
== ADDR_OK
) {
350 surf
->htile_size
= AddrHtileOut
->htileBytes
;
351 surf
->htile_alignment
= AddrHtileOut
->baseAlign
;
358 #define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03)
359 #define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07)
361 static void gfx6_set_micro_tile_mode(struct radeon_surf
*surf
,
362 const struct amdgpu_gpu_info
*amdinfo
)
364 uint32_t tile_mode
= amdinfo
->gb_tile_mode
[surf
->u
.legacy
.tiling_index
[0]];
366 if (amdinfo
->family_id
>= AMDGPU_FAMILY_CI
)
367 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE_NEW(tile_mode
);
369 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE(tile_mode
);
372 static unsigned cik_get_macro_tile_index(struct radeon_surf
*surf
)
374 unsigned index
, tileb
;
376 tileb
= 8 * 8 * surf
->bpe
;
377 tileb
= MIN2(surf
->u
.legacy
.tile_split
, tileb
);
379 for (index
= 0; tileb
> 64; index
++)
387 * Fill in the tiling information in \p surf based on the given surface config.
389 * The following fields of \p surf must be initialized by the caller:
390 * blk_w, blk_h, bpe, flags.
392 static int gfx6_compute_surface(ADDR_HANDLE addrlib
,
393 const struct ac_surf_config
*config
,
394 enum radeon_surf_mode mode
,
395 struct radeon_surf
*surf
)
399 ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
400 ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut
= {0};
401 ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn
= {0};
402 ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut
= {0};
403 ADDR_COMPUTE_HTILE_INFO_INPUT AddrHtileIn
= {0};
404 ADDR_COMPUTE_HTILE_INFO_OUTPUT AddrHtileOut
= {0};
405 ADDR_TILEINFO AddrTileInfoIn
= {0};
406 ADDR_TILEINFO AddrTileInfoOut
= {0};
409 AddrSurfInfoIn
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT
);
410 AddrSurfInfoOut
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT
);
411 AddrDccIn
.size
= sizeof(ADDR_COMPUTE_DCCINFO_INPUT
);
412 AddrDccOut
.size
= sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT
);
413 AddrHtileIn
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT
);
414 AddrHtileOut
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT
);
415 AddrSurfInfoOut
.pTileInfo
= &AddrTileInfoOut
;
417 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
419 /* MSAA and FMASK require 2D tiling. */
420 if (config
->info
.samples
> 1 ||
421 (surf
->flags
& RADEON_SURF_FMASK
))
422 mode
= RADEON_SURF_MODE_2D
;
424 /* DB doesn't support linear layouts. */
425 if (surf
->flags
& (RADEON_SURF_Z_OR_SBUFFER
) &&
426 mode
< RADEON_SURF_MODE_1D
)
427 mode
= RADEON_SURF_MODE_1D
;
429 /* Set the requested tiling mode. */
431 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
432 AddrSurfInfoIn
.tileMode
= ADDR_TM_LINEAR_ALIGNED
;
434 case RADEON_SURF_MODE_1D
:
435 AddrSurfInfoIn
.tileMode
= ADDR_TM_1D_TILED_THIN1
;
437 case RADEON_SURF_MODE_2D
:
438 AddrSurfInfoIn
.tileMode
= ADDR_TM_2D_TILED_THIN1
;
444 /* The format must be set correctly for the allocation of compressed
445 * textures to work. In other cases, setting the bpp is sufficient.
450 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
453 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
460 AddrDccIn
.bpp
= AddrSurfInfoIn
.bpp
= surf
->bpe
* 8;
463 AddrDccIn
.numSamples
= AddrSurfInfoIn
.numSamples
=
464 config
->info
.samples
? config
->info
.samples
: 1;
465 AddrSurfInfoIn
.tileIndex
= -1;
467 /* Set the micro tile type. */
468 if (surf
->flags
& RADEON_SURF_SCANOUT
)
469 AddrSurfInfoIn
.tileType
= ADDR_DISPLAYABLE
;
470 else if (surf
->flags
& (RADEON_SURF_Z_OR_SBUFFER
| RADEON_SURF_FMASK
))
471 AddrSurfInfoIn
.tileType
= ADDR_DEPTH_SAMPLE_ORDER
;
473 AddrSurfInfoIn
.tileType
= ADDR_NON_DISPLAYABLE
;
475 AddrSurfInfoIn
.flags
.color
= !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
);
476 AddrSurfInfoIn
.flags
.depth
= (surf
->flags
& RADEON_SURF_ZBUFFER
) != 0;
477 AddrSurfInfoIn
.flags
.cube
= config
->is_cube
;
478 AddrSurfInfoIn
.flags
.fmask
= (surf
->flags
& RADEON_SURF_FMASK
) != 0;
479 AddrSurfInfoIn
.flags
.display
= (surf
->flags
& RADEON_SURF_SCANOUT
) != 0;
480 AddrSurfInfoIn
.flags
.pow2Pad
= config
->info
.levels
> 1;
481 AddrSurfInfoIn
.flags
.tcCompatible
= (surf
->flags
& RADEON_SURF_TC_COMPATIBLE_HTILE
) != 0;
483 /* Only degrade the tile mode for space if TC-compatible HTILE hasn't been
484 * requested, because TC-compatible HTILE requires 2D tiling.
486 AddrSurfInfoIn
.flags
.opt4Space
= !AddrSurfInfoIn
.flags
.tcCompatible
&&
487 !AddrSurfInfoIn
.flags
.fmask
&&
488 config
->info
.samples
<= 1 &&
489 (surf
->flags
& RADEON_SURF_OPTIMIZE_FOR_SPACE
);
492 * - If we add MSAA support, keep in mind that CB can't decompress 8bpp
494 * - Mipmapped array textures have low performance (discovered by a closed
497 AddrSurfInfoIn
.flags
.dccCompatible
=
498 config
->chip_class
>= VI
&&
499 !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
) &&
500 !(surf
->flags
& RADEON_SURF_DISABLE_DCC
) &&
501 !compressed
&& AddrDccIn
.numSamples
<= 1 &&
502 ((config
->info
.array_size
== 1 && config
->info
.depth
== 1) ||
503 config
->info
.levels
== 1);
505 AddrSurfInfoIn
.flags
.noStencil
= (surf
->flags
& RADEON_SURF_SBUFFER
) == 0;
506 AddrSurfInfoIn
.flags
.compressZ
= AddrSurfInfoIn
.flags
.depth
;
508 /* noStencil = 0 can result in a depth part that is incompatible with
509 * mipmapped texturing. So set noStencil = 1 when mipmaps are requested (in
510 * this case, we may end up setting stencil_adjusted).
512 * TODO: update addrlib to a newer version, remove this, and
513 * use flags.matchStencilTileCfg = 1 as an alternative fix.
515 if (config
->info
.levels
> 1)
516 AddrSurfInfoIn
.flags
.noStencil
= 1;
518 /* Set preferred macrotile parameters. This is usually required
519 * for shared resources. This is for 2D tiling only. */
520 if (AddrSurfInfoIn
.tileMode
>= ADDR_TM_2D_TILED_THIN1
&&
521 surf
->u
.legacy
.bankw
&& surf
->u
.legacy
.bankh
&&
522 surf
->u
.legacy
.mtilea
&& surf
->u
.legacy
.tile_split
) {
523 assert(!(surf
->flags
& RADEON_SURF_FMASK
));
525 /* If any of these parameters are incorrect, the calculation
527 AddrTileInfoIn
.banks
= surf
->u
.legacy
.num_banks
;
528 AddrTileInfoIn
.bankWidth
= surf
->u
.legacy
.bankw
;
529 AddrTileInfoIn
.bankHeight
= surf
->u
.legacy
.bankh
;
530 AddrTileInfoIn
.macroAspectRatio
= surf
->u
.legacy
.mtilea
;
531 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.tile_split
;
532 AddrTileInfoIn
.pipeConfig
= surf
->u
.legacy
.pipe_config
+ 1; /* +1 compared to GB_TILE_MODE */
533 AddrSurfInfoIn
.flags
.opt4Space
= 0;
534 AddrSurfInfoIn
.pTileInfo
= &AddrTileInfoIn
;
536 /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set
537 * the tile index, because we are expected to know it if
538 * we know the other parameters.
540 * This is something that can easily be fixed in Addrlib.
541 * For now, just figure it out here.
542 * Note that only 2D_TILE_THIN1 is handled here.
544 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
545 assert(AddrSurfInfoIn
.tileMode
== ADDR_TM_2D_TILED_THIN1
);
547 if (config
->chip_class
== SI
) {
548 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
) {
550 AddrSurfInfoIn
.tileIndex
= 11; /* 16bpp */
552 AddrSurfInfoIn
.tileIndex
= 12; /* 32bpp */
555 AddrSurfInfoIn
.tileIndex
= 14; /* 8bpp */
556 else if (surf
->bpe
== 2)
557 AddrSurfInfoIn
.tileIndex
= 15; /* 16bpp */
558 else if (surf
->bpe
== 4)
559 AddrSurfInfoIn
.tileIndex
= 16; /* 32bpp */
561 AddrSurfInfoIn
.tileIndex
= 17; /* 64bpp (and 128bpp) */
565 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
)
566 AddrSurfInfoIn
.tileIndex
= 10; /* 2D displayable */
568 AddrSurfInfoIn
.tileIndex
= 14; /* 2D non-displayable */
570 /* Addrlib doesn't set this if tileIndex is forced like above. */
571 AddrSurfInfoOut
.macroModeIndex
= cik_get_macro_tile_index(surf
);
575 surf
->num_dcc_levels
= 0;
578 surf
->dcc_alignment
= 1;
579 surf
->htile_size
= 0;
580 surf
->htile_alignment
= 1;
582 /* Calculate texture layout information. */
583 for (level
= 0; level
< config
->info
.levels
; level
++) {
584 r
= gfx6_compute_level(addrlib
, config
, surf
, false, level
, compressed
,
585 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
586 &AddrDccIn
, &AddrDccOut
, &AddrHtileIn
, &AddrHtileOut
);
591 surf
->surf_alignment
= AddrSurfInfoOut
.baseAlign
;
592 surf
->u
.legacy
.pipe_config
= AddrSurfInfoOut
.pTileInfo
->pipeConfig
- 1;
593 gfx6_set_micro_tile_mode(surf
, config
->amdinfo
);
595 /* For 2D modes only. */
596 if (AddrSurfInfoOut
.tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
597 surf
->u
.legacy
.bankw
= AddrSurfInfoOut
.pTileInfo
->bankWidth
;
598 surf
->u
.legacy
.bankh
= AddrSurfInfoOut
.pTileInfo
->bankHeight
;
599 surf
->u
.legacy
.mtilea
= AddrSurfInfoOut
.pTileInfo
->macroAspectRatio
;
600 surf
->u
.legacy
.tile_split
= AddrSurfInfoOut
.pTileInfo
->tileSplitBytes
;
601 surf
->u
.legacy
.num_banks
= AddrSurfInfoOut
.pTileInfo
->banks
;
602 surf
->u
.legacy
.macro_tile_index
= AddrSurfInfoOut
.macroModeIndex
;
604 surf
->u
.legacy
.macro_tile_index
= 0;
609 /* Calculate texture layout information for stencil. */
610 if (surf
->flags
& RADEON_SURF_SBUFFER
) {
611 AddrSurfInfoIn
.bpp
= 8;
612 AddrSurfInfoIn
.flags
.depth
= 0;
613 AddrSurfInfoIn
.flags
.stencil
= 1;
614 AddrSurfInfoIn
.flags
.tcCompatible
= 0;
615 /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */
616 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.stencil_tile_split
;
618 for (level
= 0; level
< config
->info
.levels
; level
++) {
619 r
= gfx6_compute_level(addrlib
, config
, surf
, true, level
, compressed
,
620 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
621 &AddrDccIn
, &AddrDccOut
,
626 /* DB uses the depth pitch for both stencil and depth. */
627 if (surf
->u
.legacy
.stencil_level
[level
].nblk_x
!=
628 surf
->u
.legacy
.level
[level
].nblk_x
)
629 surf
->u
.legacy
.stencil_adjusted
= true;
632 /* For 2D modes only. */
633 if (AddrSurfInfoOut
.tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
634 surf
->u
.legacy
.stencil_tile_split
=
635 AddrSurfInfoOut
.pTileInfo
->tileSplitBytes
;
641 /* Recalculate the whole DCC miptree size including disabled levels.
642 * This is what addrlib does, but calling addrlib would be a lot more
645 if (surf
->dcc_size
&& config
->info
.levels
> 1) {
646 surf
->dcc_size
= align64(surf
->surf_size
>> 8,
647 config
->pipe_interleave_bytes
*
648 config
->num_tile_pipes
);
651 /* Make sure HTILE covers the whole miptree, because the shader reads
652 * TC-compatible HTILE even for levels where it's disabled by DB.
654 if (surf
->htile_size
&& config
->info
.levels
> 1)
655 surf
->htile_size
*= 2;
657 surf
->is_linear
= surf
->u
.legacy
.level
[0].mode
== RADEON_SURF_MODE_LINEAR_ALIGNED
;
661 /* This is only called when expecting a tiled layout. */
663 gfx9_get_preferred_swizzle_mode(ADDR_HANDLE addrlib
,
664 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
,
665 bool is_fmask
, AddrSwizzleMode
*swizzle_mode
)
667 ADDR_E_RETURNCODE ret
;
668 ADDR2_GET_PREFERRED_SURF_SETTING_INPUT sin
= {0};
669 ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT sout
= {0};
671 sin
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_INPUT
);
672 sout
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT
);
674 sin
.flags
= in
->flags
;
675 sin
.resourceType
= in
->resourceType
;
676 sin
.format
= in
->format
;
677 sin
.resourceLoction
= ADDR_RSRC_LOC_INVIS
;
678 /* TODO: We could allow some of these: */
679 sin
.forbiddenBlock
.micro
= 1; /* don't allow the 256B swizzle modes */
680 sin
.forbiddenBlock
.var
= 1; /* don't allow the variable-sized swizzle modes */
681 sin
.forbiddenBlock
.linear
= 1; /* don't allow linear swizzle modes */
683 sin
.width
= in
->width
;
684 sin
.height
= in
->height
;
685 sin
.numSlices
= in
->numSlices
;
686 sin
.numMipLevels
= in
->numMipLevels
;
687 sin
.numSamples
= in
->numSamples
;
688 sin
.numFrags
= in
->numFrags
;
695 ret
= Addr2GetPreferredSurfaceSetting(addrlib
, &sin
, &sout
);
699 *swizzle_mode
= sout
.swizzleMode
;
703 static int gfx9_compute_miptree(ADDR_HANDLE addrlib
,
704 struct radeon_surf
*surf
, bool compressed
,
705 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
)
707 ADDR2_MIP_INFO mip_info
[RADEON_SURF_MAX_LEVELS
] = {};
708 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT out
= {0};
709 ADDR_E_RETURNCODE ret
;
711 out
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT
);
712 out
.pMipInfo
= mip_info
;
714 ret
= Addr2ComputeSurfaceInfo(addrlib
, in
, &out
);
718 if (in
->flags
.stencil
) {
719 surf
->u
.gfx9
.stencil
.swizzle_mode
= in
->swizzleMode
;
720 surf
->u
.gfx9
.stencil
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
721 out
.mipChainPitch
- 1;
722 surf
->surf_alignment
= MAX2(surf
->surf_alignment
, out
.baseAlign
);
723 surf
->u
.gfx9
.stencil_offset
= align(surf
->surf_size
, out
.baseAlign
);
724 surf
->surf_size
= surf
->u
.gfx9
.stencil_offset
+ out
.surfSize
;
728 surf
->u
.gfx9
.surf
.swizzle_mode
= in
->swizzleMode
;
729 surf
->u
.gfx9
.surf
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
730 out
.mipChainPitch
- 1;
732 /* CMASK fast clear uses these even if FMASK isn't allocated.
733 * FMASK only supports the Z swizzle modes, whose numbers are multiples of 4.
735 surf
->u
.gfx9
.fmask
.swizzle_mode
= surf
->u
.gfx9
.surf
.swizzle_mode
& ~0x3;
736 surf
->u
.gfx9
.fmask
.epitch
= surf
->u
.gfx9
.surf
.epitch
;
738 surf
->u
.gfx9
.surf_slice_size
= out
.sliceSize
;
739 surf
->u
.gfx9
.surf_pitch
= out
.pitch
;
740 surf
->u
.gfx9
.surf_height
= out
.height
;
741 surf
->surf_size
= out
.surfSize
;
742 surf
->surf_alignment
= out
.baseAlign
;
744 if (in
->swizzleMode
== ADDR_SW_LINEAR
) {
745 for (unsigned i
= 0; i
< in
->numMipLevels
; i
++)
746 surf
->u
.gfx9
.offset
[i
] = mip_info
[i
].offset
;
749 if (in
->flags
.depth
) {
750 assert(in
->swizzleMode
!= ADDR_SW_LINEAR
);
753 ADDR2_COMPUTE_HTILE_INFO_INPUT hin
= {0};
754 ADDR2_COMPUTE_HTILE_INFO_OUTPUT hout
= {0};
756 hin
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT
);
757 hout
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT
);
759 hin
.hTileFlags
.pipeAligned
= 1;
760 hin
.hTileFlags
.rbAligned
= 1;
761 hin
.depthFlags
= in
->flags
;
762 hin
.swizzleMode
= in
->swizzleMode
;
763 hin
.unalignedWidth
= in
->width
;
764 hin
.unalignedHeight
= in
->height
;
765 hin
.numSlices
= in
->numSlices
;
766 hin
.numMipLevels
= in
->numMipLevels
;
768 ret
= Addr2ComputeHtileInfo(addrlib
, &hin
, &hout
);
772 surf
->u
.gfx9
.htile
.rb_aligned
= hin
.hTileFlags
.rbAligned
;
773 surf
->u
.gfx9
.htile
.pipe_aligned
= hin
.hTileFlags
.pipeAligned
;
774 surf
->htile_size
= hout
.htileBytes
;
775 surf
->htile_alignment
= hout
.baseAlign
;
778 if (!(surf
->flags
& RADEON_SURF_DISABLE_DCC
) &&
779 !(surf
->flags
& RADEON_SURF_SCANOUT
) &&
781 in
->swizzleMode
!= ADDR_SW_LINEAR
&&
782 /* TODO: We could support DCC with MSAA. */
783 in
->numSamples
== 1) {
784 ADDR2_COMPUTE_DCCINFO_INPUT din
= {0};
785 ADDR2_COMPUTE_DCCINFO_OUTPUT dout
= {0};
787 din
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_INPUT
);
788 dout
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT
);
790 din
.dccKeyFlags
.pipeAligned
= 1;
791 din
.dccKeyFlags
.rbAligned
= 1;
792 din
.colorFlags
= in
->flags
;
793 din
.resourceType
= in
->resourceType
;
794 din
.swizzleMode
= in
->swizzleMode
;
796 din
.unalignedWidth
= in
->width
;
797 din
.unalignedHeight
= in
->height
;
798 din
.numSlices
= in
->numSlices
;
799 din
.numFrags
= in
->numFrags
;
800 din
.numMipLevels
= in
->numMipLevels
;
801 din
.dataSurfaceSize
= out
.surfSize
;
803 ret
= Addr2ComputeDccInfo(addrlib
, &din
, &dout
);
807 surf
->u
.gfx9
.dcc
.rb_aligned
= din
.dccKeyFlags
.rbAligned
;
808 surf
->u
.gfx9
.dcc
.pipe_aligned
= din
.dccKeyFlags
.pipeAligned
;
809 surf
->u
.gfx9
.dcc_pitch_max
= dout
.pitch
- 1;
810 surf
->dcc_size
= dout
.dccRamSize
;
811 surf
->dcc_alignment
= dout
.dccRamBaseAlign
;
815 if (in
->numSamples
> 1) {
816 ADDR2_COMPUTE_FMASK_INFO_INPUT fin
= {0};
817 ADDR2_COMPUTE_FMASK_INFO_OUTPUT fout
= {0};
819 fin
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT
);
820 fout
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT
);
822 ret
= gfx9_get_preferred_swizzle_mode(addrlib
, in
, true, &fin
.swizzleMode
);
826 fin
.unalignedWidth
= in
->width
;
827 fin
.unalignedHeight
= in
->height
;
828 fin
.numSlices
= in
->numSlices
;
829 fin
.numSamples
= in
->numSamples
;
830 fin
.numFrags
= in
->numFrags
;
832 ret
= Addr2ComputeFmaskInfo(addrlib
, &fin
, &fout
);
836 surf
->u
.gfx9
.fmask
.swizzle_mode
= fin
.swizzleMode
;
837 surf
->u
.gfx9
.fmask
.epitch
= fout
.pitch
- 1;
838 surf
->u
.gfx9
.fmask_size
= fout
.fmaskBytes
;
839 surf
->u
.gfx9
.fmask_alignment
= fout
.baseAlign
;
843 if (in
->swizzleMode
!= ADDR_SW_LINEAR
) {
844 ADDR2_COMPUTE_CMASK_INFO_INPUT cin
= {0};
845 ADDR2_COMPUTE_CMASK_INFO_OUTPUT cout
= {0};
847 cin
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT
);
848 cout
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT
);
850 cin
.cMaskFlags
.pipeAligned
= 1;
851 cin
.cMaskFlags
.rbAligned
= 1;
852 cin
.colorFlags
= in
->flags
;
853 cin
.resourceType
= in
->resourceType
;
854 cin
.unalignedWidth
= in
->width
;
855 cin
.unalignedHeight
= in
->height
;
856 cin
.numSlices
= in
->numSlices
;
858 if (in
->numSamples
> 1)
859 cin
.swizzleMode
= surf
->u
.gfx9
.fmask
.swizzle_mode
;
861 cin
.swizzleMode
= in
->swizzleMode
;
863 ret
= Addr2ComputeCmaskInfo(addrlib
, &cin
, &cout
);
867 surf
->u
.gfx9
.cmask
.rb_aligned
= cin
.cMaskFlags
.rbAligned
;
868 surf
->u
.gfx9
.cmask
.pipe_aligned
= cin
.cMaskFlags
.pipeAligned
;
869 surf
->u
.gfx9
.cmask_size
= cout
.cmaskBytes
;
870 surf
->u
.gfx9
.cmask_alignment
= cout
.baseAlign
;
877 static int gfx9_compute_surface(ADDR_HANDLE addrlib
,
878 const struct ac_surf_config
*config
,
879 enum radeon_surf_mode mode
,
880 struct radeon_surf
*surf
)
883 ADDR2_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
886 assert(!(surf
->flags
& RADEON_SURF_FMASK
));
888 AddrSurfInfoIn
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT
);
890 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
892 /* The format must be set correctly for the allocation of compressed
893 * textures to work. In other cases, setting the bpp is sufficient. */
897 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
900 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
906 AddrSurfInfoIn
.bpp
= surf
->bpe
* 8;
909 AddrSurfInfoIn
.flags
.color
= !(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
);
910 AddrSurfInfoIn
.flags
.depth
= (surf
->flags
& RADEON_SURF_ZBUFFER
) != 0;
911 AddrSurfInfoIn
.flags
.display
= (surf
->flags
& RADEON_SURF_SCANOUT
) != 0;
912 AddrSurfInfoIn
.flags
.texture
= 1;
913 AddrSurfInfoIn
.flags
.opt4space
= 1;
915 AddrSurfInfoIn
.numMipLevels
= config
->info
.levels
;
916 AddrSurfInfoIn
.numSamples
= config
->info
.samples
? config
->info
.samples
: 1;
917 AddrSurfInfoIn
.numFrags
= AddrSurfInfoIn
.numSamples
;
919 /* GFX9 doesn't support 1D depth textures, so allocate all 1D textures
920 * as 2D to avoid having shader variants for 1D vs 2D, so all shaders
921 * must sample 1D textures as 2D. */
923 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_3D
;
925 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_2D
;
927 AddrSurfInfoIn
.width
= config
->info
.width
;
928 AddrSurfInfoIn
.height
= config
->info
.height
;
931 AddrSurfInfoIn
.numSlices
= config
->info
.depth
;
932 else if (config
->is_cube
)
933 AddrSurfInfoIn
.numSlices
= 6;
935 AddrSurfInfoIn
.numSlices
= config
->info
.array_size
;
938 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
939 assert(config
->info
.samples
<= 1);
940 assert(!(surf
->flags
& RADEON_SURF_Z_OR_SBUFFER
));
941 AddrSurfInfoIn
.swizzleMode
= ADDR_SW_LINEAR
;
944 case RADEON_SURF_MODE_1D
:
945 case RADEON_SURF_MODE_2D
:
946 r
= gfx9_get_preferred_swizzle_mode(addrlib
, &AddrSurfInfoIn
, false,
947 &AddrSurfInfoIn
.swizzleMode
);
956 surf
->u
.gfx9
.resource_type
= AddrSurfInfoIn
.resourceType
;
960 surf
->htile_size
= 0;
961 surf
->u
.gfx9
.surf_offset
= 0;
962 surf
->u
.gfx9
.stencil_offset
= 0;
963 surf
->u
.gfx9
.fmask_size
= 0;
964 surf
->u
.gfx9
.cmask_size
= 0;
966 /* Calculate texture layout information. */
967 r
= gfx9_compute_miptree(addrlib
, surf
, compressed
, &AddrSurfInfoIn
);
971 /* Calculate texture layout information for stencil. */
972 if (surf
->flags
& RADEON_SURF_SBUFFER
) {
973 AddrSurfInfoIn
.bpp
= 8;
974 AddrSurfInfoIn
.flags
.depth
= 0;
975 AddrSurfInfoIn
.flags
.stencil
= 1;
977 r
= gfx9_compute_miptree(addrlib
, surf
, compressed
, &AddrSurfInfoIn
);
982 surf
->is_linear
= surf
->u
.gfx9
.surf
.swizzle_mode
== ADDR_SW_LINEAR
;
983 surf
->num_dcc_levels
= surf
->dcc_size
? config
->info
.levels
: 0;
985 switch (surf
->u
.gfx9
.surf
.swizzle_mode
) {
991 case ADDR_SW_64KB_S_T
:
992 case ADDR_SW_4KB_S_X
:
993 case ADDR_SW_64KB_S_X
:
994 case ADDR_SW_VAR_S_X
:
995 surf
->micro_tile_mode
= RADEON_MICRO_MODE_THIN
;
1000 case ADDR_SW_256B_D
:
1002 case ADDR_SW_64KB_D
:
1004 case ADDR_SW_64KB_D_T
:
1005 case ADDR_SW_4KB_D_X
:
1006 case ADDR_SW_64KB_D_X
:
1007 case ADDR_SW_VAR_D_X
:
1008 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DISPLAY
;
1012 case ADDR_SW_256B_R
:
1014 case ADDR_SW_64KB_R
:
1016 case ADDR_SW_64KB_R_T
:
1017 case ADDR_SW_4KB_R_X
:
1018 case ADDR_SW_64KB_R_X
:
1019 case ADDR_SW_VAR_R_X
:
1020 surf
->micro_tile_mode
= RADEON_MICRO_MODE_ROTATED
;
1025 case ADDR_SW_64KB_Z
:
1027 case ADDR_SW_64KB_Z_T
:
1028 case ADDR_SW_4KB_Z_X
:
1029 case ADDR_SW_64KB_Z_X
:
1030 case ADDR_SW_VAR_Z_X
:
1031 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DEPTH
;
1041 int ac_compute_surface(ADDR_HANDLE addrlib
,
1042 const struct ac_surf_config
*config
,
1043 enum radeon_surf_mode mode
,
1044 struct radeon_surf
*surf
)
1048 r
= surf_config_sanity(config
);
1052 if (config
->chip_class
>= GFX9
)
1053 return gfx9_compute_surface(addrlib
, config
, mode
, surf
);
1055 return gfx6_compute_surface(addrlib
, config
, mode
, surf
);