ec126bfc7cb45657a4e4c18a47bd8af670d83110
[mesa.git] / src / amd / vulkan / winsys / amdgpu / radv_amdgpu_bo.c
1 /*
2 * Copyright © 2016 Red Hat.
3 * Copyright © 2016 Bas Nieuwenhuizen
4 *
5 * based on amdgpu winsys.
6 * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
7 * Copyright © 2015 Advanced Micro Devices, Inc.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the next
17 * paragraph) shall be included in all copies or substantial portions of the
18 * Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 * IN THE SOFTWARE.
27 */
28
29 #include <stdio.h>
30
31 #include "radv_amdgpu_bo.h"
32
33 #include <amdgpu.h>
34 #include <amdgpu_drm.h>
35 #include <inttypes.h>
36 #include <pthread.h>
37 #include <unistd.h>
38
39 #include "util/u_atomic.h"
40
41 static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo);
42
43 static int
44 radv_amdgpu_bo_va_op(struct radv_amdgpu_winsys *ws,
45 amdgpu_bo_handle bo,
46 uint64_t offset,
47 uint64_t size,
48 uint64_t addr,
49 uint32_t bo_flags,
50 uint32_t ops)
51 {
52 uint64_t flags = AMDGPU_VM_PAGE_READABLE |
53 AMDGPU_VM_PAGE_EXECUTABLE;
54
55 if ((bo_flags & RADEON_FLAG_VA_UNCACHED) && ws->info.chip_class >= GFX9)
56 flags |= AMDGPU_VM_MTYPE_UC;
57
58 if (!(bo_flags & RADEON_FLAG_READ_ONLY))
59 flags |= AMDGPU_VM_PAGE_WRITEABLE;
60
61 size = ALIGN(size, getpagesize());
62
63 return amdgpu_bo_va_op_raw(ws->dev, bo, offset, size, addr,
64 flags, ops);
65 }
66
67 static void
68 radv_amdgpu_winsys_virtual_map(struct radv_amdgpu_winsys_bo *bo,
69 const struct radv_amdgpu_map_range *range)
70 {
71 assert(range->size);
72
73 if (!range->bo)
74 return; /* TODO: PRT mapping */
75
76 p_atomic_inc(&range->bo->ref_count);
77 int r = radv_amdgpu_bo_va_op(bo->ws, range->bo->bo, range->bo_offset,
78 range->size, range->offset + bo->base.va,
79 0, AMDGPU_VA_OP_MAP);
80 if (r)
81 abort();
82 }
83
84 static void
85 radv_amdgpu_winsys_virtual_unmap(struct radv_amdgpu_winsys_bo *bo,
86 const struct radv_amdgpu_map_range *range)
87 {
88 assert(range->size);
89
90 if (!range->bo)
91 return; /* TODO: PRT mapping */
92
93 int r = radv_amdgpu_bo_va_op(bo->ws, range->bo->bo, range->bo_offset,
94 range->size, range->offset + bo->base.va,
95 0, AMDGPU_VA_OP_UNMAP);
96 if (r)
97 abort();
98 radv_amdgpu_winsys_bo_destroy((struct radeon_winsys_bo *)range->bo);
99 }
100
101 static int bo_comparator(const void *ap, const void *bp) {
102 struct radv_amdgpu_bo *a = *(struct radv_amdgpu_bo *const *)ap;
103 struct radv_amdgpu_bo *b = *(struct radv_amdgpu_bo *const *)bp;
104 return (a > b) ? 1 : (a < b) ? -1 : 0;
105 }
106
107 static void
108 radv_amdgpu_winsys_rebuild_bo_list(struct radv_amdgpu_winsys_bo *bo)
109 {
110 if (bo->bo_capacity < bo->range_count) {
111 uint32_t new_count = MAX2(bo->bo_capacity * 2, bo->range_count);
112 bo->bos = realloc(bo->bos, new_count * sizeof(struct radv_amdgpu_winsys_bo *));
113 bo->bo_capacity = new_count;
114 }
115
116 uint32_t temp_bo_count = 0;
117 for (uint32_t i = 0; i < bo->range_count; ++i)
118 if (bo->ranges[i].bo)
119 bo->bos[temp_bo_count++] = bo->ranges[i].bo;
120
121 qsort(bo->bos, temp_bo_count, sizeof(struct radv_amdgpu_winsys_bo *), &bo_comparator);
122
123 uint32_t final_bo_count = 1;
124 for (uint32_t i = 1; i < temp_bo_count; ++i)
125 if (bo->bos[i] != bo->bos[i - 1])
126 bo->bos[final_bo_count++] = bo->bos[i];
127
128 bo->bo_count = final_bo_count;
129 }
130
131 static void
132 radv_amdgpu_winsys_bo_virtual_bind(struct radeon_winsys_bo *_parent,
133 uint64_t offset, uint64_t size,
134 struct radeon_winsys_bo *_bo, uint64_t bo_offset)
135 {
136 struct radv_amdgpu_winsys_bo *parent = (struct radv_amdgpu_winsys_bo *)_parent;
137 struct radv_amdgpu_winsys_bo *bo = (struct radv_amdgpu_winsys_bo*)_bo;
138 int range_count_delta, new_idx;
139 int first = 0, last;
140 struct radv_amdgpu_map_range new_first, new_last;
141
142 assert(parent->is_virtual);
143 assert(!bo || !bo->is_virtual);
144
145 if (!size)
146 return;
147
148 /* We have at most 2 new ranges (1 by the bind, and another one by splitting a range that contains the newly bound range). */
149 if (parent->range_capacity - parent->range_count < 2) {
150 parent->range_capacity += 2;
151 parent->ranges = realloc(parent->ranges,
152 parent->range_capacity * sizeof(struct radv_amdgpu_map_range));
153 }
154
155 /*
156 * [first, last] is exactly the range of ranges that either overlap the
157 * new parent, or are adjacent to it. This corresponds to the bind ranges
158 * that may change.
159 */
160 while(first + 1 < parent->range_count && parent->ranges[first].offset + parent->ranges[first].size < offset)
161 ++first;
162
163 last = first;
164 while(last + 1 < parent->range_count && parent->ranges[last].offset <= offset + size)
165 ++last;
166
167 /* Whether the first or last range are going to be totally removed or just
168 * resized/left alone. Note that in the case of first == last, we will split
169 * this into a part before and after the new range. The remove flag is then
170 * whether to not create the corresponding split part. */
171 bool remove_first = parent->ranges[first].offset == offset;
172 bool remove_last = parent->ranges[last].offset + parent->ranges[last].size == offset + size;
173 bool unmapped_first = false;
174
175 assert(parent->ranges[first].offset <= offset);
176 assert(parent->ranges[last].offset + parent->ranges[last].size >= offset + size);
177
178 /* Try to merge the new range with the first range. */
179 if (parent->ranges[first].bo == bo && (!bo || offset - bo_offset == parent->ranges[first].offset - parent->ranges[first].bo_offset)) {
180 size += offset - parent->ranges[first].offset;
181 offset = parent->ranges[first].offset;
182 bo_offset = parent->ranges[first].bo_offset;
183 remove_first = true;
184 }
185
186 /* Try to merge the new range with the last range. */
187 if (parent->ranges[last].bo == bo && (!bo || offset - bo_offset == parent->ranges[last].offset - parent->ranges[last].bo_offset)) {
188 size = parent->ranges[last].offset + parent->ranges[last].size - offset;
189 remove_last = true;
190 }
191
192 range_count_delta = 1 - (last - first + 1) + !remove_first + !remove_last;
193 new_idx = first + !remove_first;
194
195 /* Any range between first and last is going to be entirely covered by the new range so just unmap them. */
196 for (int i = first + 1; i < last; ++i)
197 radv_amdgpu_winsys_virtual_unmap(parent, parent->ranges + i);
198
199 /* If the first/last range are not left alone we unmap then and optionally map
200 * them again after modifications. Not that this implicitly can do the splitting
201 * if first == last. */
202 new_first = parent->ranges[first];
203 new_last = parent->ranges[last];
204
205 if (parent->ranges[first].offset + parent->ranges[first].size > offset || remove_first) {
206 radv_amdgpu_winsys_virtual_unmap(parent, parent->ranges + first);
207 unmapped_first = true;
208
209 if (!remove_first) {
210 new_first.size = offset - new_first.offset;
211 radv_amdgpu_winsys_virtual_map(parent, &new_first);
212 }
213 }
214
215 if (parent->ranges[last].offset < offset + size || remove_last) {
216 if (first != last || !unmapped_first)
217 radv_amdgpu_winsys_virtual_unmap(parent, parent->ranges + last);
218
219 if (!remove_last) {
220 new_last.size -= offset + size - new_last.offset;
221 new_last.offset = offset + size;
222 radv_amdgpu_winsys_virtual_map(parent, &new_last);
223 }
224 }
225
226 /* Moves the range list after last to account for the changed number of ranges. */
227 memmove(parent->ranges + last + 1 + range_count_delta, parent->ranges + last + 1,
228 sizeof(struct radv_amdgpu_map_range) * (parent->range_count - last - 1));
229
230 if (!remove_first)
231 parent->ranges[first] = new_first;
232
233 if (!remove_last)
234 parent->ranges[new_idx + 1] = new_last;
235
236 /* Actually set up the new range. */
237 parent->ranges[new_idx].offset = offset;
238 parent->ranges[new_idx].size = size;
239 parent->ranges[new_idx].bo = bo;
240 parent->ranges[new_idx].bo_offset = bo_offset;
241
242 radv_amdgpu_winsys_virtual_map(parent, parent->ranges + new_idx);
243
244 parent->range_count += range_count_delta;
245
246 radv_amdgpu_winsys_rebuild_bo_list(parent);
247 }
248
249 static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo)
250 {
251 struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
252
253 if (p_atomic_dec_return(&bo->ref_count))
254 return;
255 if (bo->is_virtual) {
256 for (uint32_t i = 0; i < bo->range_count; ++i) {
257 radv_amdgpu_winsys_virtual_unmap(bo, bo->ranges + i);
258 }
259 free(bo->bos);
260 free(bo->ranges);
261 } else {
262 if (bo->ws->debug_all_bos) {
263 pthread_mutex_lock(&bo->ws->global_bo_list_lock);
264 LIST_DEL(&bo->global_list_item);
265 bo->ws->num_buffers--;
266 pthread_mutex_unlock(&bo->ws->global_bo_list_lock);
267 }
268 radv_amdgpu_bo_va_op(bo->ws, bo->bo, 0, bo->size, bo->base.va,
269 0, AMDGPU_VA_OP_UNMAP);
270 amdgpu_bo_free(bo->bo);
271 }
272 amdgpu_va_range_free(bo->va_handle);
273 FREE(bo);
274 }
275
276 static void radv_amdgpu_add_buffer_to_global_list(struct radv_amdgpu_winsys_bo *bo)
277 {
278 struct radv_amdgpu_winsys *ws = bo->ws;
279
280 if (bo->ws->debug_all_bos) {
281 pthread_mutex_lock(&ws->global_bo_list_lock);
282 LIST_ADDTAIL(&bo->global_list_item, &ws->global_bo_list);
283 ws->num_buffers++;
284 pthread_mutex_unlock(&ws->global_bo_list_lock);
285 }
286 }
287
288 static struct radeon_winsys_bo *
289 radv_amdgpu_winsys_bo_create(struct radeon_winsys *_ws,
290 uint64_t size,
291 unsigned alignment,
292 enum radeon_bo_domain initial_domain,
293 unsigned flags)
294 {
295 struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
296 struct radv_amdgpu_winsys_bo *bo;
297 struct amdgpu_bo_alloc_request request = {0};
298 amdgpu_bo_handle buf_handle;
299 uint64_t va = 0;
300 amdgpu_va_handle va_handle;
301 int r;
302 bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo);
303 if (!bo) {
304 return NULL;
305 }
306
307 unsigned virt_alignment = alignment;
308 if (size >= ws->info.pte_fragment_size)
309 virt_alignment = MAX2(virt_alignment, ws->info.pte_fragment_size);
310
311 r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
312 size, virt_alignment, 0, &va, &va_handle,
313 (flags & RADEON_FLAG_32BIT ? AMDGPU_VA_RANGE_32_BIT : 0) |
314 AMDGPU_VA_RANGE_HIGH);
315 if (r)
316 goto error_va_alloc;
317
318 bo->base.va = va;
319 bo->va_handle = va_handle;
320 bo->size = size;
321 bo->ws = ws;
322 bo->is_virtual = !!(flags & RADEON_FLAG_VIRTUAL);
323 bo->ref_count = 1;
324
325 if (flags & RADEON_FLAG_VIRTUAL) {
326 bo->ranges = realloc(NULL, sizeof(struct radv_amdgpu_map_range));
327 bo->range_count = 1;
328 bo->range_capacity = 1;
329
330 bo->ranges[0].offset = 0;
331 bo->ranges[0].size = size;
332 bo->ranges[0].bo = NULL;
333 bo->ranges[0].bo_offset = 0;
334
335 radv_amdgpu_winsys_virtual_map(bo, bo->ranges);
336 return (struct radeon_winsys_bo *)bo;
337 }
338
339 request.alloc_size = size;
340 request.phys_alignment = alignment;
341
342 if (initial_domain & RADEON_DOMAIN_VRAM)
343 request.preferred_heap |= AMDGPU_GEM_DOMAIN_VRAM;
344 if (initial_domain & RADEON_DOMAIN_GTT)
345 request.preferred_heap |= AMDGPU_GEM_DOMAIN_GTT;
346
347 if (flags & RADEON_FLAG_CPU_ACCESS)
348 request.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
349 if (flags & RADEON_FLAG_NO_CPU_ACCESS)
350 request.flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
351 if (flags & RADEON_FLAG_GTT_WC)
352 request.flags |= AMDGPU_GEM_CREATE_CPU_GTT_USWC;
353 if (!(flags & RADEON_FLAG_IMPLICIT_SYNC) && ws->info.drm_minor >= 22)
354 request.flags |= AMDGPU_GEM_CREATE_EXPLICIT_SYNC;
355 if (flags & RADEON_FLAG_NO_INTERPROCESS_SHARING &&
356 ws->info.has_local_buffers && ws->use_local_bos) {
357 bo->base.is_local = true;
358 request.flags |= AMDGPU_GEM_CREATE_VM_ALWAYS_VALID;
359 }
360
361 /* this won't do anything on pre 4.9 kernels */
362 if (ws->zero_all_vram_allocs && (initial_domain & RADEON_DOMAIN_VRAM))
363 request.flags |= AMDGPU_GEM_CREATE_VRAM_CLEARED;
364 r = amdgpu_bo_alloc(ws->dev, &request, &buf_handle);
365 if (r) {
366 fprintf(stderr, "amdgpu: Failed to allocate a buffer:\n");
367 fprintf(stderr, "amdgpu: size : %"PRIu64" bytes\n", size);
368 fprintf(stderr, "amdgpu: alignment : %u bytes\n", alignment);
369 fprintf(stderr, "amdgpu: domains : %u\n", initial_domain);
370 goto error_bo_alloc;
371 }
372
373 r = radv_amdgpu_bo_va_op(ws, buf_handle, 0, size, va, flags,
374 AMDGPU_VA_OP_MAP);
375 if (r)
376 goto error_va_map;
377
378 bo->bo = buf_handle;
379 bo->initial_domain = initial_domain;
380 bo->is_shared = false;
381 radv_amdgpu_add_buffer_to_global_list(bo);
382 return (struct radeon_winsys_bo *)bo;
383 error_va_map:
384 amdgpu_bo_free(buf_handle);
385
386 error_bo_alloc:
387 amdgpu_va_range_free(va_handle);
388
389 error_va_alloc:
390 FREE(bo);
391 return NULL;
392 }
393
394 static void *
395 radv_amdgpu_winsys_bo_map(struct radeon_winsys_bo *_bo)
396 {
397 struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
398 int ret;
399 void *data;
400 ret = amdgpu_bo_cpu_map(bo->bo, &data);
401 if (ret)
402 return NULL;
403 return data;
404 }
405
406 static void
407 radv_amdgpu_winsys_bo_unmap(struct radeon_winsys_bo *_bo)
408 {
409 struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
410 amdgpu_bo_cpu_unmap(bo->bo);
411 }
412
413 static struct radeon_winsys_bo *
414 radv_amdgpu_winsys_bo_from_ptr(struct radeon_winsys *_ws,
415 void *pointer,
416 uint64_t size)
417 {
418 struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
419 amdgpu_bo_handle buf_handle;
420 struct radv_amdgpu_winsys_bo *bo;
421 uint64_t va;
422 amdgpu_va_handle va_handle;
423
424 bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo);
425 if (!bo)
426 return NULL;
427
428 if (amdgpu_create_bo_from_user_mem(ws->dev, pointer, size, &buf_handle))
429 goto error;
430
431 if (amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
432 size, 1 << 12, 0, &va, &va_handle,
433 AMDGPU_VA_RANGE_HIGH))
434 goto error_va_alloc;
435
436 if (amdgpu_bo_va_op(buf_handle, 0, size, va, 0, AMDGPU_VA_OP_MAP))
437 goto error_va_map;
438
439 /* Initialize it */
440 bo->base.va = va;
441 bo->va_handle = va_handle;
442 bo->size = size;
443 bo->ref_count = 1;
444 bo->ws = ws;
445 bo->bo = buf_handle;
446 bo->initial_domain = RADEON_DOMAIN_GTT;
447
448 radv_amdgpu_add_buffer_to_global_list(bo);
449 return (struct radeon_winsys_bo *)bo;
450
451 error_va_map:
452 amdgpu_va_range_free(va_handle);
453
454 error_va_alloc:
455 amdgpu_bo_free(buf_handle);
456
457 error:
458 FREE(bo);
459 return NULL;
460 }
461
462 static struct radeon_winsys_bo *
463 radv_amdgpu_winsys_bo_from_fd(struct radeon_winsys *_ws,
464 int fd, unsigned *stride,
465 unsigned *offset)
466 {
467 struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
468 struct radv_amdgpu_winsys_bo *bo;
469 uint64_t va;
470 amdgpu_va_handle va_handle;
471 enum amdgpu_bo_handle_type type = amdgpu_bo_handle_type_dma_buf_fd;
472 struct amdgpu_bo_import_result result = {0};
473 struct amdgpu_bo_info info = {0};
474 enum radeon_bo_domain initial = 0;
475 int r;
476 bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo);
477 if (!bo)
478 return NULL;
479
480 r = amdgpu_bo_import(ws->dev, type, fd, &result);
481 if (r)
482 goto error;
483
484 r = amdgpu_bo_query_info(result.buf_handle, &info);
485 if (r)
486 goto error_query;
487
488 r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
489 result.alloc_size, 1 << 20, 0, &va, &va_handle,
490 AMDGPU_VA_RANGE_HIGH);
491 if (r)
492 goto error_query;
493
494 r = radv_amdgpu_bo_va_op(ws, result.buf_handle, 0, result.alloc_size,
495 va, 0, AMDGPU_VA_OP_MAP);
496 if (r)
497 goto error_va_map;
498
499 if (info.preferred_heap & AMDGPU_GEM_DOMAIN_VRAM)
500 initial |= RADEON_DOMAIN_VRAM;
501 if (info.preferred_heap & AMDGPU_GEM_DOMAIN_GTT)
502 initial |= RADEON_DOMAIN_GTT;
503
504 bo->bo = result.buf_handle;
505 bo->base.va = va;
506 bo->va_handle = va_handle;
507 bo->initial_domain = initial;
508 bo->size = result.alloc_size;
509 bo->is_shared = true;
510 bo->ws = ws;
511 bo->ref_count = 1;
512 radv_amdgpu_add_buffer_to_global_list(bo);
513 return (struct radeon_winsys_bo *)bo;
514 error_va_map:
515 amdgpu_va_range_free(va_handle);
516
517 error_query:
518 amdgpu_bo_free(result.buf_handle);
519
520 error:
521 FREE(bo);
522 return NULL;
523 }
524
525 static bool
526 radv_amdgpu_winsys_get_fd(struct radeon_winsys *_ws,
527 struct radeon_winsys_bo *_bo,
528 int *fd)
529 {
530 struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
531 enum amdgpu_bo_handle_type type = amdgpu_bo_handle_type_dma_buf_fd;
532 int r;
533 unsigned handle;
534 r = amdgpu_bo_export(bo->bo, type, &handle);
535 if (r)
536 return false;
537
538 *fd = (int)handle;
539 bo->is_shared = true;
540 return true;
541 }
542
543 static unsigned eg_tile_split(unsigned tile_split)
544 {
545 switch (tile_split) {
546 case 0: tile_split = 64; break;
547 case 1: tile_split = 128; break;
548 case 2: tile_split = 256; break;
549 case 3: tile_split = 512; break;
550 default:
551 case 4: tile_split = 1024; break;
552 case 5: tile_split = 2048; break;
553 case 6: tile_split = 4096; break;
554 }
555 return tile_split;
556 }
557
558 static unsigned radv_eg_tile_split_rev(unsigned eg_tile_split)
559 {
560 switch (eg_tile_split) {
561 case 64: return 0;
562 case 128: return 1;
563 case 256: return 2;
564 case 512: return 3;
565 default:
566 case 1024: return 4;
567 case 2048: return 5;
568 case 4096: return 6;
569 }
570 }
571
572 static void
573 radv_amdgpu_winsys_bo_set_metadata(struct radeon_winsys_bo *_bo,
574 struct radeon_bo_metadata *md)
575 {
576 struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
577 struct amdgpu_bo_metadata metadata = {0};
578 uint32_t tiling_flags = 0;
579
580 if (bo->ws->info.chip_class >= GFX9) {
581 tiling_flags |= AMDGPU_TILING_SET(SWIZZLE_MODE, md->u.gfx9.swizzle_mode);
582 } else {
583 if (md->u.legacy.macrotile == RADEON_LAYOUT_TILED)
584 tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 4); /* 2D_TILED_THIN1 */
585 else if (md->u.legacy.microtile == RADEON_LAYOUT_TILED)
586 tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 2); /* 1D_TILED_THIN1 */
587 else
588 tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 1); /* LINEAR_ALIGNED */
589
590 tiling_flags |= AMDGPU_TILING_SET(PIPE_CONFIG, md->u.legacy.pipe_config);
591 tiling_flags |= AMDGPU_TILING_SET(BANK_WIDTH, util_logbase2(md->u.legacy.bankw));
592 tiling_flags |= AMDGPU_TILING_SET(BANK_HEIGHT, util_logbase2(md->u.legacy.bankh));
593 if (md->u.legacy.tile_split)
594 tiling_flags |= AMDGPU_TILING_SET(TILE_SPLIT, radv_eg_tile_split_rev(md->u.legacy.tile_split));
595 tiling_flags |= AMDGPU_TILING_SET(MACRO_TILE_ASPECT, util_logbase2(md->u.legacy.mtilea));
596 tiling_flags |= AMDGPU_TILING_SET(NUM_BANKS, util_logbase2(md->u.legacy.num_banks)-1);
597
598 if (md->u.legacy.scanout)
599 tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 0); /* DISPLAY_MICRO_TILING */
600 else
601 tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 1); /* THIN_MICRO_TILING */
602 }
603
604 metadata.tiling_info = tiling_flags;
605 metadata.size_metadata = md->size_metadata;
606 memcpy(metadata.umd_metadata, md->metadata, sizeof(md->metadata));
607
608 amdgpu_bo_set_metadata(bo->bo, &metadata);
609 }
610
611 static void
612 radv_amdgpu_winsys_bo_get_metadata(struct radeon_winsys_bo *_bo,
613 struct radeon_bo_metadata *md)
614 {
615 struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
616 struct amdgpu_bo_info info = {0};
617
618 int r = amdgpu_bo_query_info(bo->bo, &info);
619 if (r)
620 return;
621
622 uint64_t tiling_flags = info.metadata.tiling_info;
623
624 if (bo->ws->info.chip_class >= GFX9) {
625 md->u.gfx9.swizzle_mode = AMDGPU_TILING_GET(tiling_flags, SWIZZLE_MODE);
626 } else {
627 md->u.legacy.microtile = RADEON_LAYOUT_LINEAR;
628 md->u.legacy.macrotile = RADEON_LAYOUT_LINEAR;
629
630 if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == 4) /* 2D_TILED_THIN1 */
631 md->u.legacy.macrotile = RADEON_LAYOUT_TILED;
632 else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == 2) /* 1D_TILED_THIN1 */
633 md->u.legacy.microtile = RADEON_LAYOUT_TILED;
634
635 md->u.legacy.pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
636 md->u.legacy.bankw = 1 << AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
637 md->u.legacy.bankh = 1 << AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
638 md->u.legacy.tile_split = eg_tile_split(AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT));
639 md->u.legacy.mtilea = 1 << AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
640 md->u.legacy.num_banks = 2 << AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
641 md->u.legacy.scanout = AMDGPU_TILING_GET(tiling_flags, MICRO_TILE_MODE) == 0; /* DISPLAY */
642 }
643
644 md->size_metadata = info.metadata.size_metadata;
645 memcpy(md->metadata, info.metadata.umd_metadata, sizeof(md->metadata));
646 }
647
648 void radv_amdgpu_bo_init_functions(struct radv_amdgpu_winsys *ws)
649 {
650 ws->base.buffer_create = radv_amdgpu_winsys_bo_create;
651 ws->base.buffer_destroy = radv_amdgpu_winsys_bo_destroy;
652 ws->base.buffer_map = radv_amdgpu_winsys_bo_map;
653 ws->base.buffer_unmap = radv_amdgpu_winsys_bo_unmap;
654 ws->base.buffer_from_ptr = radv_amdgpu_winsys_bo_from_ptr;
655 ws->base.buffer_from_fd = radv_amdgpu_winsys_bo_from_fd;
656 ws->base.buffer_get_fd = radv_amdgpu_winsys_get_fd;
657 ws->base.buffer_set_metadata = radv_amdgpu_winsys_bo_set_metadata;
658 ws->base.buffer_get_metadata = radv_amdgpu_winsys_bo_get_metadata;
659 ws->base.buffer_virtual_bind = radv_amdgpu_winsys_bo_virtual_bind;
660 }