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 33VkResult MUST_CHECK 34vk_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 51void 52vk_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 63VKAPI_ATTR VkResult VKAPI_CALL 64vk_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 89VKAPI_ATTR void VKAPI_CALL 90vk_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 104VKAPI_ATTR VkResult VKAPI_CALL 105vk_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 134VKAPI_ATTR void VKAPI_CALL 135vk_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 150VKAPI_ATTR void VKAPI_CALL 151vk_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