Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

radv_amdgpu_bo.c 18KB

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