Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/winsys/radeon/drm/radeon_drm_surface.c
4566 views
1
/*
2
* Copyright © 2014 Advanced Micro Devices, Inc.
3
* All Rights Reserved.
4
*
5
* Permission is hereby granted, free of charge, to any person obtaining
6
* a copy of this software and associated documentation files (the
7
* "Software"), to deal in the Software without restriction, including
8
* without limitation the rights to use, copy, modify, merge, publish,
9
* distribute, sub license, and/or sell copies of the Software, and to
10
* permit persons to whom the Software is furnished to do so, subject to
11
* the following conditions:
12
*
13
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
* NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
17
* AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20
* USE OR OTHER DEALINGS IN THE SOFTWARE.
21
*
22
* The above copyright notice and this permission notice (including the
23
* next paragraph) shall be included in all copies or substantial portions
24
* of the Software.
25
*/
26
27
#include "radeon_drm_winsys.h"
28
#include "util/format/u_format.h"
29
#include <radeon_surface.h>
30
31
static unsigned cik_get_macro_tile_index(struct radeon_surf *surf)
32
{
33
unsigned index, tileb;
34
35
tileb = 8 * 8 * surf->bpe;
36
tileb = MIN2(surf->u.legacy.tile_split, tileb);
37
38
for (index = 0; tileb > 64; index++)
39
tileb >>= 1;
40
41
assert(index < 16);
42
return index;
43
}
44
45
#define G_009910_MICRO_TILE_MODE(x) (((x) >> 0) & 0x03)
46
#define G_009910_MICRO_TILE_MODE_NEW(x) (((x) >> 22) & 0x07)
47
48
static void set_micro_tile_mode(struct radeon_surf *surf,
49
struct radeon_info *info)
50
{
51
uint32_t tile_mode;
52
53
if (info->chip_class < GFX6) {
54
surf->micro_tile_mode = 0;
55
return;
56
}
57
58
tile_mode = info->si_tile_mode_array[surf->u.legacy.tiling_index[0]];
59
60
if (info->chip_class >= GFX7)
61
surf->micro_tile_mode = G_009910_MICRO_TILE_MODE_NEW(tile_mode);
62
else
63
surf->micro_tile_mode = G_009910_MICRO_TILE_MODE(tile_mode);
64
}
65
66
static void surf_level_winsys_to_drm(struct radeon_surface_level *level_drm,
67
const struct legacy_surf_level *level_ws,
68
unsigned bpe)
69
{
70
level_drm->offset = (uint64_t)level_ws->offset_256B * 256;
71
level_drm->slice_size = (uint64_t)level_ws->slice_size_dw * 4;
72
level_drm->nblk_x = level_ws->nblk_x;
73
level_drm->nblk_y = level_ws->nblk_y;
74
level_drm->pitch_bytes = level_ws->nblk_x * bpe;
75
level_drm->mode = level_ws->mode;
76
}
77
78
static void surf_level_drm_to_winsys(struct legacy_surf_level *level_ws,
79
const struct radeon_surface_level *level_drm,
80
unsigned bpe)
81
{
82
level_ws->offset_256B = level_drm->offset / 256;
83
level_ws->slice_size_dw = level_drm->slice_size / 4;
84
level_ws->nblk_x = level_drm->nblk_x;
85
level_ws->nblk_y = level_drm->nblk_y;
86
level_ws->mode = level_drm->mode;
87
assert(level_drm->nblk_x * bpe == level_drm->pitch_bytes);
88
}
89
90
static void surf_winsys_to_drm(struct radeon_surface *surf_drm,
91
const struct pipe_resource *tex,
92
unsigned flags, unsigned bpe,
93
enum radeon_surf_mode mode,
94
const struct radeon_surf *surf_ws)
95
{
96
int i;
97
98
memset(surf_drm, 0, sizeof(*surf_drm));
99
100
surf_drm->npix_x = tex->width0;
101
surf_drm->npix_y = tex->height0;
102
surf_drm->npix_z = tex->depth0;
103
surf_drm->blk_w = util_format_get_blockwidth(tex->format);
104
surf_drm->blk_h = util_format_get_blockheight(tex->format);
105
surf_drm->blk_d = 1;
106
surf_drm->array_size = 1;
107
surf_drm->last_level = tex->last_level;
108
surf_drm->bpe = bpe;
109
surf_drm->nsamples = tex->nr_samples ? tex->nr_samples : 1;
110
111
surf_drm->flags = flags;
112
surf_drm->flags = RADEON_SURF_CLR(surf_drm->flags, TYPE);
113
surf_drm->flags = RADEON_SURF_CLR(surf_drm->flags, MODE);
114
surf_drm->flags |= RADEON_SURF_SET(mode, MODE) |
115
RADEON_SURF_HAS_SBUFFER_MIPTREE |
116
RADEON_SURF_HAS_TILE_MODE_INDEX;
117
118
switch (tex->target) {
119
case PIPE_TEXTURE_1D:
120
surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D, TYPE);
121
break;
122
case PIPE_TEXTURE_RECT:
123
case PIPE_TEXTURE_2D:
124
surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
125
break;
126
case PIPE_TEXTURE_3D:
127
surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_3D, TYPE);
128
break;
129
case PIPE_TEXTURE_1D_ARRAY:
130
surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY, TYPE);
131
surf_drm->array_size = tex->array_size;
132
break;
133
case PIPE_TEXTURE_CUBE_ARRAY: /* cube array layout like 2d array */
134
assert(tex->array_size % 6 == 0);
135
FALLTHROUGH;
136
case PIPE_TEXTURE_2D_ARRAY:
137
surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY, TYPE);
138
surf_drm->array_size = tex->array_size;
139
break;
140
case PIPE_TEXTURE_CUBE:
141
surf_drm->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP, TYPE);
142
break;
143
case PIPE_BUFFER:
144
default:
145
assert(0);
146
}
147
148
surf_drm->bo_size = surf_ws->surf_size;
149
surf_drm->bo_alignment = 1 << surf_ws->surf_alignment_log2;
150
151
surf_drm->bankw = surf_ws->u.legacy.bankw;
152
surf_drm->bankh = surf_ws->u.legacy.bankh;
153
surf_drm->mtilea = surf_ws->u.legacy.mtilea;
154
surf_drm->tile_split = surf_ws->u.legacy.tile_split;
155
156
for (i = 0; i <= surf_drm->last_level; i++) {
157
surf_level_winsys_to_drm(&surf_drm->level[i], &surf_ws->u.legacy.level[i],
158
bpe * surf_drm->nsamples);
159
160
surf_drm->tiling_index[i] = surf_ws->u.legacy.tiling_index[i];
161
}
162
163
if (flags & RADEON_SURF_SBUFFER) {
164
surf_drm->stencil_tile_split = surf_ws->u.legacy.stencil_tile_split;
165
166
for (i = 0; i <= surf_drm->last_level; i++) {
167
surf_level_winsys_to_drm(&surf_drm->stencil_level[i],
168
&surf_ws->u.legacy.zs.stencil_level[i],
169
surf_drm->nsamples);
170
surf_drm->stencil_tiling_index[i] = surf_ws->u.legacy.zs.stencil_tiling_index[i];
171
}
172
}
173
}
174
175
static void surf_drm_to_winsys(struct radeon_drm_winsys *ws,
176
struct radeon_surf *surf_ws,
177
const struct radeon_surface *surf_drm)
178
{
179
int i;
180
181
memset(surf_ws, 0, sizeof(*surf_ws));
182
183
surf_ws->blk_w = surf_drm->blk_w;
184
surf_ws->blk_h = surf_drm->blk_h;
185
surf_ws->bpe = surf_drm->bpe;
186
surf_ws->is_linear = surf_drm->level[0].mode <= RADEON_SURF_MODE_LINEAR_ALIGNED;
187
surf_ws->has_stencil = !!(surf_drm->flags & RADEON_SURF_SBUFFER);
188
surf_ws->flags = surf_drm->flags;
189
190
surf_ws->surf_size = surf_drm->bo_size;
191
surf_ws->surf_alignment_log2 = util_logbase2(surf_drm->bo_alignment);
192
193
surf_ws->u.legacy.bankw = surf_drm->bankw;
194
surf_ws->u.legacy.bankh = surf_drm->bankh;
195
surf_ws->u.legacy.mtilea = surf_drm->mtilea;
196
surf_ws->u.legacy.tile_split = surf_drm->tile_split;
197
198
surf_ws->u.legacy.macro_tile_index = cik_get_macro_tile_index(surf_ws);
199
200
for (i = 0; i <= surf_drm->last_level; i++) {
201
surf_level_drm_to_winsys(&surf_ws->u.legacy.level[i], &surf_drm->level[i],
202
surf_drm->bpe * surf_drm->nsamples);
203
surf_ws->u.legacy.tiling_index[i] = surf_drm->tiling_index[i];
204
}
205
206
if (surf_ws->flags & RADEON_SURF_SBUFFER) {
207
surf_ws->u.legacy.stencil_tile_split = surf_drm->stencil_tile_split;
208
209
for (i = 0; i <= surf_drm->last_level; i++) {
210
surf_level_drm_to_winsys(&surf_ws->u.legacy.zs.stencil_level[i],
211
&surf_drm->stencil_level[i],
212
surf_drm->nsamples);
213
surf_ws->u.legacy.zs.stencil_tiling_index[i] = surf_drm->stencil_tiling_index[i];
214
}
215
}
216
217
set_micro_tile_mode(surf_ws, &ws->info);
218
surf_ws->is_displayable = surf_ws->is_linear ||
219
surf_ws->micro_tile_mode == RADEON_MICRO_MODE_DISPLAY ||
220
surf_ws->micro_tile_mode == RADEON_MICRO_MODE_RENDER;
221
}
222
223
static void si_compute_cmask(const struct radeon_info *info,
224
const struct ac_surf_config *config,
225
struct radeon_surf *surf)
226
{
227
unsigned pipe_interleave_bytes = info->pipe_interleave_bytes;
228
unsigned num_pipes = info->num_tile_pipes;
229
unsigned cl_width, cl_height;
230
231
if (surf->flags & RADEON_SURF_Z_OR_SBUFFER)
232
return;
233
234
assert(info->chip_class <= GFX8);
235
236
switch (num_pipes) {
237
case 2:
238
cl_width = 32;
239
cl_height = 16;
240
break;
241
case 4:
242
cl_width = 32;
243
cl_height = 32;
244
break;
245
case 8:
246
cl_width = 64;
247
cl_height = 32;
248
break;
249
case 16: /* Hawaii */
250
cl_width = 64;
251
cl_height = 64;
252
break;
253
default:
254
assert(0);
255
return;
256
}
257
258
unsigned base_align = num_pipes * pipe_interleave_bytes;
259
260
unsigned width = align(surf->u.legacy.level[0].nblk_x, cl_width*8);
261
unsigned height = align(surf->u.legacy.level[0].nblk_y, cl_height*8);
262
unsigned slice_elements = (width * height) / (8*8);
263
264
/* Each element of CMASK is a nibble. */
265
unsigned slice_bytes = slice_elements / 2;
266
267
surf->u.legacy.color.cmask_slice_tile_max = (width * height) / (128*128);
268
if (surf->u.legacy.color.cmask_slice_tile_max)
269
surf->u.legacy.color.cmask_slice_tile_max -= 1;
270
271
unsigned num_layers;
272
if (config->is_3d)
273
num_layers = config->info.depth;
274
else if (config->is_cube)
275
num_layers = 6;
276
else
277
num_layers = config->info.array_size;
278
279
surf->cmask_alignment_log2 = util_logbase2(MAX2(256, base_align));
280
surf->cmask_size = align(slice_bytes, base_align) * num_layers;
281
}
282
283
static void si_compute_htile(const struct radeon_info *info,
284
struct radeon_surf *surf, unsigned num_layers)
285
{
286
unsigned cl_width, cl_height, width, height;
287
unsigned slice_elements, slice_bytes, pipe_interleave_bytes, base_align;
288
unsigned num_pipes = info->num_tile_pipes;
289
290
surf->meta_size = 0;
291
292
if (!(surf->flags & RADEON_SURF_Z_OR_SBUFFER) ||
293
surf->flags & RADEON_SURF_NO_HTILE)
294
return;
295
296
if (surf->u.legacy.level[0].mode == RADEON_SURF_MODE_1D &&
297
!info->htile_cmask_support_1d_tiling)
298
return;
299
300
/* Overalign HTILE on P2 configs to work around GPU hangs in
301
* piglit/depthstencil-render-miplevels 585.
302
*
303
* This has been confirmed to help Kabini & Stoney, where the hangs
304
* are always reproducible. I think I have seen the test hang
305
* on Carrizo too, though it was very rare there.
306
*/
307
if (info->chip_class >= GFX7 && num_pipes < 4)
308
num_pipes = 4;
309
310
switch (num_pipes) {
311
case 1:
312
cl_width = 32;
313
cl_height = 16;
314
break;
315
case 2:
316
cl_width = 32;
317
cl_height = 32;
318
break;
319
case 4:
320
cl_width = 64;
321
cl_height = 32;
322
break;
323
case 8:
324
cl_width = 64;
325
cl_height = 64;
326
break;
327
case 16:
328
cl_width = 128;
329
cl_height = 64;
330
break;
331
default:
332
assert(0);
333
return;
334
}
335
336
width = align(surf->u.legacy.level[0].nblk_x, cl_width * 8);
337
height = align(surf->u.legacy.level[0].nblk_y, cl_height * 8);
338
339
slice_elements = (width * height) / (8 * 8);
340
slice_bytes = slice_elements * 4;
341
342
pipe_interleave_bytes = info->pipe_interleave_bytes;
343
base_align = num_pipes * pipe_interleave_bytes;
344
345
surf->meta_alignment_log2 = util_logbase2(base_align);
346
surf->meta_size = num_layers * align(slice_bytes, base_align);
347
}
348
349
static int radeon_winsys_surface_init(struct radeon_winsys *rws,
350
const struct pipe_resource *tex,
351
unsigned flags, unsigned bpe,
352
enum radeon_surf_mode mode,
353
struct radeon_surf *surf_ws)
354
{
355
struct radeon_drm_winsys *ws = (struct radeon_drm_winsys*)rws;
356
struct radeon_surface surf_drm;
357
int r;
358
359
surf_winsys_to_drm(&surf_drm, tex, flags, bpe, mode, surf_ws);
360
361
if (!(flags & (RADEON_SURF_IMPORTED | RADEON_SURF_FMASK))) {
362
r = radeon_surface_best(ws->surf_man, &surf_drm);
363
if (r)
364
return r;
365
}
366
367
r = radeon_surface_init(ws->surf_man, &surf_drm);
368
if (r)
369
return r;
370
371
surf_drm_to_winsys(ws, surf_ws, &surf_drm);
372
373
/* Compute FMASK. */
374
if (ws->gen == DRV_SI &&
375
tex->nr_samples >= 2 &&
376
!(flags & (RADEON_SURF_Z_OR_SBUFFER | RADEON_SURF_FMASK | RADEON_SURF_NO_FMASK))) {
377
/* FMASK is allocated like an ordinary texture. */
378
struct pipe_resource templ = *tex;
379
struct radeon_surf fmask = {};
380
unsigned fmask_flags, bpe;
381
382
templ.nr_samples = 1;
383
fmask_flags = flags | RADEON_SURF_FMASK;
384
385
switch (tex->nr_samples) {
386
case 2:
387
case 4:
388
bpe = 1;
389
break;
390
case 8:
391
bpe = 4;
392
break;
393
default:
394
fprintf(stderr, "radeon: Invalid sample count for FMASK allocation.\n");
395
return -1;
396
}
397
398
if (radeon_winsys_surface_init(rws, &templ, fmask_flags, bpe,
399
RADEON_SURF_MODE_2D, &fmask)) {
400
fprintf(stderr, "Got error in surface_init while allocating FMASK.\n");
401
return -1;
402
}
403
404
assert(fmask.u.legacy.level[0].mode == RADEON_SURF_MODE_2D);
405
406
surf_ws->fmask_size = fmask.surf_size;
407
surf_ws->fmask_alignment_log2 = util_logbase2(MAX2(256, 1 << fmask.surf_alignment_log2));
408
surf_ws->fmask_tile_swizzle = fmask.tile_swizzle;
409
410
surf_ws->u.legacy.color.fmask.slice_tile_max =
411
(fmask.u.legacy.level[0].nblk_x * fmask.u.legacy.level[0].nblk_y) / 64;
412
if (surf_ws->u.legacy.color.fmask.slice_tile_max)
413
surf_ws->u.legacy.color.fmask.slice_tile_max -= 1;
414
415
surf_ws->u.legacy.color.fmask.tiling_index = fmask.u.legacy.tiling_index[0];
416
surf_ws->u.legacy.color.fmask.bankh = fmask.u.legacy.bankh;
417
surf_ws->u.legacy.color.fmask.pitch_in_pixels = fmask.u.legacy.level[0].nblk_x;
418
}
419
420
if (ws->gen == DRV_SI &&
421
(tex->nr_samples <= 1 || surf_ws->fmask_size)) {
422
struct ac_surf_config config;
423
424
/* Only these fields need to be set for the CMASK computation. */
425
config.info.width = tex->width0;
426
config.info.height = tex->height0;
427
config.info.depth = tex->depth0;
428
config.info.array_size = tex->array_size;
429
config.is_3d = !!(tex->target == PIPE_TEXTURE_3D);
430
config.is_cube = !!(tex->target == PIPE_TEXTURE_CUBE);
431
432
si_compute_cmask(&ws->info, &config, surf_ws);
433
}
434
435
if (ws->gen == DRV_SI) {
436
si_compute_htile(&ws->info, surf_ws, util_num_layers(tex, 0));
437
438
/* Determine the memory layout of multiple allocations in one buffer. */
439
surf_ws->total_size = surf_ws->surf_size;
440
441
if (surf_ws->meta_size) {
442
surf_ws->meta_offset = align64(surf_ws->total_size, 1 << surf_ws->meta_alignment_log2);
443
surf_ws->total_size = surf_ws->meta_offset + surf_ws->meta_size;
444
}
445
446
if (surf_ws->fmask_size) {
447
assert(tex->nr_samples >= 2);
448
surf_ws->fmask_offset = align64(surf_ws->total_size, 1 << surf_ws->fmask_alignment_log2);
449
surf_ws->total_size = surf_ws->fmask_offset + surf_ws->fmask_size;
450
}
451
452
/* Single-sample CMASK is in a separate buffer. */
453
if (surf_ws->cmask_size && tex->nr_samples >= 2) {
454
surf_ws->cmask_offset = align64(surf_ws->total_size, 1 << surf_ws->cmask_alignment_log2);
455
surf_ws->total_size = surf_ws->cmask_offset + surf_ws->cmask_size;
456
}
457
}
458
459
return 0;
460
}
461
462
void radeon_surface_init_functions(struct radeon_drm_winsys *ws)
463
{
464
ws->base.surface_init = radeon_winsys_surface_init;
465
}
466
467