gallium/radeon/winsyses: boolean -> bool, TRUE -> true, FALSE -> false
[mesa.git] / src / gallium / winsys / amdgpu / drm / amdgpu_bo.c
1 /*
2 * Copyright © 2011 Marek Olšák <maraeo@gmail.com>
3 * Copyright © 2015 Advanced Micro Devices, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
16 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
18 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
22 *
23 * The above copyright notice and this permission notice (including the
24 * next paragraph) shall be included in all copies or substantial portions
25 * of the Software.
26 */
27 /*
28 * Authors:
29 * Marek Olšák <maraeo@gmail.com>
30 */
31
32 #include "amdgpu_cs.h"
33
34 #include "os/os_time.h"
35 #include "state_tracker/drm_driver.h"
36 #include <amdgpu_drm.h>
37 #include <xf86drm.h>
38 #include <stdio.h>
39 #include <inttypes.h>
40
41 static bool amdgpu_bo_wait(struct pb_buffer *_buf, uint64_t timeout,
42 enum radeon_bo_usage usage)
43 {
44 struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(_buf);
45 struct amdgpu_winsys *ws = bo->ws;
46 int64_t abs_timeout;
47 int i;
48
49 if (timeout == 0) {
50 if (p_atomic_read(&bo->num_active_ioctls))
51 return false;
52
53 } else {
54 abs_timeout = os_time_get_absolute_timeout(timeout);
55
56 /* Wait if any ioctl is being submitted with this buffer. */
57 if (!os_wait_until_zero_abs_timeout(&bo->num_active_ioctls, abs_timeout))
58 return false;
59 }
60
61 if (bo->is_shared) {
62 /* We can't use user fences for shared buffers, because user fences
63 * are local to this process only. If we want to wait for all buffer
64 * uses in all processes, we have to use amdgpu_bo_wait_for_idle.
65 */
66 bool buffer_busy = true;
67 int r;
68
69 r = amdgpu_bo_wait_for_idle(bo->bo, timeout, &buffer_busy);
70 if (r)
71 fprintf(stderr, "%s: amdgpu_bo_wait_for_idle failed %i\n", __func__,
72 r);
73 return !buffer_busy;
74 }
75
76 if (timeout == 0) {
77 pipe_mutex_lock(ws->bo_fence_lock);
78 for (i = 0; i < RING_LAST; i++)
79 if (bo->fence[i]) {
80 if (amdgpu_fence_wait(bo->fence[i], 0, false)) {
81 /* Release the idle fence to avoid checking it again later. */
82 amdgpu_fence_reference(&bo->fence[i], NULL);
83 } else {
84 pipe_mutex_unlock(ws->bo_fence_lock);
85 return false;
86 }
87 }
88 pipe_mutex_unlock(ws->bo_fence_lock);
89 return true;
90
91 } else {
92 struct pipe_fence_handle *fence[RING_LAST] = {};
93 bool fence_idle[RING_LAST] = {};
94 bool buffer_idle = true;
95
96 /* Take references to all fences, so that we can wait for them
97 * without the lock. */
98 pipe_mutex_lock(ws->bo_fence_lock);
99 for (i = 0; i < RING_LAST; i++)
100 amdgpu_fence_reference(&fence[i], bo->fence[i]);
101 pipe_mutex_unlock(ws->bo_fence_lock);
102
103 /* Now wait for the fences. */
104 for (i = 0; i < RING_LAST; i++) {
105 if (fence[i]) {
106 if (amdgpu_fence_wait(fence[i], abs_timeout, true))
107 fence_idle[i] = true;
108 else
109 buffer_idle = false;
110 }
111 }
112
113 /* Release idle fences to avoid checking them again later. */
114 pipe_mutex_lock(ws->bo_fence_lock);
115 for (i = 0; i < RING_LAST; i++) {
116 if (fence[i] == bo->fence[i] && fence_idle[i])
117 amdgpu_fence_reference(&bo->fence[i], NULL);
118
119 amdgpu_fence_reference(&fence[i], NULL);
120 }
121 pipe_mutex_unlock(ws->bo_fence_lock);
122
123 return buffer_idle;
124 }
125 }
126
127 static enum radeon_bo_domain amdgpu_bo_get_initial_domain(
128 struct pb_buffer *buf)
129 {
130 return ((struct amdgpu_winsys_bo*)buf)->initial_domain;
131 }
132
133 void amdgpu_bo_destroy(struct pb_buffer *_buf)
134 {
135 struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(_buf);
136 int i;
137
138 pipe_mutex_lock(bo->ws->global_bo_list_lock);
139 LIST_DEL(&bo->global_list_item);
140 bo->ws->num_buffers--;
141 pipe_mutex_unlock(bo->ws->global_bo_list_lock);
142
143 amdgpu_bo_va_op(bo->bo, 0, bo->base.size, bo->va, 0, AMDGPU_VA_OP_UNMAP);
144 amdgpu_va_range_free(bo->va_handle);
145 amdgpu_bo_free(bo->bo);
146
147 for (i = 0; i < RING_LAST; i++)
148 amdgpu_fence_reference(&bo->fence[i], NULL);
149
150 if (bo->initial_domain & RADEON_DOMAIN_VRAM)
151 bo->ws->allocated_vram -= align64(bo->base.size, bo->ws->info.gart_page_size);
152 else if (bo->initial_domain & RADEON_DOMAIN_GTT)
153 bo->ws->allocated_gtt -= align64(bo->base.size, bo->ws->info.gart_page_size);
154 FREE(bo);
155 }
156
157 static void amdgpu_bo_destroy_or_cache(struct pb_buffer *_buf)
158 {
159 struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(_buf);
160
161 if (bo->use_reusable_pool)
162 pb_cache_add_buffer(&bo->cache_entry);
163 else
164 amdgpu_bo_destroy(_buf);
165 }
166
167 static void *amdgpu_bo_map(struct pb_buffer *buf,
168 struct radeon_winsys_cs *rcs,
169 enum pipe_transfer_usage usage)
170 {
171 struct amdgpu_winsys_bo *bo = (struct amdgpu_winsys_bo*)buf;
172 struct amdgpu_cs *cs = (struct amdgpu_cs*)rcs;
173 int r;
174 void *cpu = NULL;
175
176 /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */
177 if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
178 /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */
179 if (usage & PIPE_TRANSFER_DONTBLOCK) {
180 if (!(usage & PIPE_TRANSFER_WRITE)) {
181 /* Mapping for read.
182 *
183 * Since we are mapping for read, we don't need to wait
184 * if the GPU is using the buffer for read too
185 * (neither one is changing it).
186 *
187 * Only check whether the buffer is being used for write. */
188 if (cs && amdgpu_bo_is_referenced_by_cs_with_usage(cs, bo,
189 RADEON_USAGE_WRITE)) {
190 cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC, NULL);
191 return NULL;
192 }
193
194 if (!amdgpu_bo_wait((struct pb_buffer*)bo, 0,
195 RADEON_USAGE_WRITE)) {
196 return NULL;
197 }
198 } else {
199 if (cs && amdgpu_bo_is_referenced_by_cs(cs, bo)) {
200 cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC, NULL);
201 return NULL;
202 }
203
204 if (!amdgpu_bo_wait((struct pb_buffer*)bo, 0,
205 RADEON_USAGE_READWRITE)) {
206 return NULL;
207 }
208 }
209 } else {
210 uint64_t time = os_time_get_nano();
211
212 if (!(usage & PIPE_TRANSFER_WRITE)) {
213 /* Mapping for read.
214 *
215 * Since we are mapping for read, we don't need to wait
216 * if the GPU is using the buffer for read too
217 * (neither one is changing it).
218 *
219 * Only check whether the buffer is being used for write. */
220 if (cs && amdgpu_bo_is_referenced_by_cs_with_usage(cs, bo,
221 RADEON_USAGE_WRITE)) {
222 cs->flush_cs(cs->flush_data, 0, NULL);
223 } else {
224 /* Try to avoid busy-waiting in amdgpu_bo_wait. */
225 if (p_atomic_read(&bo->num_active_ioctls))
226 amdgpu_cs_sync_flush(rcs);
227 }
228 amdgpu_bo_wait((struct pb_buffer*)bo, PIPE_TIMEOUT_INFINITE,
229 RADEON_USAGE_WRITE);
230 } else {
231 /* Mapping for write. */
232 if (cs) {
233 if (amdgpu_bo_is_referenced_by_cs(cs, bo)) {
234 cs->flush_cs(cs->flush_data, 0, NULL);
235 } else {
236 /* Try to avoid busy-waiting in amdgpu_bo_wait. */
237 if (p_atomic_read(&bo->num_active_ioctls))
238 amdgpu_cs_sync_flush(rcs);
239 }
240 }
241
242 amdgpu_bo_wait((struct pb_buffer*)bo, PIPE_TIMEOUT_INFINITE,
243 RADEON_USAGE_READWRITE);
244 }
245
246 bo->ws->buffer_wait_time += os_time_get_nano() - time;
247 }
248 }
249
250 /* If the buffer is created from user memory, return the user pointer. */
251 if (bo->user_ptr)
252 return bo->user_ptr;
253
254 r = amdgpu_bo_cpu_map(bo->bo, &cpu);
255 if (r) {
256 /* Clear the cache and try again. */
257 pb_cache_release_all_buffers(&bo->ws->bo_cache);
258 r = amdgpu_bo_cpu_map(bo->bo, &cpu);
259 }
260 return r ? NULL : cpu;
261 }
262
263 static void amdgpu_bo_unmap(struct pb_buffer *buf)
264 {
265 struct amdgpu_winsys_bo *bo = (struct amdgpu_winsys_bo*)buf;
266
267 amdgpu_bo_cpu_unmap(bo->bo);
268 }
269
270 static const struct pb_vtbl amdgpu_winsys_bo_vtbl = {
271 amdgpu_bo_destroy_or_cache
272 /* other functions are never called */
273 };
274
275 static void amdgpu_add_buffer_to_global_list(struct amdgpu_winsys_bo *bo)
276 {
277 struct amdgpu_winsys *ws = bo->ws;
278
279 pipe_mutex_lock(ws->global_bo_list_lock);
280 LIST_ADDTAIL(&bo->global_list_item, &ws->global_bo_list);
281 ws->num_buffers++;
282 pipe_mutex_unlock(ws->global_bo_list_lock);
283 }
284
285 static struct amdgpu_winsys_bo *amdgpu_create_bo(struct amdgpu_winsys *ws,
286 uint64_t size,
287 unsigned alignment,
288 unsigned usage,
289 enum radeon_bo_domain initial_domain,
290 unsigned flags)
291 {
292 struct amdgpu_bo_alloc_request request = {0};
293 amdgpu_bo_handle buf_handle;
294 uint64_t va = 0;
295 struct amdgpu_winsys_bo *bo;
296 amdgpu_va_handle va_handle;
297 unsigned va_gap_size;
298 int r;
299
300 assert(initial_domain & RADEON_DOMAIN_VRAM_GTT);
301 bo = CALLOC_STRUCT(amdgpu_winsys_bo);
302 if (!bo) {
303 return NULL;
304 }
305
306 pb_cache_init_entry(&ws->bo_cache, &bo->cache_entry, &bo->base);
307 request.alloc_size = size;
308 request.phys_alignment = alignment;
309
310 if (initial_domain & RADEON_DOMAIN_VRAM)
311 request.preferred_heap |= AMDGPU_GEM_DOMAIN_VRAM;
312 if (initial_domain & RADEON_DOMAIN_GTT)
313 request.preferred_heap |= AMDGPU_GEM_DOMAIN_GTT;
314
315 if (flags & RADEON_FLAG_CPU_ACCESS)
316 request.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
317 if (flags & RADEON_FLAG_NO_CPU_ACCESS)
318 request.flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
319 if (flags & RADEON_FLAG_GTT_WC)
320 request.flags |= AMDGPU_GEM_CREATE_CPU_GTT_USWC;
321
322 r = amdgpu_bo_alloc(ws->dev, &request, &buf_handle);
323 if (r) {
324 fprintf(stderr, "amdgpu: Failed to allocate a buffer:\n");
325 fprintf(stderr, "amdgpu: size : %"PRIu64" bytes\n", size);
326 fprintf(stderr, "amdgpu: alignment : %u bytes\n", alignment);
327 fprintf(stderr, "amdgpu: domains : %u\n", initial_domain);
328 goto error_bo_alloc;
329 }
330
331 va_gap_size = ws->check_vm ? MAX2(4 * alignment, 64 * 1024) : 0;
332 r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
333 size + va_gap_size, alignment, 0, &va, &va_handle, 0);
334 if (r)
335 goto error_va_alloc;
336
337 r = amdgpu_bo_va_op(buf_handle, 0, size, va, 0, AMDGPU_VA_OP_MAP);
338 if (r)
339 goto error_va_map;
340
341 pipe_reference_init(&bo->base.reference, 1);
342 bo->base.alignment = alignment;
343 bo->base.usage = usage;
344 bo->base.size = size;
345 bo->base.vtbl = &amdgpu_winsys_bo_vtbl;
346 bo->ws = ws;
347 bo->bo = buf_handle;
348 bo->va = va;
349 bo->va_handle = va_handle;
350 bo->initial_domain = initial_domain;
351 bo->unique_id = __sync_fetch_and_add(&ws->next_bo_unique_id, 1);
352
353 if (initial_domain & RADEON_DOMAIN_VRAM)
354 ws->allocated_vram += align64(size, ws->info.gart_page_size);
355 else if (initial_domain & RADEON_DOMAIN_GTT)
356 ws->allocated_gtt += align64(size, ws->info.gart_page_size);
357
358 amdgpu_add_buffer_to_global_list(bo);
359
360 return bo;
361
362 error_va_map:
363 amdgpu_va_range_free(va_handle);
364
365 error_va_alloc:
366 amdgpu_bo_free(buf_handle);
367
368 error_bo_alloc:
369 FREE(bo);
370 return NULL;
371 }
372
373 bool amdgpu_bo_can_reclaim(struct pb_buffer *_buf)
374 {
375 struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(_buf);
376
377 if (amdgpu_bo_is_referenced_by_any_cs(bo)) {
378 return false;
379 }
380
381 return amdgpu_bo_wait(_buf, 0, RADEON_USAGE_READWRITE);
382 }
383
384 static unsigned eg_tile_split(unsigned tile_split)
385 {
386 switch (tile_split) {
387 case 0: tile_split = 64; break;
388 case 1: tile_split = 128; break;
389 case 2: tile_split = 256; break;
390 case 3: tile_split = 512; break;
391 default:
392 case 4: tile_split = 1024; break;
393 case 5: tile_split = 2048; break;
394 case 6: tile_split = 4096; break;
395 }
396 return tile_split;
397 }
398
399 static unsigned eg_tile_split_rev(unsigned eg_tile_split)
400 {
401 switch (eg_tile_split) {
402 case 64: return 0;
403 case 128: return 1;
404 case 256: return 2;
405 case 512: return 3;
406 default:
407 case 1024: return 4;
408 case 2048: return 5;
409 case 4096: return 6;
410 }
411 }
412
413 static void amdgpu_buffer_get_metadata(struct pb_buffer *_buf,
414 struct radeon_bo_metadata *md)
415 {
416 struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(_buf);
417 struct amdgpu_bo_info info = {0};
418 uint32_t tiling_flags;
419 int r;
420
421 r = amdgpu_bo_query_info(bo->bo, &info);
422 if (r)
423 return;
424
425 tiling_flags = info.metadata.tiling_info;
426
427 md->microtile = RADEON_LAYOUT_LINEAR;
428 md->macrotile = RADEON_LAYOUT_LINEAR;
429
430 if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == 4) /* 2D_TILED_THIN1 */
431 md->macrotile = RADEON_LAYOUT_TILED;
432 else if (AMDGPU_TILING_GET(tiling_flags, ARRAY_MODE) == 2) /* 1D_TILED_THIN1 */
433 md->microtile = RADEON_LAYOUT_TILED;
434
435 md->pipe_config = AMDGPU_TILING_GET(tiling_flags, PIPE_CONFIG);
436 md->bankw = 1 << AMDGPU_TILING_GET(tiling_flags, BANK_WIDTH);
437 md->bankh = 1 << AMDGPU_TILING_GET(tiling_flags, BANK_HEIGHT);
438 md->tile_split = eg_tile_split(AMDGPU_TILING_GET(tiling_flags, TILE_SPLIT));
439 md->mtilea = 1 << AMDGPU_TILING_GET(tiling_flags, MACRO_TILE_ASPECT);
440 md->num_banks = 2 << AMDGPU_TILING_GET(tiling_flags, NUM_BANKS);
441 md->scanout = AMDGPU_TILING_GET(tiling_flags, MICRO_TILE_MODE) == 0; /* DISPLAY */
442
443 md->size_metadata = info.metadata.size_metadata;
444 memcpy(md->metadata, info.metadata.umd_metadata, sizeof(md->metadata));
445 }
446
447 static void amdgpu_buffer_set_metadata(struct pb_buffer *_buf,
448 struct radeon_bo_metadata *md)
449 {
450 struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(_buf);
451 struct amdgpu_bo_metadata metadata = {0};
452 uint32_t tiling_flags = 0;
453
454 if (md->macrotile == RADEON_LAYOUT_TILED)
455 tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 4); /* 2D_TILED_THIN1 */
456 else if (md->microtile == RADEON_LAYOUT_TILED)
457 tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 2); /* 1D_TILED_THIN1 */
458 else
459 tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 1); /* LINEAR_ALIGNED */
460
461 tiling_flags |= AMDGPU_TILING_SET(PIPE_CONFIG, md->pipe_config);
462 tiling_flags |= AMDGPU_TILING_SET(BANK_WIDTH, util_logbase2(md->bankw));
463 tiling_flags |= AMDGPU_TILING_SET(BANK_HEIGHT, util_logbase2(md->bankh));
464 if (md->tile_split)
465 tiling_flags |= AMDGPU_TILING_SET(TILE_SPLIT, eg_tile_split_rev(md->tile_split));
466 tiling_flags |= AMDGPU_TILING_SET(MACRO_TILE_ASPECT, util_logbase2(md->mtilea));
467 tiling_flags |= AMDGPU_TILING_SET(NUM_BANKS, util_logbase2(md->num_banks)-1);
468
469 if (md->scanout)
470 tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 0); /* DISPLAY_MICRO_TILING */
471 else
472 tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 1); /* THIN_MICRO_TILING */
473
474 metadata.tiling_info = tiling_flags;
475 metadata.size_metadata = md->size_metadata;
476 memcpy(metadata.umd_metadata, md->metadata, sizeof(md->metadata));
477
478 amdgpu_bo_set_metadata(bo->bo, &metadata);
479 }
480
481 static struct pb_buffer *
482 amdgpu_bo_create(struct radeon_winsys *rws,
483 uint64_t size,
484 unsigned alignment,
485 enum radeon_bo_domain domain,
486 enum radeon_bo_flag flags)
487 {
488 struct amdgpu_winsys *ws = amdgpu_winsys(rws);
489 struct amdgpu_winsys_bo *bo;
490 unsigned usage = 0;
491
492 /* Align size to page size. This is the minimum alignment for normal
493 * BOs. Aligning this here helps the cached bufmgr. Especially small BOs,
494 * like constant/uniform buffers, can benefit from better and more reuse.
495 */
496 size = align64(size, ws->info.gart_page_size);
497 alignment = align(alignment, ws->info.gart_page_size);
498
499 /* Only set one usage bit each for domains and flags, or the cache manager
500 * might consider different sets of domains / flags compatible
501 */
502 if (domain == RADEON_DOMAIN_VRAM_GTT)
503 usage = 1 << 2;
504 else
505 usage = domain >> 1;
506 assert(flags < sizeof(usage) * 8 - 3);
507 usage |= 1 << (flags + 3);
508
509 /* Get a buffer from the cache. */
510 bo = (struct amdgpu_winsys_bo*)
511 pb_cache_reclaim_buffer(&ws->bo_cache, size, alignment, usage);
512 if (bo)
513 return &bo->base;
514
515 /* Create a new one. */
516 bo = amdgpu_create_bo(ws, size, alignment, usage, domain, flags);
517 if (!bo) {
518 /* Clear the cache and try again. */
519 pb_cache_release_all_buffers(&ws->bo_cache);
520 bo = amdgpu_create_bo(ws, size, alignment, usage, domain, flags);
521 if (!bo)
522 return NULL;
523 }
524
525 bo->use_reusable_pool = true;
526 return &bo->base;
527 }
528
529 static struct pb_buffer *amdgpu_bo_from_handle(struct radeon_winsys *rws,
530 struct winsys_handle *whandle,
531 unsigned *stride,
532 unsigned *offset)
533 {
534 struct amdgpu_winsys *ws = amdgpu_winsys(rws);
535 struct amdgpu_winsys_bo *bo;
536 enum amdgpu_bo_handle_type type;
537 struct amdgpu_bo_import_result result = {0};
538 uint64_t va;
539 amdgpu_va_handle va_handle;
540 struct amdgpu_bo_info info = {0};
541 enum radeon_bo_domain initial = 0;
542 int r;
543
544 /* Initialize the structure. */
545 bo = CALLOC_STRUCT(amdgpu_winsys_bo);
546 if (!bo) {
547 return NULL;
548 }
549
550 switch (whandle->type) {
551 case DRM_API_HANDLE_TYPE_SHARED:
552 type = amdgpu_bo_handle_type_gem_flink_name;
553 break;
554 case DRM_API_HANDLE_TYPE_FD:
555 type = amdgpu_bo_handle_type_dma_buf_fd;
556 break;
557 default:
558 return NULL;
559 }
560
561 r = amdgpu_bo_import(ws->dev, type, whandle->handle, &result);
562 if (r)
563 goto error;
564
565 /* Get initial domains. */
566 r = amdgpu_bo_query_info(result.buf_handle, &info);
567 if (r)
568 goto error_query;
569
570 r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
571 result.alloc_size, 1 << 20, 0, &va, &va_handle, 0);
572 if (r)
573 goto error_query;
574
575 r = amdgpu_bo_va_op(result.buf_handle, 0, result.alloc_size, va, 0, AMDGPU_VA_OP_MAP);
576 if (r)
577 goto error_va_map;
578
579 if (info.preferred_heap & AMDGPU_GEM_DOMAIN_VRAM)
580 initial |= RADEON_DOMAIN_VRAM;
581 if (info.preferred_heap & AMDGPU_GEM_DOMAIN_GTT)
582 initial |= RADEON_DOMAIN_GTT;
583
584
585 pipe_reference_init(&bo->base.reference, 1);
586 bo->base.alignment = info.phys_alignment;
587 bo->bo = result.buf_handle;
588 bo->base.size = result.alloc_size;
589 bo->base.vtbl = &amdgpu_winsys_bo_vtbl;
590 bo->ws = ws;
591 bo->va = va;
592 bo->va_handle = va_handle;
593 bo->initial_domain = initial;
594 bo->unique_id = __sync_fetch_and_add(&ws->next_bo_unique_id, 1);
595 bo->is_shared = true;
596
597 if (stride)
598 *stride = whandle->stride;
599 if (offset)
600 *offset = whandle->offset;
601
602 if (bo->initial_domain & RADEON_DOMAIN_VRAM)
603 ws->allocated_vram += align64(bo->base.size, ws->info.gart_page_size);
604 else if (bo->initial_domain & RADEON_DOMAIN_GTT)
605 ws->allocated_gtt += align64(bo->base.size, ws->info.gart_page_size);
606
607 amdgpu_add_buffer_to_global_list(bo);
608
609 return &bo->base;
610
611 error_va_map:
612 amdgpu_va_range_free(va_handle);
613
614 error_query:
615 amdgpu_bo_free(result.buf_handle);
616
617 error:
618 FREE(bo);
619 return NULL;
620 }
621
622 static bool amdgpu_bo_get_handle(struct pb_buffer *buffer,
623 unsigned stride, unsigned offset,
624 unsigned slice_size,
625 struct winsys_handle *whandle)
626 {
627 struct amdgpu_winsys_bo *bo = amdgpu_winsys_bo(buffer);
628 enum amdgpu_bo_handle_type type;
629 int r;
630
631 bo->use_reusable_pool = false;
632
633 switch (whandle->type) {
634 case DRM_API_HANDLE_TYPE_SHARED:
635 type = amdgpu_bo_handle_type_gem_flink_name;
636 break;
637 case DRM_API_HANDLE_TYPE_FD:
638 type = amdgpu_bo_handle_type_dma_buf_fd;
639 break;
640 case DRM_API_HANDLE_TYPE_KMS:
641 type = amdgpu_bo_handle_type_kms;
642 break;
643 default:
644 return false;
645 }
646
647 r = amdgpu_bo_export(bo->bo, type, &whandle->handle);
648 if (r)
649 return false;
650
651 whandle->stride = stride;
652 whandle->offset = offset;
653 whandle->offset += slice_size * whandle->layer;
654 bo->is_shared = true;
655 return true;
656 }
657
658 static struct pb_buffer *amdgpu_bo_from_ptr(struct radeon_winsys *rws,
659 void *pointer, uint64_t size)
660 {
661 struct amdgpu_winsys *ws = amdgpu_winsys(rws);
662 amdgpu_bo_handle buf_handle;
663 struct amdgpu_winsys_bo *bo;
664 uint64_t va;
665 amdgpu_va_handle va_handle;
666
667 bo = CALLOC_STRUCT(amdgpu_winsys_bo);
668 if (!bo)
669 return NULL;
670
671 if (amdgpu_create_bo_from_user_mem(ws->dev, pointer, size, &buf_handle))
672 goto error;
673
674 if (amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
675 size, 1 << 12, 0, &va, &va_handle, 0))
676 goto error_va_alloc;
677
678 if (amdgpu_bo_va_op(buf_handle, 0, size, va, 0, AMDGPU_VA_OP_MAP))
679 goto error_va_map;
680
681 /* Initialize it. */
682 pipe_reference_init(&bo->base.reference, 1);
683 bo->bo = buf_handle;
684 bo->base.alignment = 0;
685 bo->base.size = size;
686 bo->base.vtbl = &amdgpu_winsys_bo_vtbl;
687 bo->ws = ws;
688 bo->user_ptr = pointer;
689 bo->va = va;
690 bo->va_handle = va_handle;
691 bo->initial_domain = RADEON_DOMAIN_GTT;
692 bo->unique_id = __sync_fetch_and_add(&ws->next_bo_unique_id, 1);
693
694 ws->allocated_gtt += align64(bo->base.size, ws->info.gart_page_size);
695
696 amdgpu_add_buffer_to_global_list(bo);
697
698 return (struct pb_buffer*)bo;
699
700 error_va_map:
701 amdgpu_va_range_free(va_handle);
702
703 error_va_alloc:
704 amdgpu_bo_free(buf_handle);
705
706 error:
707 FREE(bo);
708 return NULL;
709 }
710
711 static bool amdgpu_bo_is_user_ptr(struct pb_buffer *buf)
712 {
713 return ((struct amdgpu_winsys_bo*)buf)->user_ptr != NULL;
714 }
715
716 static uint64_t amdgpu_bo_get_va(struct pb_buffer *buf)
717 {
718 return ((struct amdgpu_winsys_bo*)buf)->va;
719 }
720
721 void amdgpu_bo_init_functions(struct amdgpu_winsys *ws)
722 {
723 ws->base.buffer_set_metadata = amdgpu_buffer_set_metadata;
724 ws->base.buffer_get_metadata = amdgpu_buffer_get_metadata;
725 ws->base.buffer_map = amdgpu_bo_map;
726 ws->base.buffer_unmap = amdgpu_bo_unmap;
727 ws->base.buffer_wait = amdgpu_bo_wait;
728 ws->base.buffer_create = amdgpu_bo_create;
729 ws->base.buffer_from_handle = amdgpu_bo_from_handle;
730 ws->base.buffer_from_ptr = amdgpu_bo_from_ptr;
731 ws->base.buffer_is_user_ptr = amdgpu_bo_is_user_ptr;
732 ws->base.buffer_get_handle = amdgpu_bo_get_handle;
733 ws->base.buffer_get_virtual_address = amdgpu_bo_get_va;
734 ws->base.buffer_get_initial_domain = amdgpu_bo_get_initial_domain;
735 }