1 /*
2 * Copyright © 2022 Collabora Ltd. and Red Hat Inc.
3 * SPDX-License-Identifier: MIT
4 */
5 #include "nvk_cmd_pool.h"
6
7 #include "nvk_device.h"
8 #include "nvk_entrypoints.h"
9 #include "nvk_physical_device.h"
10
11 static VkResult
nvk_cmd_bo_create(struct nvk_cmd_pool * pool,bool force_gart,struct nvk_cmd_bo ** bo_out)12 nvk_cmd_bo_create(struct nvk_cmd_pool *pool, bool force_gart, struct nvk_cmd_bo **bo_out)
13 {
14 struct nvk_device *dev = nvk_cmd_pool_device(pool);
15 struct nvk_cmd_bo *bo;
16
17 bo = vk_zalloc(&pool->vk.alloc, sizeof(*bo), 8,
18 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
19 if (bo == NULL)
20 return vk_error(pool, VK_ERROR_OUT_OF_HOST_MEMORY);
21
22 uint32_t flags = NOUVEAU_WS_BO_GART | NOUVEAU_WS_BO_MAP | NOUVEAU_WS_BO_NO_SHARE;
23 if (force_gart)
24 assert(flags & NOUVEAU_WS_BO_GART);
25 bo->bo = nouveau_ws_bo_new_mapped(dev->ws_dev, NVK_CMD_BO_SIZE, 0,
26 flags, NOUVEAU_WS_BO_WR, &bo->map);
27 if (bo->bo == NULL) {
28 vk_free(&pool->vk.alloc, bo);
29 return vk_error(pool, VK_ERROR_OUT_OF_DEVICE_MEMORY);
30 }
31
32 *bo_out = bo;
33 return VK_SUCCESS;
34 }
35
36 static void
nvk_cmd_bo_destroy(struct nvk_cmd_pool * pool,struct nvk_cmd_bo * bo)37 nvk_cmd_bo_destroy(struct nvk_cmd_pool *pool, struct nvk_cmd_bo *bo)
38 {
39 nouveau_ws_bo_unmap(bo->bo, bo->map);
40 nouveau_ws_bo_destroy(bo->bo);
41 vk_free(&pool->vk.alloc, bo);
42 }
43
44 VKAPI_ATTR VkResult VKAPI_CALL
nvk_CreateCommandPool(VkDevice _device,const VkCommandPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkCommandPool * pCmdPool)45 nvk_CreateCommandPool(VkDevice _device,
46 const VkCommandPoolCreateInfo *pCreateInfo,
47 const VkAllocationCallbacks *pAllocator,
48 VkCommandPool *pCmdPool)
49 {
50 VK_FROM_HANDLE(nvk_device, device, _device);
51 struct nvk_cmd_pool *pool;
52
53 pool = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*pool), 8,
54 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
55 if (pool == NULL)
56 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
57
58 VkResult result = vk_command_pool_init(&device->vk, &pool->vk,
59 pCreateInfo, pAllocator);
60 if (result != VK_SUCCESS) {
61 vk_free2(&device->vk.alloc, pAllocator, pool);
62 return result;
63 }
64
65 list_inithead(&pool->free_bos);
66 list_inithead(&pool->free_gart_bos);
67
68 *pCmdPool = nvk_cmd_pool_to_handle(pool);
69
70 return VK_SUCCESS;
71 }
72
73 static void
nvk_cmd_pool_destroy_bos(struct nvk_cmd_pool * pool)74 nvk_cmd_pool_destroy_bos(struct nvk_cmd_pool *pool)
75 {
76 list_for_each_entry_safe(struct nvk_cmd_bo, bo, &pool->free_bos, link)
77 nvk_cmd_bo_destroy(pool, bo);
78
79 list_inithead(&pool->free_bos);
80
81 list_for_each_entry_safe(struct nvk_cmd_bo, bo, &pool->free_gart_bos, link)
82 nvk_cmd_bo_destroy(pool, bo);
83
84 list_inithead(&pool->free_gart_bos);
85 }
86
87 VkResult
nvk_cmd_pool_alloc_bo(struct nvk_cmd_pool * pool,bool force_gart,struct nvk_cmd_bo ** bo_out)88 nvk_cmd_pool_alloc_bo(struct nvk_cmd_pool *pool, bool force_gart, struct nvk_cmd_bo **bo_out)
89 {
90 struct nvk_cmd_bo *bo = NULL;
91 if (force_gart) {
92 if (!list_is_empty(&pool->free_gart_bos))
93 bo = list_first_entry(&pool->free_gart_bos, struct nvk_cmd_bo, link);
94 } else {
95 if (!list_is_empty(&pool->free_bos))
96 bo = list_first_entry(&pool->free_bos, struct nvk_cmd_bo, link);
97 }
98 if (bo) {
99 list_del(&bo->link);
100 *bo_out = bo;
101 return VK_SUCCESS;
102 }
103
104 return nvk_cmd_bo_create(pool, force_gart, bo_out);
105 }
106
107 void
nvk_cmd_pool_free_bo_list(struct nvk_cmd_pool * pool,struct list_head * bos)108 nvk_cmd_pool_free_bo_list(struct nvk_cmd_pool *pool, struct list_head *bos)
109 {
110 list_splicetail(bos, &pool->free_bos);
111 list_inithead(bos);
112 }
113
114 void
nvk_cmd_pool_free_gart_bo_list(struct nvk_cmd_pool * pool,struct list_head * bos)115 nvk_cmd_pool_free_gart_bo_list(struct nvk_cmd_pool *pool, struct list_head *bos)
116 {
117 list_splicetail(bos, &pool->free_gart_bos);
118 list_inithead(bos);
119 }
120
121 VKAPI_ATTR void VKAPI_CALL
nvk_DestroyCommandPool(VkDevice _device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)122 nvk_DestroyCommandPool(VkDevice _device,
123 VkCommandPool commandPool,
124 const VkAllocationCallbacks *pAllocator)
125 {
126 VK_FROM_HANDLE(nvk_device, device, _device);
127 VK_FROM_HANDLE(nvk_cmd_pool, pool, commandPool);
128
129 if (!pool)
130 return;
131
132 vk_command_pool_finish(&pool->vk);
133 nvk_cmd_pool_destroy_bos(pool);
134 vk_free2(&device->vk.alloc, pAllocator, pool);
135 }
136
137 VKAPI_ATTR void VKAPI_CALL
nvk_TrimCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolTrimFlags flags)138 nvk_TrimCommandPool(VkDevice device,
139 VkCommandPool commandPool,
140 VkCommandPoolTrimFlags flags)
141 {
142 VK_FROM_HANDLE(nvk_cmd_pool, pool, commandPool);
143
144 vk_command_pool_trim(&pool->vk, flags);
145 nvk_cmd_pool_destroy_bos(pool);
146 }
147