/* * Copyright © 2019 Raspberry Pi * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ #include "v3dv_private.h" VkResult v3dv_CreateCommandPool(VkDevice _device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCmdPool) { V3DV_FROM_HANDLE(v3dv_device, device, _device); struct v3dv_cmd_pool *pool; /* We only support one queue */ assert(pCreateInfo->queueFamilyIndex == 0); pool = vk_alloc2(&device->alloc, pAllocator, sizeof(*pool), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (pool == NULL) return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); if (pAllocator) pool->alloc = *pAllocator; else pool->alloc = device->alloc; list_inithead(&pool->cmd_buffers); *pCmdPool = v3dv_cmd_pool_to_handle(pool); return VK_SUCCESS; } static VkResult cmd_buffer_create(struct v3dv_device *device, struct v3dv_cmd_pool *pool, VkCommandBufferLevel level, VkCommandBuffer *pCommandBuffer) { struct v3dv_cmd_buffer *cmd_buffer; cmd_buffer = vk_zalloc(&pool->alloc, sizeof(*cmd_buffer), 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); if (cmd_buffer == NULL) return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); cmd_buffer->_loader_data.loaderMagic = ICD_LOADER_MAGIC; cmd_buffer->device = device; cmd_buffer->pool = pool; cmd_buffer->level = level; cmd_buffer->usage_flags = 0; /* FIXME: setup command list structures */ assert(pool); list_addtail(&cmd_buffer->pool_link, &pool->cmd_buffers); *pCommandBuffer = v3dv_cmd_buffer_to_handle(cmd_buffer); return VK_SUCCESS; } static void cmd_buffer_destroy(struct v3dv_cmd_buffer *cmd_buffer) { list_del(&cmd_buffer->pool_link); v3dv_cl_destroy(&cmd_buffer->bcl); v3dv_cl_destroy(&cmd_buffer->rcl); v3dv_cl_destroy(&cmd_buffer->indirect); vk_free(&cmd_buffer->pool->alloc, cmd_buffer); } static VkResult cmd_buffer_reset(struct v3dv_cmd_buffer *cmd_buffer) { cmd_buffer->usage_flags = 0; v3dv_cl_reset(&cmd_buffer->bcl); v3dv_cl_reset(&cmd_buffer->rcl); v3dv_cl_reset(&cmd_buffer->indirect); return VK_SUCCESS; } VkResult v3dv_AllocateCommandBuffers(VkDevice _device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) { V3DV_FROM_HANDLE(v3dv_device, device, _device); V3DV_FROM_HANDLE(v3dv_cmd_pool, pool, pAllocateInfo->commandPool); /* FIXME: implement secondary command buffers */ assert(pAllocateInfo->level == VK_COMMAND_BUFFER_LEVEL_PRIMARY); VkResult result = VK_SUCCESS; uint32_t i; for (i = 0; i < pAllocateInfo->commandBufferCount; i++) { result = cmd_buffer_create(device, pool, pAllocateInfo->level, &pCommandBuffers[i]); if (result != VK_SUCCESS) break; } if (result != VK_SUCCESS) { v3dv_FreeCommandBuffers(_device, pAllocateInfo->commandPool, i, pCommandBuffers); for (i = 0; i < pAllocateInfo->commandBufferCount; i++) pCommandBuffers[i] = VK_NULL_HANDLE; } return result; } void v3dv_FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) { for (uint32_t i = 0; i < commandBufferCount; i++) { V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, pCommandBuffers[i]); if (!cmd_buffer) continue; cmd_buffer_destroy(cmd_buffer); } } void v3dv_DestroyCommandPool(VkDevice _device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) { V3DV_FROM_HANDLE(v3dv_device, device, _device); V3DV_FROM_HANDLE(v3dv_cmd_pool, pool, commandPool); if (!pool) return; list_for_each_entry_safe(struct v3dv_cmd_buffer, cmd_buffer, &pool->cmd_buffers, pool_link) { cmd_buffer_destroy(cmd_buffer); } vk_free2(&device->alloc, pAllocator, pool); } VkResult v3dv_BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) { V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); assert(cmd_buffer->level == VK_COMMAND_BUFFER_LEVEL_SECONDARY || !(cmd_buffer->usage_flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)); /* If this is the first vkBeginCommandBuffer, we must initialize the * command buffer's state. Otherwise, we must reset its state. In both * cases we reset it. */ VkResult result = cmd_buffer_reset(cmd_buffer); if (result != VK_SUCCESS) return result; cmd_buffer->usage_flags = pBeginInfo->flags; v3dv_cl_init(cmd_buffer, &cmd_buffer->bcl); v3dv_cl_init(cmd_buffer, &cmd_buffer->rcl); v3dv_cl_init(cmd_buffer, &cmd_buffer->indirect); return VK_SUCCESS; }