1 /*
2 * Copyright 2024 Valve Corporation
3 * Copyright 2024 Alyssa Rosenzweig
4 * Copyright 2022-2023 Collabora Ltd. and Red Hat Inc.
5 * SPDX-License-Identifier: MIT
6 */
7 #include "hk_cmd_pool.h"
8 #include "asahi/lib/agx_bo.h"
9
10 #include "hk_device.h"
11 #include "hk_entrypoints.h"
12 #include "hk_physical_device.h"
13
14 static VkResult
hk_cmd_bo_create(struct hk_cmd_pool * pool,bool usc,struct hk_cmd_bo ** bo_out)15 hk_cmd_bo_create(struct hk_cmd_pool *pool, bool usc, struct hk_cmd_bo **bo_out)
16 {
17 struct hk_device *dev = hk_cmd_pool_device(pool);
18 struct hk_cmd_bo *bo;
19
20 bo = vk_zalloc(&pool->vk.alloc, sizeof(*bo), 8,
21 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
22 if (bo == NULL)
23 return vk_error(pool, VK_ERROR_OUT_OF_HOST_MEMORY);
24
25 bo->bo = agx_bo_create(&dev->dev, HK_CMD_BO_SIZE, 0, usc ? AGX_BO_LOW_VA : 0,
26 "Command pool");
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->map = bo->bo->map;
33
34 *bo_out = bo;
35 return VK_SUCCESS;
36 }
37
38 static void
hk_cmd_bo_destroy(struct hk_cmd_pool * pool,struct hk_cmd_bo * bo)39 hk_cmd_bo_destroy(struct hk_cmd_pool *pool, struct hk_cmd_bo *bo)
40 {
41 struct hk_device *dev = hk_cmd_pool_device(pool);
42 agx_bo_unreference(&dev->dev, bo->bo);
43 vk_free(&pool->vk.alloc, bo);
44 }
45
46 VKAPI_ATTR VkResult VKAPI_CALL
hk_CreateCommandPool(VkDevice _device,const VkCommandPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkCommandPool * pCmdPool)47 hk_CreateCommandPool(VkDevice _device,
48 const VkCommandPoolCreateInfo *pCreateInfo,
49 const VkAllocationCallbacks *pAllocator,
50 VkCommandPool *pCmdPool)
51 {
52 VK_FROM_HANDLE(hk_device, device, _device);
53 struct hk_cmd_pool *pool;
54
55 pool = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*pool), 8,
56 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
57 if (pool == NULL)
58 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
59
60 VkResult result =
61 vk_command_pool_init(&device->vk, &pool->vk, pCreateInfo, pAllocator);
62 if (result != VK_SUCCESS) {
63 vk_free2(&device->vk.alloc, pAllocator, pool);
64 return result;
65 }
66
67 list_inithead(&pool->free_bos);
68 list_inithead(&pool->free_usc_bos);
69
70 *pCmdPool = hk_cmd_pool_to_handle(pool);
71
72 return VK_SUCCESS;
73 }
74
75 static void
hk_cmd_pool_destroy_bos(struct hk_cmd_pool * pool)76 hk_cmd_pool_destroy_bos(struct hk_cmd_pool *pool)
77 {
78 list_for_each_entry_safe(struct hk_cmd_bo, bo, &pool->free_bos, link)
79 hk_cmd_bo_destroy(pool, bo);
80
81 list_inithead(&pool->free_bos);
82
83 list_for_each_entry_safe(struct hk_cmd_bo, bo, &pool->free_usc_bos, link)
84 hk_cmd_bo_destroy(pool, bo);
85
86 list_inithead(&pool->free_usc_bos);
87 }
88
89 VkResult
hk_cmd_pool_alloc_bo(struct hk_cmd_pool * pool,bool usc,struct hk_cmd_bo ** bo_out)90 hk_cmd_pool_alloc_bo(struct hk_cmd_pool *pool, bool usc,
91 struct hk_cmd_bo **bo_out)
92 {
93 struct hk_cmd_bo *bo = NULL;
94 if (usc) {
95 if (!list_is_empty(&pool->free_usc_bos))
96 bo = list_first_entry(&pool->free_usc_bos, struct hk_cmd_bo, link);
97 } else {
98 if (!list_is_empty(&pool->free_bos))
99 bo = list_first_entry(&pool->free_bos, struct hk_cmd_bo, link);
100 }
101 if (bo) {
102 list_del(&bo->link);
103 *bo_out = bo;
104 return VK_SUCCESS;
105 }
106
107 return hk_cmd_bo_create(pool, usc, bo_out);
108 }
109
110 void
hk_cmd_pool_free_bo_list(struct hk_cmd_pool * pool,struct list_head * bos)111 hk_cmd_pool_free_bo_list(struct hk_cmd_pool *pool, struct list_head *bos)
112 {
113 list_splicetail(bos, &pool->free_bos);
114 list_inithead(bos);
115 }
116
117 void
hk_cmd_pool_free_usc_bo_list(struct hk_cmd_pool * pool,struct list_head * bos)118 hk_cmd_pool_free_usc_bo_list(struct hk_cmd_pool *pool, struct list_head *bos)
119 {
120 list_splicetail(bos, &pool->free_usc_bos);
121 list_inithead(bos);
122 }
123
124 VKAPI_ATTR void VKAPI_CALL
hk_DestroyCommandPool(VkDevice _device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)125 hk_DestroyCommandPool(VkDevice _device, VkCommandPool commandPool,
126 const VkAllocationCallbacks *pAllocator)
127 {
128 VK_FROM_HANDLE(hk_device, device, _device);
129 VK_FROM_HANDLE(hk_cmd_pool, pool, commandPool);
130
131 if (!pool)
132 return;
133
134 vk_command_pool_finish(&pool->vk);
135 hk_cmd_pool_destroy_bos(pool);
136 vk_free2(&device->vk.alloc, pAllocator, pool);
137 }
138
139 VKAPI_ATTR void VKAPI_CALL
hk_TrimCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolTrimFlags flags)140 hk_TrimCommandPool(VkDevice device, VkCommandPool commandPool,
141 VkCommandPoolTrimFlags flags)
142 {
143 VK_FROM_HANDLE(hk_cmd_pool, pool, commandPool);
144
145 vk_command_pool_trim(&pool->vk, flags);
146 hk_cmd_pool_destroy_bos(pool);
147 }
148