• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
37 #include "util/u_atomic.h"
38 
39 
40 static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo);
41 
42 static int
radv_amdgpu_bo_va_op(struct radv_amdgpu_winsys * ws,amdgpu_bo_handle bo,uint64_t offset,uint64_t size,uint64_t addr,uint32_t bo_flags,uint32_t ops)43 radv_amdgpu_bo_va_op(struct radv_amdgpu_winsys *ws,
44 		     amdgpu_bo_handle bo,
45 		     uint64_t offset,
46 		     uint64_t size,
47 		     uint64_t addr,
48 		     uint32_t bo_flags,
49 		     uint32_t ops)
50 {
51 	uint64_t flags = AMDGPU_VM_PAGE_READABLE |
52 			 AMDGPU_VM_PAGE_EXECUTABLE;
53 
54 	if ((bo_flags & RADEON_FLAG_VA_UNCACHED) && ws->info.chip_class >= GFX9)
55 		flags |= AMDGPU_VM_MTYPE_UC;
56 
57 	if (!(bo_flags & RADEON_FLAG_READ_ONLY))
58 		flags |= AMDGPU_VM_PAGE_WRITEABLE;
59 
60 	size = ALIGN(size, getpagesize());
61 
62 	return amdgpu_bo_va_op_raw(ws->dev, bo, offset, size, addr,
63 				   flags, ops);
64 }
65 
66 static void
radv_amdgpu_winsys_virtual_map(struct radv_amdgpu_winsys_bo * bo,const struct radv_amdgpu_map_range * range)67 radv_amdgpu_winsys_virtual_map(struct radv_amdgpu_winsys_bo *bo,
68                                const struct radv_amdgpu_map_range *range)
69 {
70 	assert(range->size);
71 
72 	if (!range->bo)
73 		return; /* TODO: PRT mapping */
74 
75 	p_atomic_inc(&range->bo->ref_count);
76 	int r = radv_amdgpu_bo_va_op(bo->ws, range->bo->bo, range->bo_offset,
77 				     range->size, range->offset + bo->base.va,
78 				     0, AMDGPU_VA_OP_MAP);
79 	if (r)
80 		abort();
81 }
82 
83 static void
radv_amdgpu_winsys_virtual_unmap(struct radv_amdgpu_winsys_bo * bo,const struct radv_amdgpu_map_range * range)84 radv_amdgpu_winsys_virtual_unmap(struct radv_amdgpu_winsys_bo *bo,
85                                  const struct radv_amdgpu_map_range *range)
86 {
87 	assert(range->size);
88 
89 	if (!range->bo)
90 		return; /* TODO: PRT mapping */
91 
92 	int r = radv_amdgpu_bo_va_op(bo->ws, range->bo->bo, range->bo_offset,
93 				     range->size, range->offset + bo->base.va,
94 				     0, AMDGPU_VA_OP_UNMAP);
95 	if (r)
96 		abort();
97 	radv_amdgpu_winsys_bo_destroy((struct radeon_winsys_bo *)range->bo);
98 }
99 
bo_comparator(const void * ap,const void * bp)100 static int bo_comparator(const void *ap, const void *bp) {
101 	struct radv_amdgpu_bo *a = *(struct radv_amdgpu_bo *const *)ap;
102 	struct radv_amdgpu_bo *b = *(struct radv_amdgpu_bo *const *)bp;
103 	return (a > b) ? 1 : (a < b) ? -1 : 0;
104 }
105 
106 static void
radv_amdgpu_winsys_rebuild_bo_list(struct radv_amdgpu_winsys_bo * bo)107 radv_amdgpu_winsys_rebuild_bo_list(struct radv_amdgpu_winsys_bo *bo)
108 {
109 	if (bo->bo_capacity < bo->range_count) {
110 		uint32_t new_count = MAX2(bo->bo_capacity * 2, bo->range_count);
111 		bo->bos = realloc(bo->bos, new_count * sizeof(struct radv_amdgpu_winsys_bo *));
112 		bo->bo_capacity = new_count;
113 	}
114 
115 	uint32_t temp_bo_count = 0;
116 	for (uint32_t i = 0; i < bo->range_count; ++i)
117 		if (bo->ranges[i].bo)
118 			bo->bos[temp_bo_count++] = bo->ranges[i].bo;
119 
120 	qsort(bo->bos, temp_bo_count, sizeof(struct radv_amdgpu_winsys_bo *), &bo_comparator);
121 
122 	uint32_t final_bo_count = 1;
123 	for (uint32_t i = 1; i < temp_bo_count; ++i)
124 		if (bo->bos[i] != bo->bos[i - 1])
125 			bo->bos[final_bo_count++] = bo->bos[i];
126 
127 	bo->bo_count = final_bo_count;
128 }
129 
130 static void
radv_amdgpu_winsys_bo_virtual_bind(struct radeon_winsys_bo * _parent,uint64_t offset,uint64_t size,struct radeon_winsys_bo * _bo,uint64_t bo_offset)131 radv_amdgpu_winsys_bo_virtual_bind(struct radeon_winsys_bo *_parent,
132                                    uint64_t offset, uint64_t size,
133                                    struct radeon_winsys_bo *_bo, uint64_t bo_offset)
134 {
135 	struct radv_amdgpu_winsys_bo *parent = (struct radv_amdgpu_winsys_bo *)_parent;
136 	struct radv_amdgpu_winsys_bo *bo = (struct radv_amdgpu_winsys_bo*)_bo;
137 	int range_count_delta, new_idx;
138 	int first = 0, last;
139 	struct radv_amdgpu_map_range new_first, new_last;
140 
141 	assert(parent->is_virtual);
142 	assert(!bo || !bo->is_virtual);
143 
144 	if (!size)
145 		return;
146 
147 	/* We have at most 2 new ranges (1 by the bind, and another one by splitting a range that contains the newly bound range). */
148 	if (parent->range_capacity - parent->range_count < 2) {
149 		parent->range_capacity += 2;
150 		parent->ranges = realloc(parent->ranges,
151 		                         parent->range_capacity * sizeof(struct radv_amdgpu_map_range));
152 	}
153 
154 	/*
155 	 * [first, last] is exactly the range of ranges that either overlap the
156 	 * new parent, or are adjacent to it. This corresponds to the bind ranges
157 	 * that may change.
158 	 */
159 	while(first + 1 < parent->range_count && parent->ranges[first].offset + parent->ranges[first].size < offset)
160 		++first;
161 
162 	last = first;
163 	while(last + 1 < parent->range_count && parent->ranges[last].offset <= offset + size)
164 		++last;
165 
166 	/* Whether the first or last range are going to be totally removed or just
167 	 * resized/left alone. Note that in the case of first == last, we will split
168 	 * this into a part before and after the new range. The remove flag is then
169 	 * whether to not create the corresponding split part. */
170 	bool remove_first = parent->ranges[first].offset == offset;
171 	bool remove_last = parent->ranges[last].offset + parent->ranges[last].size == offset + size;
172 	bool unmapped_first = false;
173 
174 	assert(parent->ranges[first].offset <= offset);
175 	assert(parent->ranges[last].offset + parent->ranges[last].size >= offset + size);
176 
177 	/* Try to merge the new range with the first range. */
178 	if (parent->ranges[first].bo == bo && (!bo || offset - bo_offset == parent->ranges[first].offset - parent->ranges[first].bo_offset)) {
179 		size += offset - parent->ranges[first].offset;
180 		offset = parent->ranges[first].offset;
181 		bo_offset = parent->ranges[first].bo_offset;
182 		remove_first = true;
183 	}
184 
185 	/* Try to merge the new range with the last range. */
186 	if (parent->ranges[last].bo == bo && (!bo || offset - bo_offset == parent->ranges[last].offset - parent->ranges[last].bo_offset)) {
187 		size = parent->ranges[last].offset + parent->ranges[last].size - offset;
188 		remove_last = true;
189 	}
190 
191 	range_count_delta = 1 - (last - first + 1) + !remove_first + !remove_last;
192 	new_idx = first + !remove_first;
193 
194 	/* Any range between first and last is going to be entirely covered by the new range so just unmap them. */
195 	for (int i = first + 1; i < last; ++i)
196 		radv_amdgpu_winsys_virtual_unmap(parent, parent->ranges + i);
197 
198 	/* If the first/last range are not left alone we unmap then and optionally map
199 	 * them again after modifications. Not that this implicitly can do the splitting
200 	 * if first == last. */
201 	new_first = parent->ranges[first];
202 	new_last = parent->ranges[last];
203 
204 	if (parent->ranges[first].offset + parent->ranges[first].size > offset || remove_first) {
205 		radv_amdgpu_winsys_virtual_unmap(parent, parent->ranges + first);
206 		unmapped_first = true;
207 
208 		if (!remove_first) {
209 			new_first.size = offset - new_first.offset;
210 			radv_amdgpu_winsys_virtual_map(parent, &new_first);
211 		}
212 	}
213 
214 	if (parent->ranges[last].offset < offset + size || remove_last) {
215 		if (first != last || !unmapped_first)
216 			radv_amdgpu_winsys_virtual_unmap(parent, parent->ranges + last);
217 
218 		if (!remove_last) {
219 			new_last.size -= offset + size - new_last.offset;
220 			new_last.offset = offset + size;
221 			radv_amdgpu_winsys_virtual_map(parent, &new_last);
222 		}
223 	}
224 
225 	/* Moves the range list after last to account for the changed number of ranges. */
226 	memmove(parent->ranges + last + 1 + range_count_delta, parent->ranges + last + 1,
227 	        sizeof(struct radv_amdgpu_map_range) * (parent->range_count - last - 1));
228 
229 	if (!remove_first)
230 		parent->ranges[first] = new_first;
231 
232 	if (!remove_last)
233 		parent->ranges[new_idx + 1] = new_last;
234 
235 	/* Actually set up the new range. */
236 	parent->ranges[new_idx].offset = offset;
237 	parent->ranges[new_idx].size = size;
238 	parent->ranges[new_idx].bo = bo;
239 	parent->ranges[new_idx].bo_offset = bo_offset;
240 
241 	radv_amdgpu_winsys_virtual_map(parent, parent->ranges + new_idx);
242 
243 	parent->range_count += range_count_delta;
244 
245 	radv_amdgpu_winsys_rebuild_bo_list(parent);
246 }
247 
radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo * _bo)248 static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo)
249 {
250 	struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
251 
252 	if (p_atomic_dec_return(&bo->ref_count))
253 		return;
254 	if (bo->is_virtual) {
255 		for (uint32_t i = 0; i < bo->range_count; ++i) {
256 			radv_amdgpu_winsys_virtual_unmap(bo, bo->ranges + i);
257 		}
258 		free(bo->bos);
259 		free(bo->ranges);
260 	} else {
261 		if (bo->ws->debug_all_bos) {
262 			pthread_mutex_lock(&bo->ws->global_bo_list_lock);
263 			LIST_DEL(&bo->global_list_item);
264 			bo->ws->num_buffers--;
265 			pthread_mutex_unlock(&bo->ws->global_bo_list_lock);
266 		}
267 		radv_amdgpu_bo_va_op(bo->ws, bo->bo, 0, bo->size, bo->base.va,
268 				     0, AMDGPU_VA_OP_UNMAP);
269 		amdgpu_bo_free(bo->bo);
270 	}
271 	amdgpu_va_range_free(bo->va_handle);
272 	FREE(bo);
273 }
274 
radv_amdgpu_add_buffer_to_global_list(struct radv_amdgpu_winsys_bo * bo)275 static void radv_amdgpu_add_buffer_to_global_list(struct radv_amdgpu_winsys_bo *bo)
276 {
277 	struct radv_amdgpu_winsys *ws = bo->ws;
278 
279 	if (bo->ws->debug_all_bos) {
280 		pthread_mutex_lock(&ws->global_bo_list_lock);
281 		LIST_ADDTAIL(&bo->global_list_item, &ws->global_bo_list);
282 		ws->num_buffers++;
283 		pthread_mutex_unlock(&ws->global_bo_list_lock);
284 	}
285 }
286 
287 static struct radeon_winsys_bo *
radv_amdgpu_winsys_bo_create(struct radeon_winsys * _ws,uint64_t size,unsigned alignment,enum radeon_bo_domain initial_domain,unsigned flags)288 radv_amdgpu_winsys_bo_create(struct radeon_winsys *_ws,
289 			     uint64_t size,
290 			     unsigned alignment,
291 			     enum radeon_bo_domain initial_domain,
292 			     unsigned flags)
293 {
294 	struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
295 	struct radv_amdgpu_winsys_bo *bo;
296 	struct amdgpu_bo_alloc_request request = {0};
297 	amdgpu_bo_handle buf_handle;
298 	uint64_t va = 0;
299 	amdgpu_va_handle va_handle;
300 	int r;
301 	bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo);
302 	if (!bo) {
303 		return NULL;
304 	}
305 
306 	r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
307 				  size, alignment, 0, &va, &va_handle, 0);
308 	if (r)
309 		goto error_va_alloc;
310 
311 	bo->base.va = va;
312 	bo->va_handle = va_handle;
313 	bo->size = size;
314 	bo->ws = ws;
315 	bo->is_virtual = !!(flags & RADEON_FLAG_VIRTUAL);
316 	bo->ref_count = 1;
317 
318 	if (flags & RADEON_FLAG_VIRTUAL) {
319 		bo->ranges = realloc(NULL, sizeof(struct radv_amdgpu_map_range));
320 		bo->range_count = 1;
321 		bo->range_capacity = 1;
322 
323 		bo->ranges[0].offset = 0;
324 		bo->ranges[0].size = size;
325 		bo->ranges[0].bo = NULL;
326 		bo->ranges[0].bo_offset = 0;
327 
328 		radv_amdgpu_winsys_virtual_map(bo, bo->ranges);
329 		return (struct radeon_winsys_bo *)bo;
330 	}
331 
332 	request.alloc_size = size;
333 	request.phys_alignment = alignment;
334 
335 	if (initial_domain & RADEON_DOMAIN_VRAM)
336 		request.preferred_heap |= AMDGPU_GEM_DOMAIN_VRAM;
337 	if (initial_domain & RADEON_DOMAIN_GTT)
338 		request.preferred_heap |= AMDGPU_GEM_DOMAIN_GTT;
339 
340 	if (flags & RADEON_FLAG_CPU_ACCESS)
341 		request.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
342 	if (flags & RADEON_FLAG_NO_CPU_ACCESS)
343 		request.flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
344 	if (flags & RADEON_FLAG_GTT_WC)
345 		request.flags |= AMDGPU_GEM_CREATE_CPU_GTT_USWC;
346 	if (!(flags & RADEON_FLAG_IMPLICIT_SYNC) && ws->info.drm_minor >= 22)
347 		request.flags |= AMDGPU_GEM_CREATE_EXPLICIT_SYNC;
348 	if (flags & RADEON_FLAG_NO_INTERPROCESS_SHARING && ws->info.drm_minor >= 20 && ws->use_local_bos) {
349 		bo->base.is_local = true;
350 		request.flags |= AMDGPU_GEM_CREATE_VM_ALWAYS_VALID;
351 	}
352 
353 	/* this won't do anything on pre 4.9 kernels */
354 	if (ws->zero_all_vram_allocs && (initial_domain & RADEON_DOMAIN_VRAM))
355 		request.flags |= AMDGPU_GEM_CREATE_VRAM_CLEARED;
356 	r = amdgpu_bo_alloc(ws->dev, &request, &buf_handle);
357 	if (r) {
358 		fprintf(stderr, "amdgpu: Failed to allocate a buffer:\n");
359 		fprintf(stderr, "amdgpu:    size      : %"PRIu64" bytes\n", size);
360 		fprintf(stderr, "amdgpu:    alignment : %u bytes\n", alignment);
361 		fprintf(stderr, "amdgpu:    domains   : %u\n", initial_domain);
362 		goto error_bo_alloc;
363 	}
364 
365 	r = radv_amdgpu_bo_va_op(ws, buf_handle, 0, size, va, flags,
366 				 AMDGPU_VA_OP_MAP);
367 	if (r)
368 		goto error_va_map;
369 
370 	bo->bo = buf_handle;
371 	bo->initial_domain = initial_domain;
372 	bo->is_shared = false;
373 	radv_amdgpu_add_buffer_to_global_list(bo);
374 	return (struct radeon_winsys_bo *)bo;
375 error_va_map:
376 	amdgpu_bo_free(buf_handle);
377 
378 error_bo_alloc:
379 	amdgpu_va_range_free(va_handle);
380 
381 error_va_alloc:
382 	FREE(bo);
383 	return NULL;
384 }
385 
386 static void *
radv_amdgpu_winsys_bo_map(struct radeon_winsys_bo * _bo)387 radv_amdgpu_winsys_bo_map(struct radeon_winsys_bo *_bo)
388 {
389 	struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
390 	int ret;
391 	void *data;
392 	ret = amdgpu_bo_cpu_map(bo->bo, &data);
393 	if (ret)
394 		return NULL;
395 	return data;
396 }
397 
398 static void
radv_amdgpu_winsys_bo_unmap(struct radeon_winsys_bo * _bo)399 radv_amdgpu_winsys_bo_unmap(struct radeon_winsys_bo *_bo)
400 {
401 	struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
402 	amdgpu_bo_cpu_unmap(bo->bo);
403 }
404 
405 static struct radeon_winsys_bo *
radv_amdgpu_winsys_bo_from_fd(struct radeon_winsys * _ws,int fd,unsigned * stride,unsigned * offset)406 radv_amdgpu_winsys_bo_from_fd(struct radeon_winsys *_ws,
407 			      int fd, unsigned *stride,
408 			      unsigned *offset)
409 {
410 	struct radv_amdgpu_winsys *ws = radv_amdgpu_winsys(_ws);
411 	struct radv_amdgpu_winsys_bo *bo;
412 	uint64_t va;
413 	amdgpu_va_handle va_handle;
414 	enum amdgpu_bo_handle_type type = amdgpu_bo_handle_type_dma_buf_fd;
415 	struct amdgpu_bo_import_result result = {0};
416 	struct amdgpu_bo_info info = {0};
417 	enum radeon_bo_domain initial = 0;
418 	int r;
419 	bo = CALLOC_STRUCT(radv_amdgpu_winsys_bo);
420 	if (!bo)
421 		return NULL;
422 
423 	r = amdgpu_bo_import(ws->dev, type, fd, &result);
424 	if (r)
425 		goto error;
426 
427 	r = amdgpu_bo_query_info(result.buf_handle, &info);
428 	if (r)
429 		goto error_query;
430 
431 	r = amdgpu_va_range_alloc(ws->dev, amdgpu_gpu_va_range_general,
432 				  result.alloc_size, 1 << 20, 0, &va, &va_handle, 0);
433 	if (r)
434 		goto error_query;
435 
436 	r = radv_amdgpu_bo_va_op(ws, result.buf_handle, 0, result.alloc_size,
437 				 va, 0, AMDGPU_VA_OP_MAP);
438 	if (r)
439 		goto error_va_map;
440 
441 	if (info.preferred_heap & AMDGPU_GEM_DOMAIN_VRAM)
442 		initial |= RADEON_DOMAIN_VRAM;
443 	if (info.preferred_heap & AMDGPU_GEM_DOMAIN_GTT)
444 		initial |= RADEON_DOMAIN_GTT;
445 
446 	bo->bo = result.buf_handle;
447 	bo->base.va = va;
448 	bo->va_handle = va_handle;
449 	bo->initial_domain = initial;
450 	bo->size = result.alloc_size;
451 	bo->is_shared = true;
452 	bo->ws = ws;
453 	bo->ref_count = 1;
454 	radv_amdgpu_add_buffer_to_global_list(bo);
455 	return (struct radeon_winsys_bo *)bo;
456 error_va_map:
457 	amdgpu_va_range_free(va_handle);
458 
459 error_query:
460 	amdgpu_bo_free(result.buf_handle);
461 
462 error:
463 	FREE(bo);
464 	return NULL;
465 }
466 
467 static bool
radv_amdgpu_winsys_get_fd(struct radeon_winsys * _ws,struct radeon_winsys_bo * _bo,int * fd)468 radv_amdgpu_winsys_get_fd(struct radeon_winsys *_ws,
469 			  struct radeon_winsys_bo *_bo,
470 			  int *fd)
471 {
472 	struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
473 	enum amdgpu_bo_handle_type type = amdgpu_bo_handle_type_dma_buf_fd;
474 	int r;
475 	unsigned handle;
476 	r = amdgpu_bo_export(bo->bo, type, &handle);
477 	if (r)
478 		return false;
479 
480 	*fd = (int)handle;
481 	bo->is_shared = true;
482 	return true;
483 }
484 
radv_eg_tile_split_rev(unsigned eg_tile_split)485 static unsigned radv_eg_tile_split_rev(unsigned eg_tile_split)
486 {
487 	switch (eg_tile_split) {
488 	case 64:    return 0;
489 	case 128:   return 1;
490 	case 256:   return 2;
491 	case 512:   return 3;
492 	default:
493 	case 1024:  return 4;
494 	case 2048:  return 5;
495 	case 4096:  return 6;
496 	}
497 }
498 
499 static void
radv_amdgpu_winsys_bo_set_metadata(struct radeon_winsys_bo * _bo,struct radeon_bo_metadata * md)500 radv_amdgpu_winsys_bo_set_metadata(struct radeon_winsys_bo *_bo,
501 				   struct radeon_bo_metadata *md)
502 {
503 	struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
504 	struct amdgpu_bo_metadata metadata = {0};
505 	uint32_t tiling_flags = 0;
506 
507 	if (bo->ws->info.chip_class >= GFX9) {
508 		tiling_flags |= AMDGPU_TILING_SET(SWIZZLE_MODE, md->u.gfx9.swizzle_mode);
509 	} else {
510 		if (md->u.legacy.macrotile == RADEON_LAYOUT_TILED)
511 			tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 4); /* 2D_TILED_THIN1 */
512 		else if (md->u.legacy.microtile == RADEON_LAYOUT_TILED)
513 			tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 2); /* 1D_TILED_THIN1 */
514 		else
515 			tiling_flags |= AMDGPU_TILING_SET(ARRAY_MODE, 1); /* LINEAR_ALIGNED */
516 
517 		tiling_flags |= AMDGPU_TILING_SET(PIPE_CONFIG, md->u.legacy.pipe_config);
518 		tiling_flags |= AMDGPU_TILING_SET(BANK_WIDTH, util_logbase2(md->u.legacy.bankw));
519 		tiling_flags |= AMDGPU_TILING_SET(BANK_HEIGHT, util_logbase2(md->u.legacy.bankh));
520 		if (md->u.legacy.tile_split)
521 			tiling_flags |= AMDGPU_TILING_SET(TILE_SPLIT, radv_eg_tile_split_rev(md->u.legacy.tile_split));
522 		tiling_flags |= AMDGPU_TILING_SET(MACRO_TILE_ASPECT, util_logbase2(md->u.legacy.mtilea));
523 		tiling_flags |= AMDGPU_TILING_SET(NUM_BANKS, util_logbase2(md->u.legacy.num_banks)-1);
524 
525 		if (md->u.legacy.scanout)
526 			tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 0); /* DISPLAY_MICRO_TILING */
527 		else
528 			tiling_flags |= AMDGPU_TILING_SET(MICRO_TILE_MODE, 1); /* THIN_MICRO_TILING */
529 	}
530 
531 	metadata.tiling_info = tiling_flags;
532 	metadata.size_metadata = md->size_metadata;
533 	memcpy(metadata.umd_metadata, md->metadata, sizeof(md->metadata));
534 
535 	amdgpu_bo_set_metadata(bo->bo, &metadata);
536 }
537 
radv_amdgpu_bo_init_functions(struct radv_amdgpu_winsys * ws)538 void radv_amdgpu_bo_init_functions(struct radv_amdgpu_winsys *ws)
539 {
540 	ws->base.buffer_create = radv_amdgpu_winsys_bo_create;
541 	ws->base.buffer_destroy = radv_amdgpu_winsys_bo_destroy;
542 	ws->base.buffer_map = radv_amdgpu_winsys_bo_map;
543 	ws->base.buffer_unmap = radv_amdgpu_winsys_bo_unmap;
544 	ws->base.buffer_from_fd = radv_amdgpu_winsys_bo_from_fd;
545 	ws->base.buffer_get_fd = radv_amdgpu_winsys_get_fd;
546 	ws->base.buffer_set_metadata = radv_amdgpu_winsys_bo_set_metadata;
547 	ws->base.buffer_virtual_bind = radv_amdgpu_winsys_bo_virtual_bind;
548 }
549