2 * Copyright © 2011 Red Hat All Rights Reserved.
3 * Copyright © 2014 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
29 * Marek Olšák <maraeo@gmail.com>
32 #include "amdgpu_winsys.h"
33 #include "util/u_format.h"
35 #ifndef CIASICIDGFXENGINE_SOUTHERNISLAND
36 #define CIASICIDGFXENGINE_SOUTHERNISLAND 0x0000000A
39 #ifndef CIASICIDGFXENGINE_ARCTICISLAND
40 #define CIASICIDGFXENGINE_ARCTICISLAND 0x0000000D
43 static int amdgpu_surface_sanity(const struct pipe_resource
*tex
)
45 /* all dimension must be at least 1 ! */
46 if (!tex
->width0
|| !tex
->height0
|| !tex
->depth0
||
50 switch (tex
->nr_samples
) {
61 switch (tex
->target
) {
67 case PIPE_TEXTURE_RECT
:
68 if (tex
->depth0
> 1 || tex
->array_size
> 1)
72 if (tex
->array_size
> 1)
75 case PIPE_TEXTURE_1D_ARRAY
:
79 case PIPE_TEXTURE_CUBE
:
80 case PIPE_TEXTURE_2D_ARRAY
:
81 case PIPE_TEXTURE_CUBE_ARRAY
:
91 static void *ADDR_API
allocSysMem(const ADDR_ALLOCSYSMEM_INPUT
* pInput
)
93 return malloc(pInput
->sizeInBytes
);
96 static ADDR_E_RETURNCODE ADDR_API
freeSysMem(const ADDR_FREESYSMEM_INPUT
* pInput
)
98 free(pInput
->pVirtAddr
);
102 ADDR_HANDLE
amdgpu_addr_create(struct amdgpu_winsys
*ws
)
104 ADDR_CREATE_INPUT addrCreateInput
= {0};
105 ADDR_CREATE_OUTPUT addrCreateOutput
= {0};
106 ADDR_REGISTER_VALUE regValue
= {0};
107 ADDR_CREATE_FLAGS createFlags
= {{0}};
108 ADDR_E_RETURNCODE addrRet
;
110 addrCreateInput
.size
= sizeof(ADDR_CREATE_INPUT
);
111 addrCreateOutput
.size
= sizeof(ADDR_CREATE_OUTPUT
);
113 regValue
.gbAddrConfig
= ws
->amdinfo
.gb_addr_cfg
;
114 createFlags
.value
= 0;
116 if (ws
->info
.chip_class
>= GFX9
) {
117 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_ARCTICISLAND
;
118 regValue
.blockVarSizeLog2
= 0;
120 regValue
.noOfBanks
= ws
->amdinfo
.mc_arb_ramcfg
& 0x3;
121 regValue
.noOfRanks
= (ws
->amdinfo
.mc_arb_ramcfg
& 0x4) >> 2;
123 regValue
.backendDisables
= ws
->amdinfo
.enabled_rb_pipes_mask
;
124 regValue
.pTileConfig
= ws
->amdinfo
.gb_tile_mode
;
125 regValue
.noOfEntries
= ARRAY_SIZE(ws
->amdinfo
.gb_tile_mode
);
126 if (ws
->info
.chip_class
== SI
) {
127 regValue
.pMacroTileConfig
= NULL
;
128 regValue
.noOfMacroEntries
= 0;
130 regValue
.pMacroTileConfig
= ws
->amdinfo
.gb_macro_tile_mode
;
131 regValue
.noOfMacroEntries
= ARRAY_SIZE(ws
->amdinfo
.gb_macro_tile_mode
);
134 createFlags
.useTileIndex
= 1;
135 createFlags
.useHtileSliceAlign
= 1;
137 addrCreateInput
.chipEngine
= CIASICIDGFXENGINE_SOUTHERNISLAND
;
138 addrCreateInput
.chipFamily
= ws
->family
;
139 addrCreateInput
.chipRevision
= ws
->rev_id
;
142 addrCreateInput
.chipFamily
= ws
->family
;
143 addrCreateInput
.chipRevision
= ws
->rev_id
;
144 addrCreateInput
.callbacks
.allocSysMem
= allocSysMem
;
145 addrCreateInput
.callbacks
.freeSysMem
= freeSysMem
;
146 addrCreateInput
.callbacks
.debugPrint
= 0;
147 addrCreateInput
.createFlags
= createFlags
;
148 addrCreateInput
.regValue
= regValue
;
150 addrRet
= AddrCreate(&addrCreateInput
, &addrCreateOutput
);
151 if (addrRet
!= ADDR_OK
)
154 return addrCreateOutput
.hLib
;
157 static int gfx6_compute_level(struct amdgpu_winsys
*ws
,
158 const struct pipe_resource
*tex
,
159 struct radeon_surf
*surf
, bool is_stencil
,
160 unsigned level
, bool compressed
,
161 ADDR_COMPUTE_SURFACE_INFO_INPUT
*AddrSurfInfoIn
,
162 ADDR_COMPUTE_SURFACE_INFO_OUTPUT
*AddrSurfInfoOut
,
163 ADDR_COMPUTE_DCCINFO_INPUT
*AddrDccIn
,
164 ADDR_COMPUTE_DCCINFO_OUTPUT
*AddrDccOut
,
165 ADDR_COMPUTE_HTILE_INFO_INPUT
*AddrHtileIn
,
166 ADDR_COMPUTE_HTILE_INFO_OUTPUT
*AddrHtileOut
)
168 struct legacy_surf_level
*surf_level
;
169 ADDR_E_RETURNCODE ret
;
171 AddrSurfInfoIn
->mipLevel
= level
;
172 AddrSurfInfoIn
->width
= u_minify(tex
->width0
, level
);
173 AddrSurfInfoIn
->height
= u_minify(tex
->height0
, level
);
175 if (tex
->target
== PIPE_TEXTURE_3D
)
176 AddrSurfInfoIn
->numSlices
= u_minify(tex
->depth0
, level
);
177 else if (tex
->target
== PIPE_TEXTURE_CUBE
)
178 AddrSurfInfoIn
->numSlices
= 6;
180 AddrSurfInfoIn
->numSlices
= tex
->array_size
;
183 /* Set the base level pitch. This is needed for calculation
184 * of non-zero levels. */
186 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.stencil_level
[0].nblk_x
;
188 AddrSurfInfoIn
->basePitch
= surf
->u
.legacy
.level
[0].nblk_x
;
190 /* Convert blocks to pixels for compressed formats. */
192 AddrSurfInfoIn
->basePitch
*= surf
->blk_w
;
195 ret
= AddrComputeSurfaceInfo(ws
->addrlib
,
198 if (ret
!= ADDR_OK
) {
202 surf_level
= is_stencil
? &surf
->u
.legacy
.stencil_level
[level
] : &surf
->u
.legacy
.level
[level
];
203 surf_level
->offset
= align64(surf
->surf_size
, AddrSurfInfoOut
->baseAlign
);
204 surf_level
->slice_size
= AddrSurfInfoOut
->sliceSize
;
205 surf_level
->nblk_x
= AddrSurfInfoOut
->pitch
;
206 surf_level
->nblk_y
= AddrSurfInfoOut
->height
;
208 switch (AddrSurfInfoOut
->tileMode
) {
209 case ADDR_TM_LINEAR_ALIGNED
:
210 surf_level
->mode
= RADEON_SURF_MODE_LINEAR_ALIGNED
;
212 case ADDR_TM_1D_TILED_THIN1
:
213 surf_level
->mode
= RADEON_SURF_MODE_1D
;
215 case ADDR_TM_2D_TILED_THIN1
:
216 surf_level
->mode
= RADEON_SURF_MODE_2D
;
223 surf
->u
.legacy
.stencil_tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
225 surf
->u
.legacy
.tiling_index
[level
] = AddrSurfInfoOut
->tileIndex
;
227 surf
->surf_size
= surf_level
->offset
+ AddrSurfInfoOut
->surfSize
;
229 /* Clear DCC fields at the beginning. */
230 surf_level
->dcc_offset
= 0;
232 /* The previous level's flag tells us if we can use DCC for this level. */
233 if (AddrSurfInfoIn
->flags
.dccCompatible
&&
234 (level
== 0 || AddrDccOut
->subLvlCompressible
)) {
235 AddrDccIn
->colorSurfSize
= AddrSurfInfoOut
->surfSize
;
236 AddrDccIn
->tileMode
= AddrSurfInfoOut
->tileMode
;
237 AddrDccIn
->tileInfo
= *AddrSurfInfoOut
->pTileInfo
;
238 AddrDccIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
239 AddrDccIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
241 ret
= AddrComputeDccInfo(ws
->addrlib
,
245 if (ret
== ADDR_OK
) {
246 surf_level
->dcc_offset
= surf
->dcc_size
;
247 surf_level
->dcc_fast_clear_size
= AddrDccOut
->dccFastClearSize
;
248 surf
->num_dcc_levels
= level
+ 1;
249 surf
->dcc_size
= surf_level
->dcc_offset
+ AddrDccOut
->dccRamSize
;
250 surf
->dcc_alignment
= MAX2(surf
->dcc_alignment
, AddrDccOut
->dccRamBaseAlign
);
254 /* TC-compatible HTILE. */
256 AddrSurfInfoIn
->flags
.depth
&&
257 AddrSurfInfoIn
->flags
.tcCompatible
&&
258 surf_level
->mode
== RADEON_SURF_MODE_2D
&&
260 AddrHtileIn
->flags
.tcCompatible
= 1;
261 AddrHtileIn
->pitch
= AddrSurfInfoOut
->pitch
;
262 AddrHtileIn
->height
= AddrSurfInfoOut
->height
;
263 AddrHtileIn
->numSlices
= AddrSurfInfoOut
->depth
;
264 AddrHtileIn
->blockWidth
= ADDR_HTILE_BLOCKSIZE_8
;
265 AddrHtileIn
->blockHeight
= ADDR_HTILE_BLOCKSIZE_8
;
266 AddrHtileIn
->pTileInfo
= AddrSurfInfoOut
->pTileInfo
;
267 AddrHtileIn
->tileIndex
= AddrSurfInfoOut
->tileIndex
;
268 AddrHtileIn
->macroModeIndex
= AddrSurfInfoOut
->macroModeIndex
;
270 ret
= AddrComputeHtileInfo(ws
->addrlib
,
274 if (ret
== ADDR_OK
) {
275 surf
->htile_size
= AddrHtileOut
->htileBytes
;
276 surf
->htile_alignment
= AddrHtileOut
->baseAlign
;
283 #define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03)
284 #define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07)
286 static void gfx6_set_micro_tile_mode(struct radeon_surf
*surf
,
287 struct radeon_info
*info
)
289 uint32_t tile_mode
= info
->si_tile_mode_array
[surf
->u
.legacy
.tiling_index
[0]];
291 if (info
->chip_class
>= CIK
)
292 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE_NEW(tile_mode
);
294 surf
->micro_tile_mode
= G_009910_MICRO_TILE_MODE(tile_mode
);
297 static unsigned cik_get_macro_tile_index(struct radeon_surf
*surf
)
299 unsigned index
, tileb
;
301 tileb
= 8 * 8 * surf
->bpe
;
302 tileb
= MIN2(surf
->u
.legacy
.tile_split
, tileb
);
304 for (index
= 0; tileb
> 64; index
++)
311 static int gfx6_surface_init(struct radeon_winsys
*rws
,
312 const struct pipe_resource
*tex
,
313 unsigned flags
, unsigned bpe
,
314 enum radeon_surf_mode mode
,
315 struct radeon_surf
*surf
)
317 struct amdgpu_winsys
*ws
= (struct amdgpu_winsys
*)rws
;
320 ADDR_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
321 ADDR_COMPUTE_SURFACE_INFO_OUTPUT AddrSurfInfoOut
= {0};
322 ADDR_COMPUTE_DCCINFO_INPUT AddrDccIn
= {0};
323 ADDR_COMPUTE_DCCINFO_OUTPUT AddrDccOut
= {0};
324 ADDR_COMPUTE_HTILE_INFO_INPUT AddrHtileIn
= {0};
325 ADDR_COMPUTE_HTILE_INFO_OUTPUT AddrHtileOut
= {0};
326 ADDR_TILEINFO AddrTileInfoIn
= {0};
327 ADDR_TILEINFO AddrTileInfoOut
= {0};
330 r
= amdgpu_surface_sanity(tex
);
334 AddrSurfInfoIn
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_INPUT
);
335 AddrSurfInfoOut
.size
= sizeof(ADDR_COMPUTE_SURFACE_INFO_OUTPUT
);
336 AddrDccIn
.size
= sizeof(ADDR_COMPUTE_DCCINFO_INPUT
);
337 AddrDccOut
.size
= sizeof(ADDR_COMPUTE_DCCINFO_OUTPUT
);
338 AddrHtileIn
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_INPUT
);
339 AddrHtileOut
.size
= sizeof(ADDR_COMPUTE_HTILE_INFO_OUTPUT
);
340 AddrSurfInfoOut
.pTileInfo
= &AddrTileInfoOut
;
342 surf
->blk_w
= util_format_get_blockwidth(tex
->format
);
343 surf
->blk_h
= util_format_get_blockheight(tex
->format
);
347 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
349 /* MSAA and FMASK require 2D tiling. */
350 if (tex
->nr_samples
> 1 ||
351 (flags
& RADEON_SURF_FMASK
))
352 mode
= RADEON_SURF_MODE_2D
;
354 /* DB doesn't support linear layouts. */
355 if (flags
& (RADEON_SURF_Z_OR_SBUFFER
) &&
356 mode
< RADEON_SURF_MODE_1D
)
357 mode
= RADEON_SURF_MODE_1D
;
359 /* Set the requested tiling mode. */
361 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
362 AddrSurfInfoIn
.tileMode
= ADDR_TM_LINEAR_ALIGNED
;
364 case RADEON_SURF_MODE_1D
:
365 AddrSurfInfoIn
.tileMode
= ADDR_TM_1D_TILED_THIN1
;
367 case RADEON_SURF_MODE_2D
:
368 AddrSurfInfoIn
.tileMode
= ADDR_TM_2D_TILED_THIN1
;
374 /* The format must be set correctly for the allocation of compressed
375 * textures to work. In other cases, setting the bpp is sufficient. */
379 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
382 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
389 AddrDccIn
.bpp
= AddrSurfInfoIn
.bpp
= bpe
* 8;
392 AddrDccIn
.numSamples
= AddrSurfInfoIn
.numSamples
=
393 tex
->nr_samples
? tex
->nr_samples
: 1;
394 AddrSurfInfoIn
.tileIndex
= -1;
396 /* Set the micro tile type. */
397 if (flags
& RADEON_SURF_SCANOUT
)
398 AddrSurfInfoIn
.tileType
= ADDR_DISPLAYABLE
;
399 else if (flags
& (RADEON_SURF_Z_OR_SBUFFER
| RADEON_SURF_FMASK
))
400 AddrSurfInfoIn
.tileType
= ADDR_DEPTH_SAMPLE_ORDER
;
402 AddrSurfInfoIn
.tileType
= ADDR_NON_DISPLAYABLE
;
404 AddrSurfInfoIn
.flags
.color
= !(flags
& RADEON_SURF_Z_OR_SBUFFER
);
405 AddrSurfInfoIn
.flags
.depth
= (flags
& RADEON_SURF_ZBUFFER
) != 0;
406 AddrSurfInfoIn
.flags
.cube
= tex
->target
== PIPE_TEXTURE_CUBE
;
407 AddrSurfInfoIn
.flags
.fmask
= (flags
& RADEON_SURF_FMASK
) != 0;
408 AddrSurfInfoIn
.flags
.display
= (flags
& RADEON_SURF_SCANOUT
) != 0;
409 AddrSurfInfoIn
.flags
.pow2Pad
= tex
->last_level
> 0;
410 AddrSurfInfoIn
.flags
.tcCompatible
= (flags
& RADEON_SURF_TC_COMPATIBLE_HTILE
) != 0;
412 /* Only degrade the tile mode for space if TC-compatible HTILE hasn't been
413 * requested, because TC-compatible HTILE requires 2D tiling.
415 AddrSurfInfoIn
.flags
.opt4Space
= !AddrSurfInfoIn
.flags
.tcCompatible
&&
416 !AddrSurfInfoIn
.flags
.fmask
&&
417 tex
->nr_samples
<= 1 &&
418 (flags
& RADEON_SURF_OPTIMIZE_FOR_SPACE
);
421 * - If we add MSAA support, keep in mind that CB can't decompress 8bpp
423 * - Mipmapped array textures have low performance (discovered by a closed
426 AddrSurfInfoIn
.flags
.dccCompatible
= ws
->info
.chip_class
>= VI
&&
427 !(flags
& RADEON_SURF_Z_OR_SBUFFER
) &&
428 !(flags
& RADEON_SURF_DISABLE_DCC
) &&
429 !compressed
&& AddrDccIn
.numSamples
<= 1 &&
430 ((tex
->array_size
== 1 && tex
->depth0
== 1) ||
431 tex
->last_level
== 0);
433 AddrSurfInfoIn
.flags
.noStencil
= (flags
& RADEON_SURF_SBUFFER
) == 0;
434 AddrSurfInfoIn
.flags
.compressZ
= AddrSurfInfoIn
.flags
.depth
;
436 /* noStencil = 0 can result in a depth part that is incompatible with
437 * mipmapped texturing. So set noStencil = 1 when mipmaps are requested (in
438 * this case, we may end up setting stencil_adjusted).
440 * TODO: update addrlib to a newer version, remove this, and
441 * use flags.matchStencilTileCfg = 1 as an alternative fix.
443 if (tex
->last_level
> 0)
444 AddrSurfInfoIn
.flags
.noStencil
= 1;
446 /* Set preferred macrotile parameters. This is usually required
447 * for shared resources. This is for 2D tiling only. */
448 if (AddrSurfInfoIn
.tileMode
>= ADDR_TM_2D_TILED_THIN1
&&
449 surf
->u
.legacy
.bankw
&& surf
->u
.legacy
.bankh
&&
450 surf
->u
.legacy
.mtilea
&& surf
->u
.legacy
.tile_split
) {
451 assert(!(flags
& RADEON_SURF_FMASK
));
453 /* If any of these parameters are incorrect, the calculation
455 AddrTileInfoIn
.banks
= surf
->u
.legacy
.num_banks
;
456 AddrTileInfoIn
.bankWidth
= surf
->u
.legacy
.bankw
;
457 AddrTileInfoIn
.bankHeight
= surf
->u
.legacy
.bankh
;
458 AddrTileInfoIn
.macroAspectRatio
= surf
->u
.legacy
.mtilea
;
459 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.tile_split
;
460 AddrTileInfoIn
.pipeConfig
= surf
->u
.legacy
.pipe_config
+ 1; /* +1 compared to GB_TILE_MODE */
461 AddrSurfInfoIn
.flags
.opt4Space
= 0;
462 AddrSurfInfoIn
.pTileInfo
= &AddrTileInfoIn
;
464 /* If AddrSurfInfoIn.pTileInfo is set, Addrlib doesn't set
465 * the tile index, because we are expected to know it if
466 * we know the other parameters.
468 * This is something that can easily be fixed in Addrlib.
469 * For now, just figure it out here.
470 * Note that only 2D_TILE_THIN1 is handled here.
472 assert(!(flags
& RADEON_SURF_Z_OR_SBUFFER
));
473 assert(AddrSurfInfoIn
.tileMode
== ADDR_TM_2D_TILED_THIN1
);
475 if (ws
->info
.chip_class
== SI
) {
476 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
) {
478 AddrSurfInfoIn
.tileIndex
= 11; /* 16bpp */
480 AddrSurfInfoIn
.tileIndex
= 12; /* 32bpp */
483 AddrSurfInfoIn
.tileIndex
= 14; /* 8bpp */
485 AddrSurfInfoIn
.tileIndex
= 15; /* 16bpp */
487 AddrSurfInfoIn
.tileIndex
= 16; /* 32bpp */
489 AddrSurfInfoIn
.tileIndex
= 17; /* 64bpp (and 128bpp) */
493 if (AddrSurfInfoIn
.tileType
== ADDR_DISPLAYABLE
)
494 AddrSurfInfoIn
.tileIndex
= 10; /* 2D displayable */
496 AddrSurfInfoIn
.tileIndex
= 14; /* 2D non-displayable */
498 /* Addrlib doesn't set this if tileIndex is forced like above. */
499 AddrSurfInfoOut
.macroModeIndex
= cik_get_macro_tile_index(surf
);
503 surf
->num_dcc_levels
= 0;
506 surf
->dcc_alignment
= 1;
507 surf
->htile_size
= 0;
508 surf
->htile_alignment
= 1;
510 /* Calculate texture layout information. */
511 for (level
= 0; level
<= tex
->last_level
; level
++) {
512 r
= gfx6_compute_level(ws
, tex
, surf
, false, level
, compressed
,
513 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
514 &AddrDccIn
, &AddrDccOut
, &AddrHtileIn
, &AddrHtileOut
);
519 surf
->surf_alignment
= AddrSurfInfoOut
.baseAlign
;
520 surf
->u
.legacy
.pipe_config
= AddrSurfInfoOut
.pTileInfo
->pipeConfig
- 1;
521 gfx6_set_micro_tile_mode(surf
, &ws
->info
);
523 /* For 2D modes only. */
524 if (AddrSurfInfoOut
.tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
525 surf
->u
.legacy
.bankw
= AddrSurfInfoOut
.pTileInfo
->bankWidth
;
526 surf
->u
.legacy
.bankh
= AddrSurfInfoOut
.pTileInfo
->bankHeight
;
527 surf
->u
.legacy
.mtilea
= AddrSurfInfoOut
.pTileInfo
->macroAspectRatio
;
528 surf
->u
.legacy
.tile_split
= AddrSurfInfoOut
.pTileInfo
->tileSplitBytes
;
529 surf
->u
.legacy
.num_banks
= AddrSurfInfoOut
.pTileInfo
->banks
;
530 surf
->u
.legacy
.macro_tile_index
= AddrSurfInfoOut
.macroModeIndex
;
532 surf
->u
.legacy
.macro_tile_index
= 0;
537 /* Calculate texture layout information for stencil. */
538 if (flags
& RADEON_SURF_SBUFFER
) {
539 AddrSurfInfoIn
.bpp
= 8;
540 AddrSurfInfoIn
.flags
.depth
= 0;
541 AddrSurfInfoIn
.flags
.stencil
= 1;
542 AddrSurfInfoIn
.flags
.tcCompatible
= 0;
543 /* This will be ignored if AddrSurfInfoIn.pTileInfo is NULL. */
544 AddrTileInfoIn
.tileSplitBytes
= surf
->u
.legacy
.stencil_tile_split
;
546 for (level
= 0; level
<= tex
->last_level
; level
++) {
547 r
= gfx6_compute_level(ws
, tex
, surf
, true, level
, compressed
,
548 &AddrSurfInfoIn
, &AddrSurfInfoOut
,
549 &AddrDccIn
, &AddrDccOut
,
554 /* DB uses the depth pitch for both stencil and depth. */
555 if (surf
->u
.legacy
.stencil_level
[level
].nblk_x
!= surf
->u
.legacy
.level
[level
].nblk_x
)
556 surf
->u
.legacy
.stencil_adjusted
= true;
559 /* For 2D modes only. */
560 if (AddrSurfInfoOut
.tileMode
>= ADDR_TM_2D_TILED_THIN1
) {
561 surf
->u
.legacy
.stencil_tile_split
=
562 AddrSurfInfoOut
.pTileInfo
->tileSplitBytes
;
568 /* Recalculate the whole DCC miptree size including disabled levels.
569 * This is what addrlib does, but calling addrlib would be a lot more
572 if (surf
->dcc_size
&& tex
->last_level
> 0) {
573 surf
->dcc_size
= align64(surf
->surf_size
>> 8,
574 ws
->info
.pipe_interleave_bytes
*
575 ws
->info
.num_tile_pipes
);
578 /* Make sure HTILE covers the whole miptree, because the shader reads
579 * TC-compatible HTILE even for levels where it's disabled by DB.
581 if (surf
->htile_size
&& tex
->last_level
)
582 surf
->htile_size
*= 2;
584 surf
->is_linear
= surf
->u
.legacy
.level
[0].mode
== RADEON_SURF_MODE_LINEAR_ALIGNED
;
588 /* This is only called when expecting a tiled layout. */
590 gfx9_get_preferred_swizzle_mode(struct amdgpu_winsys
*ws
,
591 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
,
592 bool is_fmask
, AddrSwizzleMode
*swizzle_mode
)
594 ADDR_E_RETURNCODE ret
;
595 ADDR2_GET_PREFERRED_SURF_SETTING_INPUT sin
= {0};
596 ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT sout
= {0};
598 sin
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_INPUT
);
599 sout
.size
= sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT
);
601 sin
.flags
= in
->flags
;
602 sin
.resourceType
= in
->resourceType
;
603 sin
.format
= in
->format
;
604 sin
.resourceLoction
= ADDR_RSRC_LOC_INVIS
;
605 /* TODO: We could allow some of these: */
606 sin
.forbiddenBlock
.micro
= 1; /* don't allow the 256B swizzle modes */
607 sin
.forbiddenBlock
.var
= 1; /* don't allow the variable-sized swizzle modes */
608 sin
.forbiddenBlock
.linear
= 1; /* don't allow linear swizzle modes */
610 sin
.width
= in
->width
;
611 sin
.height
= in
->height
;
612 sin
.numSlices
= in
->numSlices
;
613 sin
.numMipLevels
= in
->numMipLevels
;
614 sin
.numSamples
= in
->numSamples
;
615 sin
.numFrags
= in
->numFrags
;
622 ret
= Addr2GetPreferredSurfaceSetting(ws
->addrlib
, &sin
, &sout
);
626 *swizzle_mode
= sout
.swizzleMode
;
630 static int gfx9_compute_miptree(struct amdgpu_winsys
*ws
,
631 struct radeon_surf
*surf
, bool compressed
,
632 ADDR2_COMPUTE_SURFACE_INFO_INPUT
*in
)
634 ADDR2_MIP_INFO mip_info
[RADEON_SURF_MAX_LEVELS
] = {};
635 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT out
= {0};
636 ADDR_E_RETURNCODE ret
;
638 out
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT
);
639 out
.pMipInfo
= mip_info
;
641 ret
= Addr2ComputeSurfaceInfo(ws
->addrlib
, in
, &out
);
645 if (in
->flags
.stencil
) {
646 surf
->u
.gfx9
.stencil
.swizzle_mode
= in
->swizzleMode
;
647 surf
->u
.gfx9
.stencil
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
648 out
.mipChainPitch
- 1;
649 surf
->surf_alignment
= MAX2(surf
->surf_alignment
, out
.baseAlign
);
650 surf
->u
.gfx9
.stencil_offset
= align(surf
->surf_size
, out
.baseAlign
);
651 surf
->surf_size
= surf
->u
.gfx9
.stencil_offset
+ out
.surfSize
;
655 surf
->u
.gfx9
.surf
.swizzle_mode
= in
->swizzleMode
;
656 surf
->u
.gfx9
.surf
.epitch
= out
.epitchIsHeight
? out
.mipChainHeight
- 1 :
657 out
.mipChainPitch
- 1;
658 surf
->u
.gfx9
.surf_slice_size
= out
.sliceSize
;
659 surf
->u
.gfx9
.surf_pitch
= out
.pitch
;
660 surf
->u
.gfx9
.surf_height
= out
.height
;
661 surf
->surf_size
= out
.surfSize
;
662 surf
->surf_alignment
= out
.baseAlign
;
664 if (in
->swizzleMode
== ADDR_SW_LINEAR
) {
665 for (unsigned i
= 0; i
< in
->numMipLevels
; i
++)
666 surf
->u
.gfx9
.offset
[i
] = mip_info
[i
].offset
;
669 if (in
->flags
.depth
) {
670 assert(in
->swizzleMode
!= ADDR_SW_LINEAR
);
673 ADDR2_COMPUTE_HTILE_INFO_INPUT hin
= {0};
674 ADDR2_COMPUTE_HTILE_INFO_OUTPUT hout
= {0};
676 hin
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT
);
677 hout
.size
= sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT
);
679 hin
.hTileFlags
.pipeAligned
= 1;
680 hin
.hTileFlags
.rbAligned
= 1;
681 hin
.depthFlags
= in
->flags
;
682 hin
.swizzleMode
= in
->swizzleMode
;
683 hin
.unalignedWidth
= in
->width
;
684 hin
.unalignedHeight
= in
->height
;
685 hin
.numSlices
= in
->numSlices
;
686 hin
.numMipLevels
= in
->numMipLevels
;
688 ret
= Addr2ComputeHtileInfo(ws
->addrlib
, &hin
, &hout
);
692 surf
->u
.gfx9
.htile
.rb_aligned
= hin
.hTileFlags
.rbAligned
;
693 surf
->u
.gfx9
.htile
.pipe_aligned
= hin
.hTileFlags
.pipeAligned
;
694 surf
->htile_size
= hout
.htileBytes
;
695 surf
->htile_alignment
= hout
.baseAlign
;
698 if (!(surf
->flags
& RADEON_SURF_DISABLE_DCC
) &&
699 !(surf
->flags
& RADEON_SURF_SCANOUT
) &&
701 in
->swizzleMode
!= ADDR_SW_LINEAR
&&
702 /* TODO: We could support DCC with MSAA. */
703 in
->numSamples
== 1) {
704 ADDR2_COMPUTE_DCCINFO_INPUT din
= {0};
705 ADDR2_COMPUTE_DCCINFO_OUTPUT dout
= {0};
707 din
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_INPUT
);
708 dout
.size
= sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT
);
710 din
.dccKeyFlags
.pipeAligned
= 1;
711 din
.dccKeyFlags
.rbAligned
= 1;
712 din
.colorFlags
= in
->flags
;
713 din
.resourceType
= in
->resourceType
;
714 din
.swizzleMode
= in
->swizzleMode
;
716 din
.unalignedWidth
= in
->width
;
717 din
.unalignedHeight
= in
->height
;
718 din
.numSlices
= in
->numSlices
;
719 din
.numFrags
= in
->numFrags
;
720 din
.numMipLevels
= in
->numMipLevels
;
721 din
.dataSurfaceSize
= out
.surfSize
;
723 ret
= Addr2ComputeDccInfo(ws
->addrlib
, &din
, &dout
);
727 surf
->u
.gfx9
.dcc
.rb_aligned
= din
.dccKeyFlags
.rbAligned
;
728 surf
->u
.gfx9
.dcc
.pipe_aligned
= din
.dccKeyFlags
.pipeAligned
;
729 surf
->u
.gfx9
.dcc_pitch_max
= dout
.pitch
- 1;
730 surf
->dcc_size
= dout
.dccRamSize
;
731 surf
->dcc_alignment
= dout
.dccRamBaseAlign
;
735 if (in
->numSamples
> 1) {
736 ADDR2_COMPUTE_FMASK_INFO_INPUT fin
= {0};
737 ADDR2_COMPUTE_FMASK_INFO_OUTPUT fout
= {0};
739 fin
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT
);
740 fout
.size
= sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT
);
742 ret
= gfx9_get_preferred_swizzle_mode(ws
, in
, true, &fin
.swizzleMode
);
746 fin
.unalignedWidth
= in
->width
;
747 fin
.unalignedHeight
= in
->height
;
748 fin
.numSlices
= in
->numSlices
;
749 fin
.numSamples
= in
->numSamples
;
750 fin
.numFrags
= in
->numFrags
;
752 ret
= Addr2ComputeFmaskInfo(ws
->addrlib
, &fin
, &fout
);
756 surf
->u
.gfx9
.fmask
.swizzle_mode
= fin
.swizzleMode
;
757 surf
->u
.gfx9
.fmask
.epitch
= fout
.pitch
- 1;
758 surf
->u
.gfx9
.fmask_size
= fout
.fmaskBytes
;
759 surf
->u
.gfx9
.fmask_alignment
= fout
.baseAlign
;
763 if (in
->swizzleMode
!= ADDR_SW_LINEAR
) {
764 ADDR2_COMPUTE_CMASK_INFO_INPUT cin
= {0};
765 ADDR2_COMPUTE_CMASK_INFO_OUTPUT cout
= {0};
767 cin
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT
);
768 cout
.size
= sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT
);
770 cin
.cMaskFlags
.pipeAligned
= 1;
771 cin
.cMaskFlags
.rbAligned
= 1;
772 cin
.colorFlags
= in
->flags
;
773 cin
.resourceType
= in
->resourceType
;
774 cin
.unalignedWidth
= in
->width
;
775 cin
.unalignedHeight
= in
->height
;
776 cin
.numSlices
= in
->numSlices
;
778 if (in
->numSamples
> 1)
779 cin
.swizzleMode
= surf
->u
.gfx9
.fmask
.swizzle_mode
;
781 cin
.swizzleMode
= in
->swizzleMode
;
783 ret
= Addr2ComputeCmaskInfo(ws
->addrlib
, &cin
, &cout
);
787 surf
->u
.gfx9
.cmask
.rb_aligned
= cin
.cMaskFlags
.rbAligned
;
788 surf
->u
.gfx9
.cmask
.pipe_aligned
= cin
.cMaskFlags
.pipeAligned
;
789 surf
->u
.gfx9
.cmask_size
= cout
.cmaskBytes
;
790 surf
->u
.gfx9
.cmask_alignment
= cout
.baseAlign
;
797 static int gfx9_surface_init(struct radeon_winsys
*rws
,
798 const struct pipe_resource
*tex
,
799 unsigned flags
, unsigned bpe
,
800 enum radeon_surf_mode mode
,
801 struct radeon_surf
*surf
)
803 struct amdgpu_winsys
*ws
= (struct amdgpu_winsys
*)rws
;
805 ADDR2_COMPUTE_SURFACE_INFO_INPUT AddrSurfInfoIn
= {0};
808 assert(!(flags
& RADEON_SURF_FMASK
));
810 r
= amdgpu_surface_sanity(tex
);
814 AddrSurfInfoIn
.size
= sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT
);
816 surf
->blk_w
= util_format_get_blockwidth(tex
->format
);
817 surf
->blk_h
= util_format_get_blockheight(tex
->format
);
821 compressed
= surf
->blk_w
== 4 && surf
->blk_h
== 4;
823 /* The format must be set correctly for the allocation of compressed
824 * textures to work. In other cases, setting the bpp is sufficient. */
828 AddrSurfInfoIn
.format
= ADDR_FMT_BC1
;
831 AddrSurfInfoIn
.format
= ADDR_FMT_BC3
;
837 AddrSurfInfoIn
.bpp
= bpe
* 8;
840 AddrSurfInfoIn
.flags
.color
= !(flags
& RADEON_SURF_Z_OR_SBUFFER
);
841 AddrSurfInfoIn
.flags
.depth
= (flags
& RADEON_SURF_ZBUFFER
) != 0;
842 AddrSurfInfoIn
.flags
.display
= (flags
& RADEON_SURF_SCANOUT
) != 0;
843 AddrSurfInfoIn
.flags
.texture
= 1;
844 AddrSurfInfoIn
.flags
.opt4space
= 1;
846 AddrSurfInfoIn
.numMipLevels
= tex
->last_level
+ 1;
847 AddrSurfInfoIn
.numSamples
= tex
->nr_samples
? tex
->nr_samples
: 1;
848 AddrSurfInfoIn
.numFrags
= AddrSurfInfoIn
.numSamples
;
850 switch (tex
->target
) {
851 /* GFX9 doesn't support 1D depth textures, so allocate all 1D textures
852 * as 2D to avoid having shader variants for 1D vs 2D, so all shaders
853 * must sample 1D textures as 2D. */
854 case PIPE_TEXTURE_1D
:
855 case PIPE_TEXTURE_1D_ARRAY
:
856 case PIPE_TEXTURE_2D
:
857 case PIPE_TEXTURE_2D_ARRAY
:
858 case PIPE_TEXTURE_RECT
:
859 case PIPE_TEXTURE_CUBE
:
860 case PIPE_TEXTURE_CUBE_ARRAY
:
861 case PIPE_TEXTURE_3D
:
862 if (tex
->target
== PIPE_TEXTURE_3D
)
863 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_3D
;
865 AddrSurfInfoIn
.resourceType
= ADDR_RSRC_TEX_2D
;
867 AddrSurfInfoIn
.width
= tex
->width0
;
868 AddrSurfInfoIn
.height
= tex
->height0
;
870 if (tex
->target
== PIPE_TEXTURE_3D
)
871 AddrSurfInfoIn
.numSlices
= tex
->depth0
;
872 else if (tex
->target
== PIPE_TEXTURE_CUBE
)
873 AddrSurfInfoIn
.numSlices
= 6;
875 AddrSurfInfoIn
.numSlices
= tex
->array_size
;
878 case RADEON_SURF_MODE_LINEAR_ALIGNED
:
879 assert(tex
->nr_samples
<= 1);
880 assert(!(flags
& RADEON_SURF_Z_OR_SBUFFER
));
881 AddrSurfInfoIn
.swizzleMode
= ADDR_SW_LINEAR
;
884 case RADEON_SURF_MODE_1D
:
885 case RADEON_SURF_MODE_2D
:
886 r
= gfx9_get_preferred_swizzle_mode(ws
, &AddrSurfInfoIn
, false,
887 &AddrSurfInfoIn
.swizzleMode
);
901 surf
->u
.gfx9
.resource_type
= AddrSurfInfoIn
.resourceType
;
905 surf
->htile_size
= 0;
906 surf
->u
.gfx9
.surf_offset
= 0;
907 surf
->u
.gfx9
.stencil_offset
= 0;
908 surf
->u
.gfx9
.fmask_size
= 0;
909 surf
->u
.gfx9
.cmask_size
= 0;
911 /* Calculate texture layout information. */
912 r
= gfx9_compute_miptree(ws
, surf
, compressed
, &AddrSurfInfoIn
);
916 /* Calculate texture layout information for stencil. */
917 if (flags
& RADEON_SURF_SBUFFER
) {
918 AddrSurfInfoIn
.bpp
= 8;
919 AddrSurfInfoIn
.flags
.depth
= 0;
920 AddrSurfInfoIn
.flags
.stencil
= 1;
922 r
= gfx9_compute_miptree(ws
, surf
, compressed
, &AddrSurfInfoIn
);
927 surf
->is_linear
= surf
->u
.gfx9
.surf
.swizzle_mode
== ADDR_SW_LINEAR
;
928 surf
->num_dcc_levels
= surf
->dcc_size
? tex
->last_level
+ 1 : 0;
930 switch (surf
->u
.gfx9
.surf
.swizzle_mode
) {
936 case ADDR_SW_64KB_S_T
:
937 case ADDR_SW_4KB_S_X
:
938 case ADDR_SW_64KB_S_X
:
939 case ADDR_SW_VAR_S_X
:
940 surf
->micro_tile_mode
= RADEON_MICRO_MODE_THIN
;
949 case ADDR_SW_64KB_D_T
:
950 case ADDR_SW_4KB_D_X
:
951 case ADDR_SW_64KB_D_X
:
952 case ADDR_SW_VAR_D_X
:
953 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DISPLAY
;
961 case ADDR_SW_64KB_R_T
:
962 case ADDR_SW_4KB_R_X
:
963 case ADDR_SW_64KB_R_X
:
964 case ADDR_SW_VAR_R_X
:
965 surf
->micro_tile_mode
= RADEON_MICRO_MODE_ROTATED
;
972 case ADDR_SW_64KB_Z_T
:
973 case ADDR_SW_4KB_Z_X
:
974 case ADDR_SW_64KB_Z_X
:
975 case ADDR_SW_VAR_Z_X
:
976 surf
->micro_tile_mode
= RADEON_MICRO_MODE_DEPTH
;
986 void amdgpu_surface_init_functions(struct amdgpu_winsys
*ws
)
988 if (ws
->info
.chip_class
>= GFX9
)
989 ws
->base
.surface_init
= gfx9_surface_init
;
991 ws
->base
.surface_init
= gfx6_surface_init
;