1 /*
2 * Copyright © 2015 Intel Corporation
3 * Copyright © 2022 Collabora, Ltd
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 #include "vk_command_pool.h"
26
27 #include "vk_alloc.h"
28 #include "vk_command_buffer.h"
29 #include "vk_common_entrypoints.h"
30 #include "vk_device.h"
31 #include "vk_log.h"
32
33 VkResult MUST_CHECK
vk_command_pool_init(struct vk_command_pool * pool,struct vk_device * device,const VkCommandPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator)34 vk_command_pool_init(struct vk_command_pool *pool,
35 struct vk_device *device,
36 const VkCommandPoolCreateInfo *pCreateInfo,
37 const VkAllocationCallbacks *pAllocator)
38 {
39 memset(pool, 0, sizeof(*pool));
40 vk_object_base_init(device, &pool->base,
41 VK_OBJECT_TYPE_COMMAND_POOL);
42
43 pool->flags = pCreateInfo->flags;
44 pool->queue_family_index = pCreateInfo->queueFamilyIndex;
45 pool->alloc = pAllocator ? *pAllocator : device->alloc;
46 list_inithead(&pool->command_buffers);
47
48 return VK_SUCCESS;
49 }
50
51 void
vk_command_pool_finish(struct vk_command_pool * pool)52 vk_command_pool_finish(struct vk_command_pool *pool)
53 {
54 list_for_each_entry_safe(struct vk_command_buffer, cmd_buffer,
55 &pool->command_buffers, pool_link) {
56 cmd_buffer->destroy(cmd_buffer);
57 }
58 assert(list_is_empty(&pool->command_buffers));
59
60 vk_object_base_finish(&pool->base);
61 }
62
63 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_CreateCommandPool(VkDevice _device,const VkCommandPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkCommandPool * pCommandPool)64 vk_common_CreateCommandPool(VkDevice _device,
65 const VkCommandPoolCreateInfo *pCreateInfo,
66 const VkAllocationCallbacks *pAllocator,
67 VkCommandPool *pCommandPool)
68 {
69 VK_FROM_HANDLE(vk_device, device, _device);
70 struct vk_command_pool *pool;
71 VkResult result;
72
73 pool = vk_alloc2(&device->alloc, pAllocator, sizeof(*pool), 8,
74 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
75 if (pool == NULL)
76 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
77
78 result = vk_command_pool_init(pool, device, pCreateInfo, pAllocator);
79 if (unlikely(result != VK_SUCCESS)) {
80 vk_free2(&device->alloc, pAllocator, pool);
81 return result;
82 }
83
84 *pCommandPool = vk_command_pool_to_handle(pool);
85
86 return VK_SUCCESS;
87 }
88
89 VKAPI_ATTR void VKAPI_CALL
vk_common_DestroyCommandPool(VkDevice _device,VkCommandPool commandPool,const VkAllocationCallbacks * pAllocator)90 vk_common_DestroyCommandPool(VkDevice _device,
91 VkCommandPool commandPool,
92 const VkAllocationCallbacks *pAllocator)
93 {
94 VK_FROM_HANDLE(vk_device, device, _device);
95 VK_FROM_HANDLE(vk_command_pool, pool, commandPool);
96
97 if (pool == NULL)
98 return;
99
100 vk_command_pool_finish(pool);
101 vk_free2(&device->alloc, pAllocator, pool);
102 }
103
104 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_ResetCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolResetFlags flags)105 vk_common_ResetCommandPool(VkDevice device,
106 VkCommandPool commandPool,
107 VkCommandPoolResetFlags flags)
108 {
109 VK_FROM_HANDLE(vk_command_pool, pool, commandPool);
110 const struct vk_device_dispatch_table *disp =
111 &pool->base.device->dispatch_table;
112
113 #define COPY_FLAG(flag) \
114 if (flags & VK_COMMAND_POOL_RESET_##flag) \
115 cb_flags |= VK_COMMAND_BUFFER_RESET_##flag
116
117 VkCommandBufferResetFlags cb_flags = 0;
118 COPY_FLAG(RELEASE_RESOURCES_BIT);
119
120 #undef COPY_FLAG
121
122 list_for_each_entry_safe(struct vk_command_buffer, cmd_buffer,
123 &pool->command_buffers, pool_link) {
124 VkResult result =
125 disp->ResetCommandBuffer(vk_command_buffer_to_handle(cmd_buffer),
126 cb_flags);
127 if (result != VK_SUCCESS)
128 return result;
129 }
130
131 return VK_SUCCESS;
132 }
133
134 VKAPI_ATTR void VKAPI_CALL
vk_common_FreeCommandBuffers(VkDevice device,VkCommandPool commandPool,uint32_t commandBufferCount,const VkCommandBuffer * pCommandBuffers)135 vk_common_FreeCommandBuffers(VkDevice device,
136 VkCommandPool commandPool,
137 uint32_t commandBufferCount,
138 const VkCommandBuffer *pCommandBuffers)
139 {
140 for (uint32_t i = 0; i < commandBufferCount; i++) {
141 VK_FROM_HANDLE(vk_command_buffer, cmd_buffer, pCommandBuffers[i]);
142
143 if (cmd_buffer == NULL)
144 continue;
145
146 cmd_buffer->destroy(cmd_buffer);
147 }
148 }
149
150 VKAPI_ATTR void VKAPI_CALL
vk_common_TrimCommandPool(VkDevice device,VkCommandPool commandPool,VkCommandPoolTrimFlags flags)151 vk_common_TrimCommandPool(VkDevice device,
152 VkCommandPool commandPool,
153 VkCommandPoolTrimFlags flags)
154 {
155 /* No-op is a valid implementation but may not be optimal */
156 }
157