1 /*
2 * Copyright © 2011 Red Hat All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
14 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
15 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
16 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
18 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
19 * USE OR OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * The above copyright notice and this permission notice (including the
22 * next paragraph) shall be included in all copies or substantial portions
23 * of the Software.
24 */
25 /*
26 * Authors:
27 * Jérôme Glisse <jglisse@redhat.com>
28 */
29
30 #include "radeon_surface.h"
31 #include "util/compiler.h"
32 #include "util/u_math.h"
33 #include <errno.h>
34 #include <xf86drm.h>
35 #include "drm-uapi/radeon_drm.h"
36
37 #define CIK_TILE_MODE_COLOR_2D 14
38 #define CIK_TILE_MODE_COLOR_2D_SCANOUT 10
39 #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64 0
40 #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128 1
41 #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256 2
42 #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512 3
43 #define CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE 4
44
45 #define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
46
47 /* keep this private */
48 enum radeon_family {
49 CHIP_UNKNOWN,
50 CHIP_R600,
51 CHIP_RV610,
52 CHIP_RV630,
53 CHIP_RV670,
54 CHIP_RV620,
55 CHIP_RV635,
56 CHIP_RS780,
57 CHIP_RS880,
58 CHIP_RV770,
59 CHIP_RV730,
60 CHIP_RV710,
61 CHIP_RV740,
62 CHIP_CEDAR,
63 CHIP_REDWOOD,
64 CHIP_JUNIPER,
65 CHIP_CYPRESS,
66 CHIP_HEMLOCK,
67 CHIP_PALM,
68 CHIP_SUMO,
69 CHIP_SUMO2,
70 CHIP_BARTS,
71 CHIP_TURKS,
72 CHIP_CAICOS,
73 CHIP_CAYMAN,
74 CHIP_ARUBA,
75 CHIP_TAHITI,
76 CHIP_PITCAIRN,
77 CHIP_VERDE,
78 CHIP_OLAND,
79 CHIP_HAINAN,
80 CHIP_BONAIRE,
81 CHIP_KAVERI,
82 CHIP_KABINI,
83 CHIP_HAWAII,
84 CHIP_MULLINS,
85 CHIP_LAST,
86 };
87
88 typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
89 struct radeon_surface *surf);
90 typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
91 struct radeon_surface *surf);
92
93 struct radeon_hw_info {
94 /* apply to r6, eg */
95 uint32_t group_bytes;
96 uint32_t num_banks;
97 uint32_t num_pipes;
98 /* apply to eg */
99 uint32_t row_size;
100 unsigned allow_2d;
101 /* apply to si */
102 uint32_t tile_mode_array[32];
103 /* apply to cik */
104 uint32_t macrotile_mode_array[16];
105 };
106
107 struct radeon_surface_manager {
108 int fd;
109 uint32_t device_id;
110 struct radeon_hw_info hw_info;
111 unsigned family;
112 hw_init_surface_t surface_init;
113 hw_best_surface_t surface_best;
114 };
115
116 /* helper */
radeon_get_value(int fd,unsigned req,uint32_t * value)117 static int radeon_get_value(int fd, unsigned req, uint32_t *value)
118 {
119 struct drm_radeon_info info = {};
120 int r;
121
122 *value = 0;
123 info.request = req;
124 info.value = (uintptr_t)value;
125 r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
126 sizeof(struct drm_radeon_info));
127 return r;
128 }
129
radeon_get_family(struct radeon_surface_manager * surf_man)130 static int radeon_get_family(struct radeon_surface_manager *surf_man)
131 {
132 switch (surf_man->device_id) {
133 #define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
134 #include "pci_ids/r600_pci_ids.h"
135 #undef CHIPSET
136 default:
137 return -EINVAL;
138 }
139 return 0;
140 }
141
next_power_of_two(unsigned x)142 static unsigned next_power_of_two(unsigned x)
143 {
144 if (x <= 1)
145 return 1;
146
147 return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
148 }
149
mip_minify(unsigned size,unsigned level)150 static unsigned mip_minify(unsigned size, unsigned level)
151 {
152 unsigned val;
153
154 val = MAX2(1, size >> level);
155 if (level > 0)
156 val = next_power_of_two(val);
157 return val;
158 }
159
surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,uint32_t xalign,uint32_t yalign,uint32_t zalign,uint64_t offset)160 static void surf_minify(struct radeon_surface *surf,
161 struct radeon_surface_level *surflevel,
162 unsigned bpe, unsigned level,
163 uint32_t xalign, uint32_t yalign, uint32_t zalign,
164 uint64_t offset)
165 {
166 surflevel->npix_x = mip_minify(surf->npix_x, level);
167 surflevel->npix_y = mip_minify(surf->npix_y, level);
168 surflevel->npix_z = mip_minify(surf->npix_z, level);
169 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
170 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
171 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
172 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
173 !(surf->flags & RADEON_SURF_FMASK)) {
174 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
175 surflevel->mode = RADEON_SURF_MODE_1D;
176 return;
177 }
178 }
179 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
180 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
181 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
182
183 surflevel->offset = offset;
184 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
185 surflevel->slice_size = (uint64_t)surflevel->pitch_bytes * surflevel->nblk_y;
186
187 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
188 }
189
190 /* ===========================================================================
191 * r600/r700 family
192 */
r6_init_hw_info(struct radeon_surface_manager * surf_man)193 static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
194 {
195 uint32_t tiling_config;
196 drmVersionPtr version;
197 int r;
198
199 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
200 &tiling_config);
201 if (r) {
202 return r;
203 }
204
205 surf_man->hw_info.allow_2d = 0;
206 version = drmGetVersion(surf_man->fd);
207 if (version && version->version_minor >= 14) {
208 surf_man->hw_info.allow_2d = 1;
209 }
210 drmFreeVersion(version);
211
212 switch ((tiling_config & 0xe) >> 1) {
213 case 0:
214 surf_man->hw_info.num_pipes = 1;
215 break;
216 case 1:
217 surf_man->hw_info.num_pipes = 2;
218 break;
219 case 2:
220 surf_man->hw_info.num_pipes = 4;
221 break;
222 case 3:
223 surf_man->hw_info.num_pipes = 8;
224 break;
225 default:
226 surf_man->hw_info.num_pipes = 8;
227 surf_man->hw_info.allow_2d = 0;
228 break;
229 }
230
231 switch ((tiling_config & 0x30) >> 4) {
232 case 0:
233 surf_man->hw_info.num_banks = 4;
234 break;
235 case 1:
236 surf_man->hw_info.num_banks = 8;
237 break;
238 default:
239 surf_man->hw_info.num_banks = 8;
240 surf_man->hw_info.allow_2d = 0;
241 break;
242 }
243
244 switch ((tiling_config & 0xc0) >> 6) {
245 case 0:
246 surf_man->hw_info.group_bytes = 256;
247 break;
248 case 1:
249 surf_man->hw_info.group_bytes = 512;
250 break;
251 default:
252 surf_man->hw_info.group_bytes = 256;
253 surf_man->hw_info.allow_2d = 0;
254 break;
255 }
256 return 0;
257 }
258
r6_surface_init_linear(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)259 static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
260 struct radeon_surface *surf,
261 uint64_t offset, unsigned start_level)
262 {
263 uint32_t xalign, yalign, zalign;
264 unsigned i;
265
266 /* compute alignment */
267 if (!start_level) {
268 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
269 }
270 /* the 32 alignment is for scanout, cb or db but to allow texture to be
271 * easily bound as such we force this alignment to all surface
272 */
273 xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
274 yalign = 1;
275 zalign = 1;
276 if (surf->flags & RADEON_SURF_SCANOUT) {
277 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
278 }
279
280 /* build mipmap tree */
281 for (i = start_level; i <= surf->last_level; i++) {
282 surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
283 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
284 /* level0 and first mipmap need to have alignment */
285 offset = surf->bo_size;
286 if (i == 0) {
287 offset = ALIGN(offset, surf->bo_alignment);
288 }
289 }
290 return 0;
291 }
292
r6_surface_init_linear_aligned(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)293 static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
294 struct radeon_surface *surf,
295 uint64_t offset, unsigned start_level)
296 {
297 uint32_t xalign, yalign, zalign;
298 unsigned i;
299
300 /* compute alignment */
301 if (!start_level) {
302 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
303 }
304 xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
305 yalign = 1;
306 zalign = 1;
307
308 /* build mipmap tree */
309 for (i = start_level; i <= surf->last_level; i++) {
310 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
311 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
312 /* level0 and first mipmap need to have alignment */
313 offset = surf->bo_size;
314 if (i == 0) {
315 offset = ALIGN(offset, surf->bo_alignment);
316 }
317 }
318 return 0;
319 }
320
r6_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)321 static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
322 struct radeon_surface *surf,
323 uint64_t offset, unsigned start_level)
324 {
325 uint32_t xalign, yalign, zalign, tilew;
326 unsigned i;
327
328 /* compute alignment */
329 tilew = 8;
330 xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
331 xalign = MAX2(tilew, xalign);
332 yalign = tilew;
333 zalign = 1;
334 if (surf->flags & RADEON_SURF_SCANOUT) {
335 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
336 }
337 if (!start_level) {
338 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
339 }
340
341 /* build mipmap tree */
342 for (i = start_level; i <= surf->last_level; i++) {
343 surf->level[i].mode = RADEON_SURF_MODE_1D;
344 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
345 /* level0 and first mipmap need to have alignment */
346 offset = surf->bo_size;
347 if (i == 0) {
348 offset = ALIGN(offset, surf->bo_alignment);
349 }
350 }
351 return 0;
352 }
353
r6_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,uint64_t offset,unsigned start_level)354 static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
355 struct radeon_surface *surf,
356 uint64_t offset, unsigned start_level)
357 {
358 uint32_t xalign, yalign, zalign, tilew;
359 unsigned i;
360
361 /* compute alignment */
362 tilew = 8;
363 zalign = 1;
364 xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
365 (tilew * surf->bpe * surf->nsamples);
366 xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
367 if (surf->flags & RADEON_SURF_FMASK)
368 xalign = MAX2(128, xalign);
369 yalign = tilew * surf_man->hw_info.num_pipes;
370 if (surf->flags & RADEON_SURF_SCANOUT) {
371 xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
372 }
373 if (!start_level) {
374 surf->bo_alignment =
375 MAX2(surf_man->hw_info.num_pipes *
376 surf_man->hw_info.num_banks *
377 surf->nsamples * surf->bpe * 64,
378 xalign * yalign * surf->nsamples * surf->bpe);
379 }
380
381 /* build mipmap tree */
382 for (i = start_level; i <= surf->last_level; i++) {
383 surf->level[i].mode = RADEON_SURF_MODE_2D;
384 surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
385 if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
386 return r6_surface_init_1d(surf_man, surf, offset, i);
387 }
388 /* level0 and first mipmap need to have alignment */
389 offset = surf->bo_size;
390 if (i == 0) {
391 offset = ALIGN(offset, surf->bo_alignment);
392 }
393 }
394 return 0;
395 }
396
r6_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)397 static int r6_surface_init(struct radeon_surface_manager *surf_man,
398 struct radeon_surface *surf)
399 {
400 unsigned mode;
401 int r;
402
403 /* MSAA surfaces support the 2D mode only. */
404 if (surf->nsamples > 1) {
405 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
406 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
407 }
408
409 /* tiling mode */
410 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
411
412 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
413 /* zbuffer only support 1D or 2D tiled surface */
414 switch (mode) {
415 case RADEON_SURF_MODE_1D:
416 case RADEON_SURF_MODE_2D:
417 break;
418 default:
419 mode = RADEON_SURF_MODE_1D;
420 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
421 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
422 break;
423 }
424 }
425
426 /* force 1d on kernel that can't do 2d */
427 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
428 if (surf->nsamples > 1) {
429 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
430 return -EFAULT;
431 }
432 mode = RADEON_SURF_MODE_1D;
433 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
434 surf->flags |= RADEON_SURF_SET(mode, MODE);
435 }
436
437 /* check surface dimension */
438 if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
439 return -EINVAL;
440 }
441
442 /* check mipmap last_level */
443 if (surf->last_level > 14) {
444 return -EINVAL;
445 }
446
447 /* check tiling mode */
448 switch (mode) {
449 case RADEON_SURF_MODE_LINEAR:
450 r = r6_surface_init_linear(surf_man, surf, 0, 0);
451 break;
452 case RADEON_SURF_MODE_LINEAR_ALIGNED:
453 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
454 break;
455 case RADEON_SURF_MODE_1D:
456 r = r6_surface_init_1d(surf_man, surf, 0, 0);
457 break;
458 case RADEON_SURF_MODE_2D:
459 r = r6_surface_init_2d(surf_man, surf, 0, 0);
460 break;
461 default:
462 return -EINVAL;
463 }
464 return r;
465 }
466
r6_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)467 static int r6_surface_best(struct radeon_surface_manager *surf_man,
468 struct radeon_surface *surf)
469 {
470 /* no value to optimize for r6xx/r7xx */
471 return 0;
472 }
473
474
475 /* ===========================================================================
476 * evergreen family
477 */
eg_init_hw_info(struct radeon_surface_manager * surf_man)478 static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
479 {
480 uint32_t tiling_config;
481 drmVersionPtr version;
482 int r;
483
484 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
485 &tiling_config);
486 if (r) {
487 return r;
488 }
489
490 surf_man->hw_info.allow_2d = 0;
491 version = drmGetVersion(surf_man->fd);
492 if (version && version->version_minor >= 16) {
493 surf_man->hw_info.allow_2d = 1;
494 }
495 drmFreeVersion(version);
496
497 switch (tiling_config & 0xf) {
498 case 0:
499 surf_man->hw_info.num_pipes = 1;
500 break;
501 case 1:
502 surf_man->hw_info.num_pipes = 2;
503 break;
504 case 2:
505 surf_man->hw_info.num_pipes = 4;
506 break;
507 case 3:
508 surf_man->hw_info.num_pipes = 8;
509 break;
510 default:
511 surf_man->hw_info.num_pipes = 8;
512 surf_man->hw_info.allow_2d = 0;
513 break;
514 }
515
516 switch ((tiling_config & 0xf0) >> 4) {
517 case 0:
518 surf_man->hw_info.num_banks = 4;
519 break;
520 case 1:
521 surf_man->hw_info.num_banks = 8;
522 break;
523 case 2:
524 surf_man->hw_info.num_banks = 16;
525 break;
526 default:
527 surf_man->hw_info.num_banks = 8;
528 surf_man->hw_info.allow_2d = 0;
529 break;
530 }
531
532 switch ((tiling_config & 0xf00) >> 8) {
533 case 0:
534 surf_man->hw_info.group_bytes = 256;
535 break;
536 case 1:
537 surf_man->hw_info.group_bytes = 512;
538 break;
539 default:
540 surf_man->hw_info.group_bytes = 256;
541 surf_man->hw_info.allow_2d = 0;
542 break;
543 }
544
545 switch ((tiling_config & 0xf000) >> 12) {
546 case 0:
547 surf_man->hw_info.row_size = 1024;
548 break;
549 case 1:
550 surf_man->hw_info.row_size = 2048;
551 break;
552 case 2:
553 surf_man->hw_info.row_size = 4096;
554 break;
555 default:
556 surf_man->hw_info.row_size = 4096;
557 surf_man->hw_info.allow_2d = 0;
558 break;
559 }
560 return 0;
561 }
562
eg_surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,unsigned slice_pt,unsigned mtilew,unsigned mtileh,unsigned mtileb,uint64_t offset)563 static void eg_surf_minify(struct radeon_surface *surf,
564 struct radeon_surface_level *surflevel,
565 unsigned bpe,
566 unsigned level,
567 unsigned slice_pt,
568 unsigned mtilew,
569 unsigned mtileh,
570 unsigned mtileb,
571 uint64_t offset)
572 {
573 unsigned mtile_pr, mtile_ps;
574
575 surflevel->npix_x = mip_minify(surf->npix_x, level);
576 surflevel->npix_y = mip_minify(surf->npix_y, level);
577 surflevel->npix_z = mip_minify(surf->npix_z, level);
578 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
579 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
580 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
581 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
582 !(surf->flags & RADEON_SURF_FMASK)) {
583 if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
584 surflevel->mode = RADEON_SURF_MODE_1D;
585 return;
586 }
587 }
588 surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
589 surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
590 surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
591
592 /* macro tile per row */
593 mtile_pr = surflevel->nblk_x / mtilew;
594 /* macro tile per slice */
595 mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
596
597 surflevel->offset = offset;
598 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
599 surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
600
601 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
602 }
603
eg_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned align_maginify,uint64_t offset,unsigned start_level)604 static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
605 struct radeon_surface *surf,
606 struct radeon_surface_level *level,
607 unsigned bpe,
608 unsigned align_maginify,
609 uint64_t offset, unsigned start_level)
610 {
611 uint32_t xalign, yalign, zalign, tilew;
612 unsigned i;
613
614 /* compute alignment */
615 tilew = 8;
616 xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
617 xalign = MAX2(tilew, xalign * align_maginify);
618 yalign = tilew;
619 zalign = 1;
620 if (surf->flags & RADEON_SURF_SCANOUT) {
621 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
622 }
623
624 if (!start_level) {
625 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
626 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
627
628 if (offset) {
629 offset = ALIGN(offset, alignment);
630 }
631 }
632
633 /* build mipmap tree */
634 for (i = start_level; i <= surf->last_level; i++) {
635 level[i].mode = RADEON_SURF_MODE_1D;
636 surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
637 /* level0 and first mipmap need to have alignment */
638 offset = surf->bo_size;
639 if (i == 0) {
640 offset = ALIGN(offset, surf->bo_alignment);
641 }
642 }
643 return 0;
644 }
645
eg_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned align_magnify,unsigned tile_split,uint64_t offset,unsigned start_level)646 static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
647 struct radeon_surface *surf,
648 struct radeon_surface_level *level,
649 unsigned bpe, unsigned align_magnify,
650 unsigned tile_split,
651 uint64_t offset, unsigned start_level)
652 {
653 unsigned tilew, tileh, tileb;
654 unsigned mtilew, mtileh, mtileb;
655 unsigned slice_pt;
656 unsigned i;
657
658 /* compute tile values */
659 tilew = 8;
660 tileh = 8;
661 tileb = tilew * tileh * bpe * surf->nsamples;
662 /* slices per tile */
663 slice_pt = 1;
664 if (tileb > tile_split && tile_split) {
665 slice_pt = tileb / tile_split;
666 }
667 tileb = tileb / slice_pt;
668
669 /* macro tile width & height */
670 mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
671 mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
672 /* macro tile bytes */
673 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
674
675 if (!start_level) {
676 unsigned alignment = MAX2(256, mtileb);
677 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
678
679 if (offset) {
680 offset = ALIGN(offset, alignment);
681 }
682 }
683
684 /* build mipmap tree */
685 for (i = start_level; i <= surf->last_level; i++) {
686 level[i].mode = RADEON_SURF_MODE_2D;
687 eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
688 if (level[i].mode == RADEON_SURF_MODE_1D) {
689 return eg_surface_init_1d(surf_man, surf, level, bpe, align_magnify, offset, i);
690 }
691 /* level0 and first mipmap need to have alignment */
692 offset = surf->bo_size;
693 if (i == 0) {
694 offset = ALIGN(offset, surf->bo_alignment);
695 }
696 }
697 return 0;
698 }
699
eg_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode)700 static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
701 struct radeon_surface *surf,
702 unsigned mode)
703 {
704 unsigned tileb;
705
706 /* check surface dimension */
707 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
708 return -EINVAL;
709 }
710
711 /* check mipmap last_level */
712 if (surf->last_level > 15) {
713 return -EINVAL;
714 }
715
716 /* force 1d on kernel that can't do 2d */
717 if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
718 if (surf->nsamples > 1) {
719 fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
720 return -EFAULT;
721 }
722 mode = RADEON_SURF_MODE_1D;
723 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
724 surf->flags |= RADEON_SURF_SET(mode, MODE);
725 }
726
727 /* check tile split */
728 if (mode == RADEON_SURF_MODE_2D) {
729 switch (surf->tile_split) {
730 case 64:
731 case 128:
732 case 256:
733 case 512:
734 case 1024:
735 case 2048:
736 case 4096:
737 break;
738 default:
739 return -EINVAL;
740 }
741 switch (surf->mtilea) {
742 case 1:
743 case 2:
744 case 4:
745 case 8:
746 break;
747 default:
748 return -EINVAL;
749 }
750 /* check aspect ratio */
751 if (surf_man->hw_info.num_banks < surf->mtilea) {
752 return -EINVAL;
753 }
754 /* check bank width */
755 switch (surf->bankw) {
756 case 1:
757 case 2:
758 case 4:
759 case 8:
760 break;
761 default:
762 return -EINVAL;
763 }
764 /* check bank height */
765 switch (surf->bankh) {
766 case 1:
767 case 2:
768 case 4:
769 case 8:
770 break;
771 default:
772 return -EINVAL;
773 }
774 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
775 if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
776 return -EINVAL;
777 }
778 }
779
780 return 0;
781 }
782
eg_surface_init_1d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)783 static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
784 struct radeon_surface *surf)
785 {
786 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
787 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
788 /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
789 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
790 struct radeon_surface_level *stencil_level =
791 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
792
793 /* With certain sizes the depth and the stencil texture end up being of
794 * different block sizes which later results in wrong rendering for npot
795 * textures. Inflate the alignment requirement for the depth surface by
796 * its bpe in order to make it allocate a texture that is of the same
797 * block size like the stencil texture (The rules used here are deducted by
798 * running dEQP tests and piglits) */
799 int magnify_align = is_depth_stencil &&
800 ((surf->npix_x < 32) ||
801 (!util_is_power_of_two_or_zero(surf->npix_x) &&
802 !surf->last_level));
803
804 r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe,
805 magnify_align ? surf->bpe : 1, 0, 0);
806 if (r)
807 return r;
808
809 if (is_depth_stencil) {
810 r = eg_surface_init_1d(surf_man, surf, stencil_level, 1, 1,
811 surf->bo_size, 0);
812 surf->stencil_offset = stencil_level[0].offset;
813 }
814 return r;
815 }
816
eg_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)817 static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
818 struct radeon_surface *surf)
819 {
820 unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
821 int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
822 /* Old libdrm_macros.headers didn't have stencil_level in it. This prevents crashes. */
823 struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
824 struct radeon_surface_level *stencil_level =
825 (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
826
827 /* Inflate the alignment requirement for npot textures to insure that
828 * stencil and depth texture have the same block size. Use this only in
829 * the 1d code path that uses the non-specific minify. */
830 int magnify_align = is_depth_stencil &&
831 ((surf->npix_x < 32) ||
832 (!util_is_power_of_two_or_zero(surf->npix_x) &&
833 !surf->last_level));
834
835 r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
836 magnify_align ? surf->bpe : 1,
837 surf->tile_split, 0, 0);
838 if (r)
839 return r;
840
841 if (is_depth_stencil) {
842 r = eg_surface_init_2d(surf_man, surf, stencil_level, 1, 1,
843 surf->stencil_tile_split, surf->bo_size, 0);
844 surf->stencil_offset = stencil_level[0].offset;
845
846 }
847 return r;
848 }
849
eg_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)850 static int eg_surface_init(struct radeon_surface_manager *surf_man,
851 struct radeon_surface *surf)
852 {
853 unsigned mode;
854 int r;
855
856 /* MSAA surfaces support the 2D mode only. */
857 if (surf->nsamples > 1) {
858 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
859 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
860 }
861
862 /* tiling mode */
863 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
864
865 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
866 /* zbuffer only support 1D or 2D tiled surface */
867 switch (mode) {
868 case RADEON_SURF_MODE_1D:
869 case RADEON_SURF_MODE_2D:
870 break;
871 default:
872 mode = RADEON_SURF_MODE_1D;
873 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
874 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
875 break;
876 }
877 }
878
879 r = eg_surface_sanity(surf_man, surf, mode);
880 if (r) {
881 return r;
882 }
883
884 surf->stencil_offset = 0;
885 surf->bo_alignment = 0;
886
887 /* check tiling mode */
888 switch (mode) {
889 case RADEON_SURF_MODE_LINEAR:
890 r = r6_surface_init_linear(surf_man, surf, 0, 0);
891 break;
892 case RADEON_SURF_MODE_LINEAR_ALIGNED:
893 r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
894 break;
895 case RADEON_SURF_MODE_1D:
896 r = eg_surface_init_1d_miptrees(surf_man, surf);
897 break;
898 case RADEON_SURF_MODE_2D:
899 r = eg_surface_init_2d_miptrees(surf_man, surf);
900 break;
901 default:
902 return -EINVAL;
903 }
904 return r;
905 }
906
log2_int(unsigned x)907 static unsigned log2_int(unsigned x)
908 {
909 unsigned l;
910
911 if (x < 2) {
912 return 0;
913 }
914 for (l = 2; ; l++) {
915 if ((unsigned)(1 << l) > x) {
916 return l - 1;
917 }
918 }
919 return 0;
920 }
921
922 /* compute best tile_split, bankw, bankh, mtilea
923 * depending on surface
924 */
eg_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)925 static int eg_surface_best(struct radeon_surface_manager *surf_man,
926 struct radeon_surface *surf)
927 {
928 unsigned mode, tileb, h_over_w;
929 int r;
930
931 /* tiling mode */
932 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
933
934 /* set some default value to avoid sanity check choking on them */
935 surf->tile_split = 1024;
936 surf->bankw = 1;
937 surf->bankh = 1;
938 surf->mtilea = surf_man->hw_info.num_banks;
939 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
940 for (; surf->bankh <= 8; surf->bankh *= 2) {
941 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
942 break;
943 }
944 }
945 if (surf->mtilea > 8) {
946 surf->mtilea = 8;
947 }
948
949 r = eg_surface_sanity(surf_man, surf, mode);
950 if (r) {
951 return r;
952 }
953
954 if (mode != RADEON_SURF_MODE_2D) {
955 /* nothing to do for non 2D tiled surface */
956 return 0;
957 }
958
959 /* Tweak TILE_SPLIT for performance here. */
960 if (surf->nsamples > 1) {
961 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
962 switch (surf->nsamples) {
963 case 2:
964 surf->tile_split = 128;
965 break;
966 case 4:
967 surf->tile_split = 128;
968 break;
969 case 8:
970 surf->tile_split = 256;
971 break;
972 case 16: /* cayman only */
973 surf->tile_split = 512;
974 break;
975 default:
976 fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
977 surf->nsamples, __LINE__);
978 return -EINVAL;
979 }
980 surf->stencil_tile_split = 64;
981 } else {
982 /* tile split must be >= 256 for colorbuffer surfaces,
983 * SAMPLE_SPLIT = tile_split / (bpe * 64), the optimal value is 2
984 */
985 surf->tile_split = MAX2(2 * surf->bpe * 64, 256);
986 if (surf->tile_split > 4096)
987 surf->tile_split = 4096;
988 }
989 } else {
990 /* set tile split to row size */
991 surf->tile_split = surf_man->hw_info.row_size;
992 surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
993 }
994
995 /* bankw or bankh greater than 1 increase alignment requirement, not
996 * sure if it's worth using smaller bankw & bankh to stick with 2D
997 * tiling on small surface rather than falling back to 1D tiling.
998 * Use recommended value based on tile size for now.
999 *
1000 * fmask buffer has different optimal value figure them out once we
1001 * use it.
1002 */
1003 if (surf->flags & RADEON_SURF_SBUFFER) {
1004 /* assume 1 bytes for stencil, we optimize for stencil as stencil
1005 * and depth shares surface values
1006 */
1007 tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
1008 } else {
1009 tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
1010 }
1011
1012 /* use bankw of 1 to minimize width alignment, might be interesting to
1013 * increase it for large surface
1014 */
1015 surf->bankw = 1;
1016 switch (tileb) {
1017 case 64:
1018 surf->bankh = 4;
1019 break;
1020 case 128:
1021 case 256:
1022 surf->bankh = 2;
1023 break;
1024 default:
1025 surf->bankh = 1;
1026 break;
1027 }
1028 /* double check the constraint */
1029 for (; surf->bankh <= 8; surf->bankh *= 2) {
1030 if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
1031 break;
1032 }
1033 }
1034
1035 h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
1036 (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
1037 surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
1038
1039 return 0;
1040 }
1041
1042
1043 /* ===========================================================================
1044 * Southern Islands family
1045 */
1046 #define SI__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1047 #define SI__PIPE_CONFIG__ADDR_SURF_P2 0
1048 #define SI__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1049 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1050 #define SI__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1051 #define SI__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1052 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1053 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1054 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1055 #define SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1056 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1057 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1058 #define SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1059 #define SI__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1060 #define SI__TILE_SPLIT__64B 0
1061 #define SI__TILE_SPLIT__128B 1
1062 #define SI__TILE_SPLIT__256B 2
1063 #define SI__TILE_SPLIT__512B 3
1064 #define SI__TILE_SPLIT__1024B 4
1065 #define SI__TILE_SPLIT__2048B 5
1066 #define SI__TILE_SPLIT__4096B 6
1067 #define SI__GB_TILE_MODE__BANK_WIDTH(x) (((x) >> 14) & 0x3)
1068 #define SI__BANK_WIDTH__1 0
1069 #define SI__BANK_WIDTH__2 1
1070 #define SI__BANK_WIDTH__4 2
1071 #define SI__BANK_WIDTH__8 3
1072 #define SI__GB_TILE_MODE__BANK_HEIGHT(x) (((x) >> 16) & 0x3)
1073 #define SI__BANK_HEIGHT__1 0
1074 #define SI__BANK_HEIGHT__2 1
1075 #define SI__BANK_HEIGHT__4 2
1076 #define SI__BANK_HEIGHT__8 3
1077 #define SI__GB_TILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 18) & 0x3)
1078 #define SI__MACRO_TILE_ASPECT__1 0
1079 #define SI__MACRO_TILE_ASPECT__2 1
1080 #define SI__MACRO_TILE_ASPECT__4 2
1081 #define SI__MACRO_TILE_ASPECT__8 3
1082 #define SI__GB_TILE_MODE__NUM_BANKS(x) (((x) >> 20) & 0x3)
1083 #define SI__NUM_BANKS__2_BANK 0
1084 #define SI__NUM_BANKS__4_BANK 1
1085 #define SI__NUM_BANKS__8_BANK 2
1086 #define SI__NUM_BANKS__16_BANK 3
1087
1088
si_gb_tile_mode(uint32_t gb_tile_mode,unsigned * num_pipes,unsigned * num_banks,uint32_t * macro_tile_aspect,uint32_t * bank_w,uint32_t * bank_h,uint32_t * tile_split)1089 static void si_gb_tile_mode(uint32_t gb_tile_mode,
1090 unsigned *num_pipes,
1091 unsigned *num_banks,
1092 uint32_t *macro_tile_aspect,
1093 uint32_t *bank_w,
1094 uint32_t *bank_h,
1095 uint32_t *tile_split)
1096 {
1097 if (num_pipes) {
1098 switch (SI__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1099 case SI__PIPE_CONFIG__ADDR_SURF_P2:
1100 default:
1101 *num_pipes = 2;
1102 break;
1103 case SI__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1104 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1105 case SI__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1106 case SI__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1107 *num_pipes = 4;
1108 break;
1109 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1110 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1111 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1112 case SI__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1113 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1114 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1115 case SI__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1116 *num_pipes = 8;
1117 break;
1118 }
1119 }
1120 if (num_banks) {
1121 switch (SI__GB_TILE_MODE__NUM_BANKS(gb_tile_mode)) {
1122 default:
1123 case SI__NUM_BANKS__2_BANK:
1124 *num_banks = 2;
1125 break;
1126 case SI__NUM_BANKS__4_BANK:
1127 *num_banks = 4;
1128 break;
1129 case SI__NUM_BANKS__8_BANK:
1130 *num_banks = 8;
1131 break;
1132 case SI__NUM_BANKS__16_BANK:
1133 *num_banks = 16;
1134 break;
1135 }
1136 }
1137 if (macro_tile_aspect) {
1138 switch (SI__GB_TILE_MODE__MACRO_TILE_ASPECT(gb_tile_mode)) {
1139 default:
1140 case SI__MACRO_TILE_ASPECT__1:
1141 *macro_tile_aspect = 1;
1142 break;
1143 case SI__MACRO_TILE_ASPECT__2:
1144 *macro_tile_aspect = 2;
1145 break;
1146 case SI__MACRO_TILE_ASPECT__4:
1147 *macro_tile_aspect = 4;
1148 break;
1149 case SI__MACRO_TILE_ASPECT__8:
1150 *macro_tile_aspect = 8;
1151 break;
1152 }
1153 }
1154 if (bank_w) {
1155 switch (SI__GB_TILE_MODE__BANK_WIDTH(gb_tile_mode)) {
1156 default:
1157 case SI__BANK_WIDTH__1:
1158 *bank_w = 1;
1159 break;
1160 case SI__BANK_WIDTH__2:
1161 *bank_w = 2;
1162 break;
1163 case SI__BANK_WIDTH__4:
1164 *bank_w = 4;
1165 break;
1166 case SI__BANK_WIDTH__8:
1167 *bank_w = 8;
1168 break;
1169 }
1170 }
1171 if (bank_h) {
1172 switch (SI__GB_TILE_MODE__BANK_HEIGHT(gb_tile_mode)) {
1173 default:
1174 case SI__BANK_HEIGHT__1:
1175 *bank_h = 1;
1176 break;
1177 case SI__BANK_HEIGHT__2:
1178 *bank_h = 2;
1179 break;
1180 case SI__BANK_HEIGHT__4:
1181 *bank_h = 4;
1182 break;
1183 case SI__BANK_HEIGHT__8:
1184 *bank_h = 8;
1185 break;
1186 }
1187 }
1188 if (tile_split) {
1189 switch (SI__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1190 default:
1191 case SI__TILE_SPLIT__64B:
1192 *tile_split = 64;
1193 break;
1194 case SI__TILE_SPLIT__128B:
1195 *tile_split = 128;
1196 break;
1197 case SI__TILE_SPLIT__256B:
1198 *tile_split = 256;
1199 break;
1200 case SI__TILE_SPLIT__512B:
1201 *tile_split = 512;
1202 break;
1203 case SI__TILE_SPLIT__1024B:
1204 *tile_split = 1024;
1205 break;
1206 case SI__TILE_SPLIT__2048B:
1207 *tile_split = 2048;
1208 break;
1209 case SI__TILE_SPLIT__4096B:
1210 *tile_split = 4096;
1211 break;
1212 }
1213 }
1214 }
1215
si_init_hw_info(struct radeon_surface_manager * surf_man)1216 static int si_init_hw_info(struct radeon_surface_manager *surf_man)
1217 {
1218 uint32_t tiling_config;
1219 drmVersionPtr version;
1220 int r;
1221
1222 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
1223 &tiling_config);
1224 if (r) {
1225 return r;
1226 }
1227
1228 surf_man->hw_info.allow_2d = 0;
1229 version = drmGetVersion(surf_man->fd);
1230 if (version && version->version_minor >= 33) {
1231 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array)) {
1232 surf_man->hw_info.allow_2d = 1;
1233 }
1234 }
1235 drmFreeVersion(version);
1236
1237 switch (tiling_config & 0xf) {
1238 case 0:
1239 surf_man->hw_info.num_pipes = 1;
1240 break;
1241 case 1:
1242 surf_man->hw_info.num_pipes = 2;
1243 break;
1244 case 2:
1245 surf_man->hw_info.num_pipes = 4;
1246 break;
1247 case 3:
1248 surf_man->hw_info.num_pipes = 8;
1249 break;
1250 default:
1251 surf_man->hw_info.num_pipes = 8;
1252 surf_man->hw_info.allow_2d = 0;
1253 break;
1254 }
1255
1256 switch ((tiling_config & 0xf0) >> 4) {
1257 case 0:
1258 surf_man->hw_info.num_banks = 4;
1259 break;
1260 case 1:
1261 surf_man->hw_info.num_banks = 8;
1262 break;
1263 case 2:
1264 surf_man->hw_info.num_banks = 16;
1265 break;
1266 default:
1267 surf_man->hw_info.num_banks = 8;
1268 surf_man->hw_info.allow_2d = 0;
1269 break;
1270 }
1271
1272 switch ((tiling_config & 0xf00) >> 8) {
1273 case 0:
1274 surf_man->hw_info.group_bytes = 256;
1275 break;
1276 case 1:
1277 surf_man->hw_info.group_bytes = 512;
1278 break;
1279 default:
1280 surf_man->hw_info.group_bytes = 256;
1281 surf_man->hw_info.allow_2d = 0;
1282 break;
1283 }
1284
1285 switch ((tiling_config & 0xf000) >> 12) {
1286 case 0:
1287 surf_man->hw_info.row_size = 1024;
1288 break;
1289 case 1:
1290 surf_man->hw_info.row_size = 2048;
1291 break;
1292 case 2:
1293 surf_man->hw_info.row_size = 4096;
1294 break;
1295 default:
1296 surf_man->hw_info.row_size = 4096;
1297 surf_man->hw_info.allow_2d = 0;
1298 break;
1299 }
1300 return 0;
1301 }
1302
si_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode,unsigned * tile_mode,unsigned * stencil_tile_mode)1303 static int si_surface_sanity(struct radeon_surface_manager *surf_man,
1304 struct radeon_surface *surf,
1305 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
1306 {
1307 uint32_t gb_tile_mode;
1308
1309 /* check surface dimension */
1310 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
1311 return -EINVAL;
1312 }
1313
1314 /* check mipmap last_level */
1315 if (surf->last_level > 15) {
1316 return -EINVAL;
1317 }
1318
1319 /* force 1d on kernel that can't do 2d */
1320 if (mode > RADEON_SURF_MODE_1D &&
1321 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
1322 if (surf->nsamples > 1) {
1323 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
1324 return -EFAULT;
1325 }
1326 mode = RADEON_SURF_MODE_1D;
1327 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1328 surf->flags |= RADEON_SURF_SET(mode, MODE);
1329 }
1330
1331 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
1332 return -EINVAL;
1333 }
1334
1335 if (!surf->tile_split) {
1336 /* default value */
1337 surf->mtilea = 1;
1338 surf->bankw = 1;
1339 surf->bankh = 1;
1340 surf->tile_split = 64;
1341 surf->stencil_tile_split = 64;
1342 }
1343
1344 switch (mode) {
1345 case RADEON_SURF_MODE_2D:
1346 if (surf->flags & RADEON_SURF_SBUFFER) {
1347 switch (surf->nsamples) {
1348 case 1:
1349 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1350 break;
1351 case 2:
1352 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1353 break;
1354 case 4:
1355 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1356 break;
1357 case 8:
1358 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1359 break;
1360 default:
1361 return -EINVAL;
1362 }
1363 /* retrieve tiling mode value */
1364 gb_tile_mode = surf_man->hw_info.tile_mode_array[*stencil_tile_mode];
1365 si_gb_tile_mode(gb_tile_mode, NULL, NULL, NULL, NULL, NULL, &surf->stencil_tile_split);
1366 }
1367 if (surf->flags & RADEON_SURF_ZBUFFER) {
1368 switch (surf->nsamples) {
1369 case 1:
1370 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D;
1371 break;
1372 case 2:
1373 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_2AA;
1374 break;
1375 case 4:
1376 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_4AA;
1377 break;
1378 case 8:
1379 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_2D_8AA;
1380 break;
1381 default:
1382 return -EINVAL;
1383 }
1384 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1385 switch (surf->bpe) {
1386 case 2:
1387 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP;
1388 break;
1389 case 4:
1390 *tile_mode = SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP;
1391 break;
1392 default:
1393 return -EINVAL;
1394 }
1395 } else {
1396 switch (surf->bpe) {
1397 case 1:
1398 *tile_mode = SI_TILE_MODE_COLOR_2D_8BPP;
1399 break;
1400 case 2:
1401 *tile_mode = SI_TILE_MODE_COLOR_2D_16BPP;
1402 break;
1403 case 4:
1404 *tile_mode = SI_TILE_MODE_COLOR_2D_32BPP;
1405 break;
1406 case 8:
1407 case 16:
1408 *tile_mode = SI_TILE_MODE_COLOR_2D_64BPP;
1409 break;
1410 default:
1411 return -EINVAL;
1412 }
1413 }
1414 /* retrieve tiling mode value */
1415 gb_tile_mode = surf_man->hw_info.tile_mode_array[*tile_mode];
1416 si_gb_tile_mode(gb_tile_mode, NULL, NULL, &surf->mtilea, &surf->bankw, &surf->bankh, &surf->tile_split);
1417 break;
1418 case RADEON_SURF_MODE_1D:
1419 if (surf->flags & RADEON_SURF_SBUFFER) {
1420 *stencil_tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1421 }
1422 if (surf->flags & RADEON_SURF_ZBUFFER) {
1423 *tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1424 } else if (surf->flags & RADEON_SURF_SCANOUT) {
1425 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1426 } else {
1427 *tile_mode = SI_TILE_MODE_COLOR_1D;
1428 }
1429 break;
1430 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1431 default:
1432 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
1433 }
1434
1435 return 0;
1436 }
1437
si_surf_minify(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,uint32_t xalign,uint32_t yalign,uint32_t zalign,uint32_t slice_align,uint64_t offset)1438 static void si_surf_minify(struct radeon_surface *surf,
1439 struct radeon_surface_level *surflevel,
1440 unsigned bpe, unsigned level,
1441 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1442 uint32_t slice_align, uint64_t offset)
1443 {
1444 if (level == 0) {
1445 surflevel->npix_x = surf->npix_x;
1446 } else {
1447 surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1448 }
1449 surflevel->npix_y = mip_minify(surf->npix_y, level);
1450 surflevel->npix_z = mip_minify(surf->npix_z, level);
1451
1452 if (level == 0 && surf->last_level > 0) {
1453 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1454 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1455 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1456 } else {
1457 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1458 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1459 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1460 }
1461
1462 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1463
1464 /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
1465 * these are just guesses for the rules behind those
1466 */
1467 if (level == 0 && surf->last_level == 0)
1468 /* Non-mipmap pitch padded to slice alignment */
1469 /* Using just bpe here breaks stencil blitting; surf->bpe works. */
1470 xalign = MAX2(xalign, slice_align / surf->bpe);
1471 else if (surflevel->mode == RADEON_SURF_MODE_LINEAR_ALIGNED)
1472 /* Small rows evenly distributed across slice */
1473 xalign = MAX2(xalign, slice_align / bpe / surflevel->nblk_y);
1474
1475 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1476 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1477
1478 surflevel->offset = offset;
1479 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1480 surflevel->slice_size = ALIGN((uint64_t)surflevel->pitch_bytes * surflevel->nblk_y,
1481 (uint64_t)slice_align);
1482
1483 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1484 }
1485
si_surf_minify_2d(struct radeon_surface * surf,struct radeon_surface_level * surflevel,unsigned bpe,unsigned level,unsigned slice_pt,uint32_t xalign,uint32_t yalign,uint32_t zalign,unsigned mtileb,uint64_t offset)1486 static void si_surf_minify_2d(struct radeon_surface *surf,
1487 struct radeon_surface_level *surflevel,
1488 unsigned bpe, unsigned level, unsigned slice_pt,
1489 uint32_t xalign, uint32_t yalign, uint32_t zalign,
1490 unsigned mtileb, uint64_t offset)
1491 {
1492 unsigned mtile_pr, mtile_ps;
1493
1494 if (level == 0) {
1495 surflevel->npix_x = surf->npix_x;
1496 } else {
1497 surflevel->npix_x = mip_minify(next_power_of_two(surf->npix_x), level);
1498 }
1499 surflevel->npix_y = mip_minify(surf->npix_y, level);
1500 surflevel->npix_z = mip_minify(surf->npix_z, level);
1501
1502 if (level == 0 && surf->last_level > 0) {
1503 surflevel->nblk_x = (next_power_of_two(surflevel->npix_x) + surf->blk_w - 1) / surf->blk_w;
1504 surflevel->nblk_y = (next_power_of_two(surflevel->npix_y) + surf->blk_h - 1) / surf->blk_h;
1505 surflevel->nblk_z = (next_power_of_two(surflevel->npix_z) + surf->blk_d - 1) / surf->blk_d;
1506 } else {
1507 surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
1508 surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
1509 surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
1510 }
1511
1512 if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D &&
1513 !(surf->flags & RADEON_SURF_FMASK)) {
1514 if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
1515 surflevel->mode = RADEON_SURF_MODE_1D;
1516 return;
1517 }
1518 }
1519 surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
1520 surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
1521 surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
1522
1523 /* macro tile per row */
1524 mtile_pr = surflevel->nblk_x / xalign;
1525 /* macro tile per slice */
1526 mtile_ps = (mtile_pr * surflevel->nblk_y) / yalign;
1527 surflevel->offset = offset;
1528 surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
1529 surflevel->slice_size = (uint64_t)mtile_ps * mtileb * slice_pt;
1530
1531 surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
1532 }
1533
si_surface_init_linear_aligned(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,uint64_t offset,unsigned start_level)1534 static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
1535 struct radeon_surface *surf,
1536 unsigned tile_mode,
1537 uint64_t offset, unsigned start_level)
1538 {
1539 uint32_t xalign, yalign, zalign, slice_align;
1540 unsigned i;
1541
1542 /* compute alignment */
1543 if (!start_level) {
1544 surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
1545 }
1546 xalign = MAX2(8, 64 / surf->bpe);
1547 yalign = 1;
1548 zalign = 1;
1549 slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
1550
1551 /* build mipmap tree */
1552 for (i = start_level; i <= surf->last_level; i++) {
1553 surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
1554 si_surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, slice_align, offset);
1555 /* level0 and first mipmap need to have alignment */
1556 offset = surf->bo_size;
1557 if (i == 0) {
1558 offset = ALIGN(offset, surf->bo_alignment);
1559 }
1560 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1561 surf->tiling_index[i] = tile_mode;
1562 }
1563 }
1564 return 0;
1565 }
1566
si_surface_init_1d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,uint64_t offset,unsigned start_level)1567 static int si_surface_init_1d(struct radeon_surface_manager *surf_man,
1568 struct radeon_surface *surf,
1569 struct radeon_surface_level *level,
1570 unsigned bpe, unsigned tile_mode,
1571 uint64_t offset, unsigned start_level)
1572 {
1573 uint32_t xalign, yalign, zalign, slice_align;
1574 unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
1575 unsigned i;
1576
1577 /* compute alignment */
1578 xalign = 8;
1579 yalign = 8;
1580 zalign = 1;
1581 slice_align = surf_man->hw_info.group_bytes;
1582 if (surf->flags & RADEON_SURF_SCANOUT) {
1583 xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
1584 }
1585
1586 if (start_level <= 1) {
1587 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1588
1589 if (offset) {
1590 offset = ALIGN(offset, alignment);
1591 }
1592 }
1593
1594 /* build mipmap tree */
1595 for (i = start_level; i <= surf->last_level; i++) {
1596 level[i].mode = RADEON_SURF_MODE_1D;
1597 si_surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, slice_align, offset);
1598 /* level0 and first mipmap need to have alignment */
1599 offset = surf->bo_size;
1600 if (i == 0) {
1601 offset = ALIGN(offset, alignment);
1602 }
1603 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1604 if (surf->level == level) {
1605 surf->tiling_index[i] = tile_mode;
1606 /* it's ok because stencil is done after */
1607 surf->stencil_tiling_index[i] = tile_mode;
1608 } else {
1609 surf->stencil_tiling_index[i] = tile_mode;
1610 }
1611 }
1612 }
1613 return 0;
1614 }
1615
si_surface_init_1d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)1616 static int si_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
1617 struct radeon_surface *surf,
1618 unsigned tile_mode, unsigned stencil_tile_mode)
1619 {
1620 int r;
1621
1622 r = si_surface_init_1d(surf_man, surf, surf->level, surf->bpe, tile_mode, 0, 0);
1623 if (r) {
1624 return r;
1625 }
1626
1627 if (surf->flags & RADEON_SURF_SBUFFER) {
1628 r = si_surface_init_1d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, surf->bo_size, 0);
1629 surf->stencil_offset = surf->stencil_level[0].offset;
1630 }
1631 return r;
1632 }
1633
si_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,unsigned num_pipes,unsigned num_banks,unsigned tile_split,uint64_t offset,unsigned start_level)1634 static int si_surface_init_2d(struct radeon_surface_manager *surf_man,
1635 struct radeon_surface *surf,
1636 struct radeon_surface_level *level,
1637 unsigned bpe, unsigned tile_mode,
1638 unsigned num_pipes, unsigned num_banks,
1639 unsigned tile_split,
1640 uint64_t offset,
1641 unsigned start_level)
1642 {
1643 uint64_t aligned_offset = offset;
1644 unsigned tilew, tileh, tileb;
1645 unsigned mtilew, mtileh, mtileb;
1646 unsigned slice_pt;
1647 unsigned i;
1648
1649 /* compute tile values */
1650 tilew = 8;
1651 tileh = 8;
1652 tileb = tilew * tileh * bpe * surf->nsamples;
1653 /* slices per tile */
1654 slice_pt = 1;
1655 if (tileb > tile_split && tile_split) {
1656 slice_pt = tileb / tile_split;
1657 }
1658 tileb = tileb / slice_pt;
1659
1660 /* macro tile width & height */
1661 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
1662 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
1663
1664 /* macro tile bytes */
1665 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
1666
1667 if (start_level <= 1) {
1668 unsigned alignment = MAX2(256, mtileb);
1669 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
1670
1671 if (aligned_offset) {
1672 aligned_offset = ALIGN(aligned_offset, alignment);
1673 }
1674 }
1675
1676 /* build mipmap tree */
1677 for (i = start_level; i <= surf->last_level; i++) {
1678 level[i].mode = RADEON_SURF_MODE_2D;
1679 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
1680 if (level[i].mode == RADEON_SURF_MODE_1D) {
1681 switch (tile_mode) {
1682 case SI_TILE_MODE_COLOR_2D_8BPP:
1683 case SI_TILE_MODE_COLOR_2D_16BPP:
1684 case SI_TILE_MODE_COLOR_2D_32BPP:
1685 case SI_TILE_MODE_COLOR_2D_64BPP:
1686 tile_mode = SI_TILE_MODE_COLOR_1D;
1687 break;
1688 case SI_TILE_MODE_COLOR_2D_SCANOUT_16BPP:
1689 case SI_TILE_MODE_COLOR_2D_SCANOUT_32BPP:
1690 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
1691 break;
1692 case SI_TILE_MODE_DEPTH_STENCIL_2D:
1693 tile_mode = SI_TILE_MODE_DEPTH_STENCIL_1D;
1694 break;
1695 default:
1696 return -EINVAL;
1697 }
1698 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
1699 }
1700 /* level0 and first mipmap need to have alignment */
1701 aligned_offset = offset = surf->bo_size;
1702 if (i == 0) {
1703 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
1704 }
1705 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
1706 if (surf->level == level) {
1707 surf->tiling_index[i] = tile_mode;
1708 /* it's ok because stencil is done after */
1709 surf->stencil_tiling_index[i] = tile_mode;
1710 } else {
1711 surf->stencil_tiling_index[i] = tile_mode;
1712 }
1713 }
1714 }
1715 return 0;
1716 }
1717
si_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)1718 static int si_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
1719 struct radeon_surface *surf,
1720 unsigned tile_mode, unsigned stencil_tile_mode)
1721 {
1722 unsigned num_pipes, num_banks;
1723 uint32_t gb_tile_mode;
1724 int r;
1725
1726 /* retrieve tiling mode value */
1727 gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1728 si_gb_tile_mode(gb_tile_mode, &num_pipes, &num_banks, NULL, NULL, NULL, NULL);
1729
1730 r = si_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode, num_pipes, num_banks, surf->tile_split, 0, 0);
1731 if (r) {
1732 return r;
1733 }
1734
1735 if (surf->flags & RADEON_SURF_SBUFFER) {
1736 r = si_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode, num_pipes, num_banks, surf->stencil_tile_split, surf->bo_size, 0);
1737 surf->stencil_offset = surf->stencil_level[0].offset;
1738 }
1739 return r;
1740 }
1741
si_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)1742 static int si_surface_init(struct radeon_surface_manager *surf_man,
1743 struct radeon_surface *surf)
1744 {
1745 unsigned mode, tile_mode, stencil_tile_mode = 0;
1746 int r;
1747
1748 /* MSAA surfaces support the 2D mode only. */
1749 if (surf->nsamples > 1) {
1750 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1751 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
1752 }
1753
1754 /* tiling mode */
1755 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1756
1757 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
1758 /* zbuffer only support 1D or 2D tiled surface */
1759 switch (mode) {
1760 case RADEON_SURF_MODE_1D:
1761 case RADEON_SURF_MODE_2D:
1762 break;
1763 default:
1764 mode = RADEON_SURF_MODE_1D;
1765 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1766 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1767 break;
1768 }
1769 }
1770
1771 r = si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1772 if (r) {
1773 return r;
1774 }
1775
1776 surf->stencil_offset = 0;
1777 surf->bo_alignment = 0;
1778
1779 /* check tiling mode */
1780 switch (mode) {
1781 case RADEON_SURF_MODE_LINEAR:
1782 r = r6_surface_init_linear(surf_man, surf, 0, 0);
1783 break;
1784 case RADEON_SURF_MODE_LINEAR_ALIGNED:
1785 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
1786 break;
1787 case RADEON_SURF_MODE_1D:
1788 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1789 break;
1790 case RADEON_SURF_MODE_2D:
1791 r = si_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
1792 break;
1793 default:
1794 return -EINVAL;
1795 }
1796 return r;
1797 }
1798
1799 /*
1800 * depending on surface
1801 */
si_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)1802 static int si_surface_best(struct radeon_surface_manager *surf_man,
1803 struct radeon_surface *surf)
1804 {
1805 unsigned mode, tile_mode, stencil_tile_mode;
1806
1807 /* tiling mode */
1808 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
1809
1810 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
1811 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
1812 /* depth/stencil force 1d tiling for old mesa */
1813 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
1814 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
1815 }
1816
1817 return si_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
1818 }
1819
1820
1821 /* ===========================================================================
1822 * Sea Islands family
1823 */
1824 #define CIK__GB_TILE_MODE__PIPE_CONFIG(x) (((x) >> 6) & 0x1f)
1825 #define CIK__PIPE_CONFIG__ADDR_SURF_P2 0
1826 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16 4
1827 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16 5
1828 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32 6
1829 #define CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32 7
1830 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16 8
1831 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16 9
1832 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16 10
1833 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16 11
1834 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16 12
1835 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32 13
1836 #define CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32 14
1837 #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16 16
1838 #define CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16 17
1839 #define CIK__GB_TILE_MODE__TILE_SPLIT(x) (((x) >> 11) & 0x7)
1840 #define CIK__TILE_SPLIT__64B 0
1841 #define CIK__TILE_SPLIT__128B 1
1842 #define CIK__TILE_SPLIT__256B 2
1843 #define CIK__TILE_SPLIT__512B 3
1844 #define CIK__TILE_SPLIT__1024B 4
1845 #define CIK__TILE_SPLIT__2048B 5
1846 #define CIK__TILE_SPLIT__4096B 6
1847 #define CIK__GB_TILE_MODE__SAMPLE_SPLIT(x) (((x) >> 25) & 0x3)
1848 #define CIK__SAMPLE_SPLIT__1 0
1849 #define CIK__SAMPLE_SPLIT__2 1
1850 #define CIK__SAMPLE_SPLIT__4 2
1851 #define CIK__SAMPLE_SPLIT__8 3
1852 #define CIK__GB_MACROTILE_MODE__BANK_WIDTH(x) ((x) & 0x3)
1853 #define CIK__BANK_WIDTH__1 0
1854 #define CIK__BANK_WIDTH__2 1
1855 #define CIK__BANK_WIDTH__4 2
1856 #define CIK__BANK_WIDTH__8 3
1857 #define CIK__GB_MACROTILE_MODE__BANK_HEIGHT(x) (((x) >> 2) & 0x3)
1858 #define CIK__BANK_HEIGHT__1 0
1859 #define CIK__BANK_HEIGHT__2 1
1860 #define CIK__BANK_HEIGHT__4 2
1861 #define CIK__BANK_HEIGHT__8 3
1862 #define CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(x) (((x) >> 4) & 0x3)
1863 #define CIK__MACRO_TILE_ASPECT__1 0
1864 #define CIK__MACRO_TILE_ASPECT__2 1
1865 #define CIK__MACRO_TILE_ASPECT__4 2
1866 #define CIK__MACRO_TILE_ASPECT__8 3
1867 #define CIK__GB_MACROTILE_MODE__NUM_BANKS(x) (((x) >> 6) & 0x3)
1868 #define CIK__NUM_BANKS__2_BANK 0
1869 #define CIK__NUM_BANKS__4_BANK 1
1870 #define CIK__NUM_BANKS__8_BANK 2
1871 #define CIK__NUM_BANKS__16_BANK 3
1872
1873
cik_get_2d_params(struct radeon_surface_manager * surf_man,unsigned bpe,unsigned nsamples,bool is_color,unsigned tile_mode,uint32_t * num_pipes,uint32_t * tile_split_ptr,uint32_t * num_banks,uint32_t * macro_tile_aspect,uint32_t * bank_w,uint32_t * bank_h)1874 static void cik_get_2d_params(struct radeon_surface_manager *surf_man,
1875 unsigned bpe, unsigned nsamples, bool is_color,
1876 unsigned tile_mode,
1877 uint32_t *num_pipes,
1878 uint32_t *tile_split_ptr,
1879 uint32_t *num_banks,
1880 uint32_t *macro_tile_aspect,
1881 uint32_t *bank_w,
1882 uint32_t *bank_h)
1883 {
1884 uint32_t gb_tile_mode = surf_man->hw_info.tile_mode_array[tile_mode];
1885 unsigned tileb_1x, tileb;
1886 unsigned gb_macrotile_mode;
1887 unsigned macrotile_index;
1888 unsigned tile_split, sample_split;
1889
1890 if (num_pipes) {
1891 switch (CIK__GB_TILE_MODE__PIPE_CONFIG(gb_tile_mode)) {
1892 case CIK__PIPE_CONFIG__ADDR_SURF_P2:
1893 default:
1894 *num_pipes = 2;
1895 break;
1896 case CIK__PIPE_CONFIG__ADDR_SURF_P4_8x16:
1897 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x16:
1898 case CIK__PIPE_CONFIG__ADDR_SURF_P4_16x32:
1899 case CIK__PIPE_CONFIG__ADDR_SURF_P4_32x32:
1900 *num_pipes = 4;
1901 break;
1902 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x16_8x16:
1903 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_8x16:
1904 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_8x16:
1905 case CIK__PIPE_CONFIG__ADDR_SURF_P8_16x32_16x16:
1906 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x16:
1907 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x32_16x32:
1908 case CIK__PIPE_CONFIG__ADDR_SURF_P8_32x64_32x32:
1909 *num_pipes = 8;
1910 break;
1911 case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_8X16:
1912 case CIK__PIPE_CONFIG__ADDR_SURF_P16_32X32_16X16:
1913 *num_pipes = 16;
1914 break;
1915 }
1916 }
1917 switch (CIK__GB_TILE_MODE__TILE_SPLIT(gb_tile_mode)) {
1918 default:
1919 case CIK__TILE_SPLIT__64B:
1920 tile_split = 64;
1921 break;
1922 case CIK__TILE_SPLIT__128B:
1923 tile_split = 128;
1924 break;
1925 case CIK__TILE_SPLIT__256B:
1926 tile_split = 256;
1927 break;
1928 case CIK__TILE_SPLIT__512B:
1929 tile_split = 512;
1930 break;
1931 case CIK__TILE_SPLIT__1024B:
1932 tile_split = 1024;
1933 break;
1934 case CIK__TILE_SPLIT__2048B:
1935 tile_split = 2048;
1936 break;
1937 case CIK__TILE_SPLIT__4096B:
1938 tile_split = 4096;
1939 break;
1940 }
1941 switch (CIK__GB_TILE_MODE__SAMPLE_SPLIT(gb_tile_mode)) {
1942 default:
1943 case CIK__SAMPLE_SPLIT__1:
1944 sample_split = 1;
1945 break;
1946 case CIK__SAMPLE_SPLIT__2:
1947 sample_split = 2;
1948 break;
1949 case CIK__SAMPLE_SPLIT__4:
1950 sample_split = 4;
1951 break;
1952 case CIK__SAMPLE_SPLIT__8:
1953 sample_split = 8;
1954 break;
1955 }
1956
1957 /* Adjust the tile split. */
1958 tileb_1x = 8 * 8 * bpe;
1959 if (is_color) {
1960 tile_split = MAX2(256, sample_split * tileb_1x);
1961 }
1962 tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
1963
1964 /* Determine the macrotile index. */
1965 tileb = MIN2(tile_split, nsamples * tileb_1x);
1966
1967 for (macrotile_index = 0; tileb > 64; macrotile_index++) {
1968 tileb >>= 1;
1969 }
1970 gb_macrotile_mode = surf_man->hw_info.macrotile_mode_array[macrotile_index];
1971
1972 if (tile_split_ptr) {
1973 *tile_split_ptr = tile_split;
1974 }
1975 if (num_banks) {
1976 switch (CIK__GB_MACROTILE_MODE__NUM_BANKS(gb_macrotile_mode)) {
1977 default:
1978 case CIK__NUM_BANKS__2_BANK:
1979 *num_banks = 2;
1980 break;
1981 case CIK__NUM_BANKS__4_BANK:
1982 *num_banks = 4;
1983 break;
1984 case CIK__NUM_BANKS__8_BANK:
1985 *num_banks = 8;
1986 break;
1987 case CIK__NUM_BANKS__16_BANK:
1988 *num_banks = 16;
1989 break;
1990 }
1991 }
1992 if (macro_tile_aspect) {
1993 switch (CIK__GB_MACROTILE_MODE__MACRO_TILE_ASPECT(gb_macrotile_mode)) {
1994 default:
1995 case CIK__MACRO_TILE_ASPECT__1:
1996 *macro_tile_aspect = 1;
1997 break;
1998 case CIK__MACRO_TILE_ASPECT__2:
1999 *macro_tile_aspect = 2;
2000 break;
2001 case CIK__MACRO_TILE_ASPECT__4:
2002 *macro_tile_aspect = 4;
2003 break;
2004 case CIK__MACRO_TILE_ASPECT__8:
2005 *macro_tile_aspect = 8;
2006 break;
2007 }
2008 }
2009 if (bank_w) {
2010 switch (CIK__GB_MACROTILE_MODE__BANK_WIDTH(gb_macrotile_mode)) {
2011 default:
2012 case CIK__BANK_WIDTH__1:
2013 *bank_w = 1;
2014 break;
2015 case CIK__BANK_WIDTH__2:
2016 *bank_w = 2;
2017 break;
2018 case CIK__BANK_WIDTH__4:
2019 *bank_w = 4;
2020 break;
2021 case CIK__BANK_WIDTH__8:
2022 *bank_w = 8;
2023 break;
2024 }
2025 }
2026 if (bank_h) {
2027 switch (CIK__GB_MACROTILE_MODE__BANK_HEIGHT(gb_macrotile_mode)) {
2028 default:
2029 case CIK__BANK_HEIGHT__1:
2030 *bank_h = 1;
2031 break;
2032 case CIK__BANK_HEIGHT__2:
2033 *bank_h = 2;
2034 break;
2035 case CIK__BANK_HEIGHT__4:
2036 *bank_h = 4;
2037 break;
2038 case CIK__BANK_HEIGHT__8:
2039 *bank_h = 8;
2040 break;
2041 }
2042 }
2043 }
2044
cik_init_hw_info(struct radeon_surface_manager * surf_man)2045 static int cik_init_hw_info(struct radeon_surface_manager *surf_man)
2046 {
2047 uint32_t tiling_config;
2048 drmVersionPtr version;
2049 int r;
2050
2051 r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
2052 &tiling_config);
2053 if (r) {
2054 return r;
2055 }
2056
2057 surf_man->hw_info.allow_2d = 0;
2058 version = drmGetVersion(surf_man->fd);
2059 if (version && version->version_minor >= 35) {
2060 if (!radeon_get_value(surf_man->fd, RADEON_INFO_SI_TILE_MODE_ARRAY, surf_man->hw_info.tile_mode_array) &&
2061 !radeon_get_value(surf_man->fd, RADEON_INFO_CIK_MACROTILE_MODE_ARRAY, surf_man->hw_info.macrotile_mode_array)) {
2062 surf_man->hw_info.allow_2d = 1;
2063 }
2064 }
2065 drmFreeVersion(version);
2066
2067 switch (tiling_config & 0xf) {
2068 case 0:
2069 surf_man->hw_info.num_pipes = 1;
2070 break;
2071 case 1:
2072 surf_man->hw_info.num_pipes = 2;
2073 break;
2074 case 2:
2075 surf_man->hw_info.num_pipes = 4;
2076 break;
2077 case 3:
2078 surf_man->hw_info.num_pipes = 8;
2079 break;
2080 default:
2081 surf_man->hw_info.num_pipes = 8;
2082 surf_man->hw_info.allow_2d = 0;
2083 break;
2084 }
2085
2086 switch ((tiling_config & 0xf0) >> 4) {
2087 case 0:
2088 surf_man->hw_info.num_banks = 4;
2089 break;
2090 case 1:
2091 surf_man->hw_info.num_banks = 8;
2092 break;
2093 case 2:
2094 surf_man->hw_info.num_banks = 16;
2095 break;
2096 default:
2097 surf_man->hw_info.num_banks = 8;
2098 surf_man->hw_info.allow_2d = 0;
2099 break;
2100 }
2101
2102 switch ((tiling_config & 0xf00) >> 8) {
2103 case 0:
2104 surf_man->hw_info.group_bytes = 256;
2105 break;
2106 case 1:
2107 surf_man->hw_info.group_bytes = 512;
2108 break;
2109 default:
2110 surf_man->hw_info.group_bytes = 256;
2111 surf_man->hw_info.allow_2d = 0;
2112 break;
2113 }
2114
2115 switch ((tiling_config & 0xf000) >> 12) {
2116 case 0:
2117 surf_man->hw_info.row_size = 1024;
2118 break;
2119 case 1:
2120 surf_man->hw_info.row_size = 2048;
2121 break;
2122 case 2:
2123 surf_man->hw_info.row_size = 4096;
2124 break;
2125 default:
2126 surf_man->hw_info.row_size = 4096;
2127 surf_man->hw_info.allow_2d = 0;
2128 break;
2129 }
2130 return 0;
2131 }
2132
cik_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned mode,unsigned * tile_mode,unsigned * stencil_tile_mode)2133 static int cik_surface_sanity(struct radeon_surface_manager *surf_man,
2134 struct radeon_surface *surf,
2135 unsigned mode, unsigned *tile_mode, unsigned *stencil_tile_mode)
2136 {
2137 /* check surface dimension */
2138 if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
2139 return -EINVAL;
2140 }
2141
2142 /* check mipmap last_level */
2143 if (surf->last_level > 15) {
2144 return -EINVAL;
2145 }
2146
2147 /* force 1d on kernel that can't do 2d */
2148 if (mode > RADEON_SURF_MODE_1D &&
2149 (!surf_man->hw_info.allow_2d || !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX))) {
2150 if (surf->nsamples > 1) {
2151 fprintf(stderr, "radeon: Cannot use 1D tiling for an MSAA surface (%i).\n", __LINE__);
2152 return -EFAULT;
2153 }
2154 mode = RADEON_SURF_MODE_1D;
2155 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2156 surf->flags |= RADEON_SURF_SET(mode, MODE);
2157 }
2158
2159 if (surf->nsamples > 1 && mode != RADEON_SURF_MODE_2D) {
2160 return -EINVAL;
2161 }
2162
2163 if (!surf->tile_split) {
2164 /* default value */
2165 surf->mtilea = 1;
2166 surf->bankw = 1;
2167 surf->bankh = 1;
2168 surf->tile_split = 64;
2169 surf->stencil_tile_split = 64;
2170 }
2171
2172 switch (mode) {
2173 case RADEON_SURF_MODE_2D: {
2174 if (surf->flags & RADEON_SURF_Z_OR_SBUFFER) {
2175 switch (surf->nsamples) {
2176 case 1:
2177 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64;
2178 break;
2179 case 2:
2180 case 4:
2181 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128;
2182 break;
2183 case 8:
2184 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256;
2185 break;
2186 default:
2187 return -EINVAL;
2188 }
2189
2190 if (surf->flags & RADEON_SURF_SBUFFER) {
2191 *stencil_tile_mode = *tile_mode;
2192
2193 cik_get_2d_params(surf_man, 1, surf->nsamples, false,
2194 *stencil_tile_mode, NULL,
2195 &surf->stencil_tile_split,
2196 NULL, NULL, NULL, NULL);
2197 }
2198 } else if (surf->flags & RADEON_SURF_SCANOUT) {
2199 *tile_mode = CIK_TILE_MODE_COLOR_2D_SCANOUT;
2200 } else {
2201 *tile_mode = CIK_TILE_MODE_COLOR_2D;
2202 }
2203
2204 /* retrieve tiling mode values */
2205 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2206 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), *tile_mode,
2207 NULL, &surf->tile_split, NULL, &surf->mtilea,
2208 &surf->bankw, &surf->bankh);
2209 break;
2210 }
2211 case RADEON_SURF_MODE_1D:
2212 if (surf->flags & RADEON_SURF_SBUFFER) {
2213 *stencil_tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2214 }
2215 if (surf->flags & RADEON_SURF_ZBUFFER) {
2216 *tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2217 } else if (surf->flags & RADEON_SURF_SCANOUT) {
2218 *tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2219 } else {
2220 *tile_mode = SI_TILE_MODE_COLOR_1D;
2221 }
2222 break;
2223 case RADEON_SURF_MODE_LINEAR_ALIGNED:
2224 default:
2225 *stencil_tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
2226 *tile_mode = SI_TILE_MODE_COLOR_LINEAR_ALIGNED;
2227 }
2228
2229 return 0;
2230 }
2231
cik_surface_init_2d(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,struct radeon_surface_level * level,unsigned bpe,unsigned tile_mode,unsigned tile_split,unsigned num_pipes,unsigned num_banks,uint64_t offset,unsigned start_level)2232 static int cik_surface_init_2d(struct radeon_surface_manager *surf_man,
2233 struct radeon_surface *surf,
2234 struct radeon_surface_level *level,
2235 unsigned bpe, unsigned tile_mode,
2236 unsigned tile_split,
2237 unsigned num_pipes, unsigned num_banks,
2238 uint64_t offset,
2239 unsigned start_level)
2240 {
2241 uint64_t aligned_offset = offset;
2242 unsigned tilew, tileh, tileb_1x, tileb;
2243 unsigned mtilew, mtileh, mtileb;
2244 unsigned slice_pt;
2245 unsigned i;
2246
2247 /* compute tile values */
2248 tilew = 8;
2249 tileh = 8;
2250 tileb_1x = tilew * tileh * bpe;
2251
2252 tile_split = MIN2(surf_man->hw_info.row_size, tile_split);
2253
2254 tileb = surf->nsamples * tileb_1x;
2255
2256 /* slices per tile */
2257 slice_pt = 1;
2258 if (tileb > tile_split && tile_split) {
2259 slice_pt = tileb / tile_split;
2260 tileb = tileb / slice_pt;
2261 }
2262
2263 /* macro tile width & height */
2264 mtilew = (tilew * surf->bankw * num_pipes) * surf->mtilea;
2265 mtileh = (tileh * surf->bankh * num_banks) / surf->mtilea;
2266
2267 /* macro tile bytes */
2268 mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
2269
2270 if (start_level <= 1) {
2271 unsigned alignment = MAX2(256, mtileb);
2272 surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
2273
2274 if (aligned_offset) {
2275 aligned_offset = ALIGN(aligned_offset, alignment);
2276 }
2277 }
2278
2279 /* build mipmap tree */
2280 for (i = start_level; i <= surf->last_level; i++) {
2281 level[i].mode = RADEON_SURF_MODE_2D;
2282 si_surf_minify_2d(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, 1, mtileb, aligned_offset);
2283 if (level[i].mode == RADEON_SURF_MODE_1D) {
2284 switch (tile_mode) {
2285 case CIK_TILE_MODE_COLOR_2D:
2286 tile_mode = SI_TILE_MODE_COLOR_1D;
2287 break;
2288 case CIK_TILE_MODE_COLOR_2D_SCANOUT:
2289 tile_mode = SI_TILE_MODE_COLOR_1D_SCANOUT;
2290 break;
2291 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_64:
2292 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_128:
2293 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_256:
2294 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_512:
2295 case CIK_TILE_MODE_DEPTH_STENCIL_2D_TILESPLIT_ROW_SIZE:
2296 tile_mode = CIK_TILE_MODE_DEPTH_STENCIL_1D;
2297 break;
2298 default:
2299 return -EINVAL;
2300 }
2301 return si_surface_init_1d(surf_man, surf, level, bpe, tile_mode, offset, i);
2302 }
2303 /* level0 and first mipmap need to have alignment */
2304 aligned_offset = offset = surf->bo_size;
2305 if (i == 0) {
2306 aligned_offset = ALIGN(aligned_offset, surf->bo_alignment);
2307 }
2308 if (surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX) {
2309 if (surf->level == level) {
2310 surf->tiling_index[i] = tile_mode;
2311 /* it's ok because stencil is done after */
2312 surf->stencil_tiling_index[i] = tile_mode;
2313 } else {
2314 surf->stencil_tiling_index[i] = tile_mode;
2315 }
2316 }
2317 }
2318 return 0;
2319 }
2320
cik_surface_init_2d_miptrees(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned tile_mode,unsigned stencil_tile_mode)2321 static int cik_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
2322 struct radeon_surface *surf,
2323 unsigned tile_mode, unsigned stencil_tile_mode)
2324 {
2325 int r;
2326 uint32_t num_pipes, num_banks;
2327
2328 cik_get_2d_params(surf_man, surf->bpe, surf->nsamples,
2329 !(surf->flags & RADEON_SURF_Z_OR_SBUFFER), tile_mode,
2330 &num_pipes, NULL, &num_banks, NULL, NULL, NULL);
2331
2332 r = cik_surface_init_2d(surf_man, surf, surf->level, surf->bpe, tile_mode,
2333 surf->tile_split, num_pipes, num_banks, 0, 0);
2334 if (r) {
2335 return r;
2336 }
2337
2338 if (surf->flags & RADEON_SURF_SBUFFER) {
2339 r = cik_surface_init_2d(surf_man, surf, surf->stencil_level, 1, stencil_tile_mode,
2340 surf->stencil_tile_split, num_pipes, num_banks,
2341 surf->bo_size, 0);
2342 surf->stencil_offset = surf->stencil_level[0].offset;
2343 }
2344 return r;
2345 }
2346
cik_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2347 static int cik_surface_init(struct radeon_surface_manager *surf_man,
2348 struct radeon_surface *surf)
2349 {
2350 unsigned mode, tile_mode, stencil_tile_mode = 0;
2351 int r;
2352
2353 /* MSAA surfaces support the 2D mode only. */
2354 if (surf->nsamples > 1) {
2355 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2356 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
2357 }
2358
2359 /* tiling mode */
2360 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2361
2362 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
2363 /* zbuffer only support 1D or 2D tiled surface */
2364 switch (mode) {
2365 case RADEON_SURF_MODE_1D:
2366 case RADEON_SURF_MODE_2D:
2367 break;
2368 default:
2369 mode = RADEON_SURF_MODE_1D;
2370 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2371 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2372 break;
2373 }
2374 }
2375
2376 r = cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2377 if (r) {
2378 return r;
2379 }
2380
2381 surf->stencil_offset = 0;
2382 surf->bo_alignment = 0;
2383
2384 /* check tiling mode */
2385 switch (mode) {
2386 case RADEON_SURF_MODE_LINEAR:
2387 r = r6_surface_init_linear(surf_man, surf, 0, 0);
2388 break;
2389 case RADEON_SURF_MODE_LINEAR_ALIGNED:
2390 r = si_surface_init_linear_aligned(surf_man, surf, tile_mode, 0, 0);
2391 break;
2392 case RADEON_SURF_MODE_1D:
2393 r = si_surface_init_1d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2394 break;
2395 case RADEON_SURF_MODE_2D:
2396 r = cik_surface_init_2d_miptrees(surf_man, surf, tile_mode, stencil_tile_mode);
2397 break;
2398 default:
2399 return -EINVAL;
2400 }
2401 return r;
2402 }
2403
2404 /*
2405 * depending on surface
2406 */
cik_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2407 static int cik_surface_best(struct radeon_surface_manager *surf_man,
2408 struct radeon_surface *surf)
2409 {
2410 unsigned mode, tile_mode, stencil_tile_mode;
2411
2412 /* tiling mode */
2413 mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
2414
2415 if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER) &&
2416 !(surf->flags & RADEON_SURF_HAS_TILE_MODE_INDEX)) {
2417 /* depth/stencil force 1d tiling for old mesa */
2418 surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
2419 surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
2420 }
2421
2422 return cik_surface_sanity(surf_man, surf, mode, &tile_mode, &stencil_tile_mode);
2423 }
2424
2425
2426 /* ===========================================================================
2427 * public API
2428 */
2429 struct radeon_surface_manager *
radeon_surface_manager_new(int fd)2430 radeon_surface_manager_new(int fd)
2431 {
2432 struct radeon_surface_manager *surf_man;
2433
2434 surf_man = calloc(1, sizeof(struct radeon_surface_manager));
2435 if (surf_man == NULL) {
2436 return NULL;
2437 }
2438 surf_man->fd = fd;
2439 if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
2440 goto out_err;
2441 }
2442 if (radeon_get_family(surf_man)) {
2443 goto out_err;
2444 }
2445
2446 if (surf_man->family <= CHIP_RV740) {
2447 if (r6_init_hw_info(surf_man)) {
2448 goto out_err;
2449 }
2450 surf_man->surface_init = &r6_surface_init;
2451 surf_man->surface_best = &r6_surface_best;
2452 } else if (surf_man->family <= CHIP_ARUBA) {
2453 if (eg_init_hw_info(surf_man)) {
2454 goto out_err;
2455 }
2456 surf_man->surface_init = &eg_surface_init;
2457 surf_man->surface_best = &eg_surface_best;
2458 } else if (surf_man->family < CHIP_BONAIRE) {
2459 if (si_init_hw_info(surf_man)) {
2460 goto out_err;
2461 }
2462 surf_man->surface_init = &si_surface_init;
2463 surf_man->surface_best = &si_surface_best;
2464 } else {
2465 if (cik_init_hw_info(surf_man)) {
2466 goto out_err;
2467 }
2468 surf_man->surface_init = &cik_surface_init;
2469 surf_man->surface_best = &cik_surface_best;
2470 }
2471
2472 return surf_man;
2473 out_err:
2474 free(surf_man);
2475 return NULL;
2476 }
2477
2478 void
radeon_surface_manager_free(struct radeon_surface_manager * surf_man)2479 radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
2480 {
2481 free(surf_man);
2482 }
2483
radeon_surface_sanity(struct radeon_surface_manager * surf_man,struct radeon_surface * surf,unsigned type,unsigned mode)2484 static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
2485 struct radeon_surface *surf,
2486 unsigned type,
2487 unsigned mode)
2488 {
2489 if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
2490 return -EINVAL;
2491 }
2492
2493 /* all dimension must be at least 1 ! */
2494 if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
2495 return -EINVAL;
2496 }
2497 if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
2498 return -EINVAL;
2499 }
2500 if (!surf->array_size) {
2501 return -EINVAL;
2502 }
2503 /* array size must be a power of 2 */
2504 surf->array_size = next_power_of_two(surf->array_size);
2505
2506 switch (surf->nsamples) {
2507 case 1:
2508 case 2:
2509 case 4:
2510 case 8:
2511 break;
2512 default:
2513 return -EINVAL;
2514 }
2515 /* check type */
2516 switch (type) {
2517 case RADEON_SURF_TYPE_1D:
2518 if (surf->npix_y > 1) {
2519 return -EINVAL;
2520 }
2521 FALLTHROUGH;
2522 case RADEON_SURF_TYPE_2D:
2523 if (surf->npix_z > 1) {
2524 return -EINVAL;
2525 }
2526 break;
2527 case RADEON_SURF_TYPE_CUBEMAP:
2528 if (surf->npix_z > 1) {
2529 return -EINVAL;
2530 }
2531 /* deal with cubemap as they were texture array */
2532 if (surf_man->family >= CHIP_RV770) {
2533 surf->array_size = 8;
2534 } else {
2535 surf->array_size = 6;
2536 }
2537 break;
2538 case RADEON_SURF_TYPE_3D:
2539 break;
2540 case RADEON_SURF_TYPE_1D_ARRAY:
2541 if (surf->npix_y > 1) {
2542 return -EINVAL;
2543 }
2544 FALLTHROUGH;
2545 case RADEON_SURF_TYPE_2D_ARRAY:
2546 break;
2547 default:
2548 return -EINVAL;
2549 }
2550 return 0;
2551 }
2552
2553 int
radeon_surface_init(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2554 radeon_surface_init(struct radeon_surface_manager *surf_man,
2555 struct radeon_surface *surf)
2556 {
2557 unsigned mode, type;
2558 int r;
2559
2560 type = RADEON_SURF_GET(surf->flags, TYPE);
2561 mode = RADEON_SURF_GET(surf->flags, MODE);
2562
2563 r = radeon_surface_sanity(surf_man, surf, type, mode);
2564 if (r) {
2565 return r;
2566 }
2567 return surf_man->surface_init(surf_man, surf);
2568 }
2569
2570 int
radeon_surface_best(struct radeon_surface_manager * surf_man,struct radeon_surface * surf)2571 radeon_surface_best(struct radeon_surface_manager *surf_man,
2572 struct radeon_surface *surf)
2573 {
2574 unsigned mode, type;
2575 int r;
2576
2577 type = RADEON_SURF_GET(surf->flags, TYPE);
2578 mode = RADEON_SURF_GET(surf->flags, MODE);
2579
2580 r = radeon_surface_sanity(surf_man, surf, type, mode);
2581 if (r) {
2582 return r;
2583 }
2584 return surf_man->surface_best(surf_man, surf);
2585 }
2586