From e99a55baa8f353a42b43aa86e7dddc3d8b68d5dc Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Tue, 19 Nov 2024 14:51:59 -0600 Subject: render: create a vkqueue struct for Vulkan queues Add a vkqueue struct to the Vulkan device interface and shift queue operations to helper functions that interact with this new struct. This makes the initialization routines more readable and simplifies the interface. Signed-off-by: Danny Holman --- render/vulkan/device.c | 190 ++++++++++++++++++++++------------------------ render/vulkan/device.h | 15 ++-- render/vulkan/swapchain.c | 11 +-- 3 files changed, 105 insertions(+), 111 deletions(-) diff --git a/render/vulkan/device.c b/render/vulkan/device.c index a123983..1254f76 100644 --- a/render/vulkan/device.c +++ b/render/vulkan/device.c @@ -3,12 +3,10 @@ #include #include -struct vkqfam_data { - uint32_t gfx; - uint32_t present; - uint32_t compute; - uint32_t transfer; -}; +static int gfx_qfam = -1; +static int tsfr_qfam = -1; +static int comp_qfam = -1; +static int pres_qfam = -1; struct vkdev_data { VkPhysicalDeviceProperties pdev_props; @@ -18,26 +16,52 @@ struct vkdev_data { const char** pdev_extensions; }; -int _query_qfam_data(VkSurfaceKHR surface, VkPhysicalDevice pdev, VkQueueFamilyProperties **qfam_props) { - uint32_t qfam_count = 0; - vkGetPhysicalDeviceQueueFamilyProperties(pdev, &qfam_count, NULL); - *qfam_props = rune_alloc(sizeof(VkQueueFamilyProperties) * qfam_count); - vkGetPhysicalDeviceQueueFamilyProperties(pdev, &qfam_count, *qfam_props); - return qfam_count; -} - void _query_pdev_data(VkPhysicalDevice pdev, struct vkdev_data *pdata) { vkGetPhysicalDeviceProperties(pdev, &pdata->pdev_props); vkGetPhysicalDeviceFeatures(pdev, &pdata->pdev_feats); vkGetPhysicalDeviceMemoryProperties(pdev, &pdata->pdev_mprops); } -int _get_qfam_index(int num_props, uint32_t queue_type, VkQueueFamilyProperties *qfam_props) { +uint32_t _query_qfam_data(VkSurfaceKHR surface, VkPhysicalDevice pdev, VkQueueFamilyProperties** qfam_props) { + uint32_t count; + vkGetPhysicalDeviceQueueFamilyProperties(pdev, &count, NULL); + *qfam_props = rune_alloc(sizeof(VkQueueFamilyProperties) * count); + vkGetPhysicalDeviceQueueFamilyProperties(pdev, &count, *qfam_props); + return count; +} + +int _query_gfx_index(int num_props, VkQueueFamilyProperties *qfam_props) { for (int i = 0; i < num_props; i++) { - if (qfam_props[i].queueFlags & queue_type) - return i; + if (qfam_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) + gfx_qfam = i; } - return -1; + return gfx_qfam; +} + +int _query_tsfr_index(int num_props, VkQueueFamilyProperties *qfam_props) { + for (int i = 0; i < num_props; i++) { + if (qfam_props[i].queueFlags & VK_QUEUE_TRANSFER_BIT) + tsfr_qfam = i; + } + return tsfr_qfam; +} + +int _query_comp_index(int num_props, VkQueueFamilyProperties *qfam_props) { + for (int i = 0; i < num_props; i++) { + if (qfam_props[i].queueFlags & VK_QUEUE_COMPUTE_BIT) + comp_qfam = i; + } + return comp_qfam; +} + +int _query_pres_index(int num_props, VkQueueFamilyProperties *qfam_props, VkPhysicalDevice pdev, VkSurfaceKHR surface) { + VkBool32 present_bit; + for (int i = 0; i < num_props; i++) { + vkGetPhysicalDeviceSurfaceSupportKHR(pdev, 0, surface, &present_bit); + if (present_bit != VK_FALSE) + pres_qfam = i; + } + return pres_qfam; } int _check_pdev(VkSurfaceKHR surface, VkPhysicalDevice pdev) { @@ -49,90 +73,78 @@ int _check_pdev(VkSurfaceKHR surface, VkPhysicalDevice pdev) { return score; VkQueueFamilyProperties *qfam_props; - int num_qfams = _query_qfam_data(surface, pdev, &qfam_props); - if (_get_qfam_index(num_qfams, VK_QUEUE_GRAPHICS_BIT, qfam_props) != -1) + uint32_t num_qfams = _query_qfam_data(surface, pdev, &qfam_props); + if (_query_gfx_index(num_qfams, qfam_props) != -1) score += 20; - if (_get_qfam_index(num_qfams, VK_QUEUE_COMPUTE_BIT, qfam_props) != -1) - score += 5; - if (_get_qfam_index(num_qfams, VK_QUEUE_TRANSFER_BIT, qfam_props) != -1) + if (_query_comp_index(num_qfams, qfam_props) != -1) score += 20; - - VkBool32 present_bit; - vkGetPhysicalDeviceSurfaceSupportKHR(pdev, 0, surface, &present_bit); - if (present_bit != VK_FALSE) + if (_query_tsfr_index(num_qfams, qfam_props) != -1) + score += 20; + if (_query_pres_index(num_qfams, qfam_props, pdev, surface) != -1) score += 20; rune_free(qfam_props); return score; } -struct vkdev* create_vkdev(VkInstance instance, VkSurfaceKHR surface) { - uint32_t pdev_count; - vkEnumeratePhysicalDevices(instance, &pdev_count, NULL); - if (pdev_count == 0) +VkPhysicalDevice _select_pdev(VkInstance instance, VkSurfaceKHR surface) { + uint32_t count; + vkEnumeratePhysicalDevices(instance, &count, NULL); + if (count == 0) return NULL; - VkPhysicalDevice pdevs[pdev_count]; - vkEnumeratePhysicalDevices(instance, &pdev_count, pdevs); - - uint32_t selected_pdev = -1; - for (uint32_t i = 0; i < pdev_count; i++) { - if (_check_pdev(surface, pdevs[i]) >= 60) { - selected_pdev = i; - break; - } + + VkPhysicalDevice pdevs[count]; + vkEnumeratePhysicalDevices(instance, &count, pdevs); + + for (uint32_t i = 0; i < count; i++) { + if (_check_pdev(surface, pdevs[i]) >= 80) + return pdevs[i]; + } + return NULL; +} + +void _create_queue(struct vkdev *dev, int qfam_index, int queue_index) { + vkGetDeviceQueue(dev->ldev, qfam_index, queue_index, &dev->queues[qfam_index].handle); + if (dev->queues[qfam_index].handle == NULL) { + log_output(LOG_FATAL, "Error creating required Vulkan queue"); + rune_abort(); } +} - if (selected_pdev == -1) { +struct vkdev* create_vkdev(VkInstance instance, VkSurfaceKHR surface) { + VkPhysicalDevice pdev = _select_pdev(instance, surface); + if (pdev == NULL) { log_output(LOG_FATAL, "No device meets minimum requirements for rendering"); - return NULL; + rune_abort(); } - struct vkdev *dev = rune_alloc(sizeof(struct vkdev)); - dev->pdev = pdevs[selected_pdev]; + struct vkdev *dev = rune_calloc(0, sizeof(struct vkdev)); + dev->pdev = pdev; - VkQueueFamilyProperties *qfam_props; - int num_qfams = _query_qfam_data(surface, pdevs[selected_pdev], &qfam_props); - VkBool32 present_support; - for (int i = 0; i < num_qfams; i++) { - vkassert(vkGetPhysicalDeviceSurfaceSupportKHR(dev->pdev, i, surface, &present_support)); - if (present_support == VK_TRUE && i != dev->gfx_index) { - dev->pres_index = i; - } - dev->gfx_index = _get_qfam_index(num_qfams, VK_QUEUE_GRAPHICS_BIT, qfam_props); - dev->tsfr_index = _get_qfam_index(num_qfams, VK_QUEUE_TRANSFER_BIT, qfam_props); - dev->comp_index = _get_qfam_index(num_qfams, VK_QUEUE_COMPUTE_BIT, qfam_props); + dev->queues[0].index = gfx_qfam; + dev->queues[1].index = tsfr_qfam; + dev->queues[2].index = comp_qfam; + dev->queues[3].index = pres_qfam; float queue_priority = 1.0f; VkDeviceQueueCreateInfo qcinfos[3]; - qcinfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - qcinfos[0].queueFamilyIndex = dev->gfx_index; - qcinfos[0].queueCount = 1; - qcinfos[0].flags = 0; - qcinfos[0].pNext = NULL; - qcinfos[0].pQueuePriorities = &queue_priority; - - qcinfos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - qcinfos[1].queueFamilyIndex = dev->tsfr_index; - qcinfos[1].queueCount = 1; - qcinfos[1].flags = 0; - qcinfos[1].pNext = NULL; - qcinfos[1].pQueuePriorities = &queue_priority; - - qcinfos[2].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - qcinfos[2].queueFamilyIndex = dev->comp_index; - qcinfos[2].queueCount = 1; - qcinfos[2].flags = 0; - qcinfos[2].pNext = NULL; - qcinfos[2].pQueuePriorities = &queue_priority; + for (int i = 0; i < 3; i++) { + qcinfos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + qcinfos[i].pNext = NULL; + qcinfos[i].flags = 0; + qcinfos[i].queueFamilyIndex = dev->queues[i].index; + qcinfos[i].queueCount = 1; + qcinfos[i].pQueuePriorities = &queue_priority; + } struct vkdev_data pdata; - _query_pdev_data(pdevs[selected_pdev], &pdata); + _query_pdev_data(pdev, &pdata); VkDeviceCreateInfo dcinfo; dcinfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; dcinfo.pNext = NULL; dcinfo.flags = 0; - dcinfo.queueCreateInfoCount = 2; + dcinfo.queueCreateInfoCount = 3; dcinfo.pQueueCreateInfos = qcinfos; dcinfo.enabledLayerCount = 0; dcinfo.ppEnabledLayerNames = NULL; @@ -142,32 +154,14 @@ struct vkdev* create_vkdev(VkInstance instance, VkSurfaceKHR surface) { dcinfo.pEnabledFeatures = &pdata.pdev_feats; vkassert(vkCreateDevice(dev->pdev, &dcinfo, NULL, &dev->ldev)); - vkGetDeviceQueue(dev->ldev, dev->gfx_index, 0, &dev->gfx_queue); - if (dev->gfx_queue == NULL) { - log_output(LOG_FATAL, "Error creating Vulkan graphics queue"); - rune_abort(); - } - vkGetDeviceQueue(dev->ldev, dev->tsfr_index, 0, &dev->tsfr_queue); - if (dev->tsfr_queue == NULL) { - log_output(LOG_FATAL, "Error creating Vulkan transfer queue"); - rune_abort(); - } - vkGetDeviceQueue(dev->ldev, dev->pres_index, 0, &dev->pres_queue); - if (dev->pres_queue == NULL) { - log_output(LOG_FATAL, "Error creating Vulkan present queue"); - rune_abort(); - } - vkGetDeviceQueue(dev->ldev, dev->comp_index, 0, &dev->comp_queue); - if (dev->comp_queue == NULL) { - log_output(LOG_FATAL, "Error creating Vulkan compute queue"); - rune_abort(); - } + for (uint32_t i = 0; i < 3; i++) + _create_queue(dev, i, 0); VkCommandPoolCreateInfo pcinfo; pcinfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; pcinfo.pNext = NULL; pcinfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - pcinfo.queueFamilyIndex = dev->gfx_index; + pcinfo.queueFamilyIndex = dev->queues[0].index; vkassert(vkCreateCommandPool(dev->ldev, &pcinfo, NULL, &dev->cmd_pool)); log_output(LOG_DEBUG, "Initialized new logical device"); diff --git a/render/vulkan/device.h b/render/vulkan/device.h index 6bdd4f5..e498137 100644 --- a/render/vulkan/device.h +++ b/render/vulkan/device.h @@ -34,18 +34,17 @@ struct vkswapchain_data { uint32_t present_count; }; +struct vkqueue { + uint32_t index; + uint32_t qfam; + VkQueue handle; +}; + struct vkdev { VkPhysicalDevice pdev; VkDevice ldev; struct vkswapchain_data scdata; - uint32_t gfx_index; - uint32_t pres_index; - uint32_t tsfr_index; - uint32_t comp_index; - VkQueue gfx_queue; - VkQueue pres_queue; - VkQueue tsfr_queue; - VkQueue comp_queue; + struct vkqueue queues[4]; VkCommandPool cmd_pool; VkFormat depth_format; }; diff --git a/render/vulkan/swapchain.c b/render/vulkan/swapchain.c index 1247c9a..c6cea29 100644 --- a/render/vulkan/swapchain.c +++ b/render/vulkan/swapchain.c @@ -37,8 +37,8 @@ struct vkswapchain* create_swapchain(struct vksurface *surface, struct vkdev *de cinfo.presentMode = VK_PRESENT_MODE_MAILBOX_KHR; cinfo.clipped = VK_TRUE; cinfo.oldSwapchain = NULL; - if (dev->gfx_index != dev->pres_index) { - uint32_t qfams[] = {dev->gfx_index, dev->pres_index}; + if (dev->queues[0].index != dev->queues[3].index) { + uint32_t qfams[] = {dev->queues[0].index, dev->queues[3].index}; cinfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; cinfo.queueFamilyIndexCount = 2; cinfo.pQueueFamilyIndices = qfams; @@ -57,9 +57,10 @@ struct vkswapchain* create_swapchain(struct vksurface *surface, struct vkdev *de VkImageViewCreateInfo vcinfo; for (uint32_t i = 0; i < swapchain->img_count; i++) { vcinfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; + vcinfo.pNext = NULL; vcinfo.image = swapchain->images[i]; vcinfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - vcinfo.format = swapchain->format; + vcinfo.format = swapchain->format_khr.format; vcinfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; vcinfo.subresourceRange.baseMipLevel = 0; vcinfo.subresourceRange.levelCount = 1; @@ -103,10 +104,10 @@ void vkswapchain_present(struct vkswapchain *swapchain, struct vkdev *dev) { pinfo.pWaitSemaphores = &swapchain->render_complete; pinfo.swapchainCount = 1; pinfo.pSwapchains = &swapchain->handle; - pinfo.pImageIndices = &dev->pres_index; + pinfo.pImageIndices = &dev->queues[3].index; pinfo.pResults = NULL; - VkResult res = vkQueuePresentKHR(dev->pres_queue, &pinfo); + VkResult res = vkQueuePresentKHR(dev->queues[3].handle, &pinfo); if (res == VK_ERROR_OUT_OF_DATE_KHR || res == VK_SUBOPTIMAL_KHR) STUBBED("Recreate swapchain"); else if (res != VK_SUCCESS) -- cgit v1.2.3