• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = agx_bo_map(bo->bo);
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_zalloc2(&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          pool->num_free_usc_bos--;
98       }
99    } else {
100       if (!list_is_empty(&pool->free_bos)) {
101          bo = list_first_entry(&pool->free_bos, struct hk_cmd_bo, link);
102          pool->num_free_bos--;
103       }
104    }
105    if (bo) {
106       list_del(&bo->link);
107       *bo_out = bo;
108       return VK_SUCCESS;
109    }
110 
111    return hk_cmd_bo_create(pool, usc, bo_out);
112 }
113 
114 void
hk_cmd_pool_free_bo_list(struct hk_cmd_pool * pool,struct list_head * bos)115 hk_cmd_pool_free_bo_list(struct hk_cmd_pool *pool, struct list_head *bos)
116 {
117    list_for_each_entry_safe(struct hk_cmd_bo, bo, bos, link) {
118       list_del(&bo->link);
119       if (pool->num_free_bos > HK_CMD_POOL_BO_MAX) {
120          hk_cmd_bo_destroy(pool, bo);
121       } else {
122          list_addtail(&bo->link, &pool->free_bos);
123          pool->num_free_bos++;
124       }
125    }
126 }
127 
128 void
hk_cmd_pool_free_usc_bo_list(struct hk_cmd_pool * pool,struct list_head * bos)129 hk_cmd_pool_free_usc_bo_list(struct hk_cmd_pool *pool, struct list_head *bos)
130 {
131    list_for_each_entry_safe(struct hk_cmd_bo, bo, bos, link) {
132       list_del(&bo->link);
133       if (pool->num_free_usc_bos > HK_CMD_POOL_BO_MAX) {
134          hk_cmd_bo_destroy(pool, bo);
135       } else {
136          list_addtail(&bo->link, &pool->free_usc_bos);
137          pool->num_free_usc_bos++;
138       }
139    }
140 }
141 
142 VKAPI_ATTR void VKAPI_CALL
hk_DestroyCommandPool(VkDevice _device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)143 hk_DestroyCommandPool(VkDevice _device, VkCommandPool commandPool,
144                       const VkAllocationCallbacks *pAllocator)
145 {
146    VK_FROM_HANDLE(hk_device, device, _device);
147    VK_FROM_HANDLE(hk_cmd_pool, pool, commandPool);
148 
149    if (!pool)
150       return;
151 
152    vk_command_pool_finish(&pool->vk);
153    hk_cmd_pool_destroy_bos(pool);
154    vk_free2(&device->vk.alloc, pAllocator, pool);
155 }
156 
157 VKAPI_ATTR void VKAPI_CALL
hk_TrimCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolTrimFlags flags)158 hk_TrimCommandPool(VkDevice device, VkCommandPool commandPool,
159                    VkCommandPoolTrimFlags flags)
160 {
161    VK_FROM_HANDLE(hk_cmd_pool, pool, commandPool);
162 
163    vk_command_pool_trim(&pool->vk, flags);
164    hk_cmd_pool_destroy_bos(pool);
165 }
166