/* * Geforce NV2A PGRAPH Vulkan Renderer * * Copyright (c) 2024 Matt Borgerson * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see . */ #include "renderer.h" static void create_command_pool(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; QueueFamilyIndices indices = pgraph_vk_find_queue_families(r->physical_device); VkCommandPoolCreateInfo create_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, .flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, .queueFamilyIndex = indices.queue_family, }; VK_CHECK( vkCreateCommandPool(r->device, &create_info, NULL, &r->command_pool)); } static void destroy_command_pool(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; vkDestroyCommandPool(r->device, r->command_pool, NULL); } static void create_command_buffers(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; VkCommandBufferAllocateInfo alloc_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, .commandPool = r->command_pool, .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, .commandBufferCount = ARRAY_SIZE(r->command_buffers), }; VK_CHECK( vkAllocateCommandBuffers(r->device, &alloc_info, r->command_buffers)); r->command_buffer = r->command_buffers[0]; r->aux_command_buffer = r->command_buffers[1]; } static void destroy_command_buffers(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; vkFreeCommandBuffers(r->device, r->command_pool, ARRAY_SIZE(r->command_buffers), r->command_buffers); r->command_buffer = VK_NULL_HANDLE; r->aux_command_buffer = VK_NULL_HANDLE; } VkCommandBuffer pgraph_vk_begin_single_time_commands(PGRAPHState *pg) { PGRAPHVkState *r = pg->vk_renderer_state; assert(!r->in_aux_command_buffer); r->in_aux_command_buffer = true; VkCommandBufferBeginInfo begin_info = { .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, }; VK_CHECK(vkBeginCommandBuffer(r->aux_command_buffer, &begin_info)); return r->aux_command_buffer; } void pgraph_vk_end_single_time_commands(PGRAPHState *pg, VkCommandBuffer cmd) { PGRAPHVkState *r = pg->vk_renderer_state; assert(r->in_aux_command_buffer); VK_CHECK(vkEndCommandBuffer(cmd)); VkSubmitInfo submit_info = { .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, .commandBufferCount = 1, .pCommandBuffers = &cmd, }; VK_CHECK(vkQueueSubmit(r->queue, 1, &submit_info, VK_NULL_HANDLE)); nv2a_profile_inc_counter(NV2A_PROF_QUEUE_SUBMIT_AUX); VK_CHECK(vkQueueWaitIdle(r->queue)); r->in_aux_command_buffer = false; } void pgraph_vk_init_command_buffers(PGRAPHState *pg) { create_command_pool(pg); create_command_buffers(pg); } void pgraph_vk_finalize_command_buffers(PGRAPHState *pg) { destroy_command_buffers(pg); destroy_command_pool(pg); }