diff --git a/src/main.c b/src/main.c index 46bc3ba..d194e4d 100644 --- a/src/main.c +++ b/src/main.c @@ -27,11 +27,17 @@ typedef struct ApplicationState { VkDevice device; //the queue for draw commands VkQueue graphics_queue; + //the window surface + VkSurfaceKHR surface; + //presentation queue + VkQueue present_queue; } ApplicationState; typedef struct QueueFamilyIndices { bool graphics_present; uint32_t graphics_queue; + bool present_present; + uint32_t present_queue; } QueueFamilyIndices; void create_window(ApplicationState* state) { @@ -131,7 +137,7 @@ void create_instance(ApplicationState* state) { free(extensions); } -QueueFamilyIndices find_queue_families(VkPhysicalDevice device) { +QueueFamilyIndices find_queue_families(ApplicationState* state, VkPhysicalDevice device) { struct QueueFamilyIndices ret = {0}; uint32_t queue_family_count = 0; vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, NULL); @@ -143,6 +149,14 @@ QueueFamilyIndices find_queue_families(VkPhysicalDevice device) { ret.graphics_present = true; ret.graphics_queue = i; } + + VkBool32 present_support = false; + vkGetPhysicalDeviceSurfaceSupportKHR(device, i, state->surface, &present_support); + + if (present_support) { + ret.present_present = true; + ret.present_queue = i; + } } free(queue_fam_props); @@ -173,11 +187,11 @@ void pick_physical_device(ApplicationState* state) { VkPhysicalDeviceFeatures device_features; vkGetPhysicalDeviceFeatures(device, &device_features); - QueueFamilyIndices families = find_queue_families(device); + QueueFamilyIndices families = find_queue_families(state, device); //for now we only require that a graphics queue is present - if (families.graphics_present) { - printf("graphics queue at %x\n", families.graphics_queue); + if (families.graphics_present && families.present_present) { + printf("graphics queue at %x, present queue at %x\n", families.graphics_queue, families.present_queue); break; } } @@ -186,17 +200,40 @@ void pick_physical_device(ApplicationState* state) { free(devices); } +int cmp(const void* a, const void* b) { + return (*(int*)a - *(int*)b); +} + void create_logical_device(ApplicationState* state) { - //we already ensured that a graphics queue exists - QueueFamilyIndices indices = find_queue_families(state->physical_device); + //we already ensured that all of the required queues exist + QueueFamilyIndices indices = find_queue_families(state, state->physical_device); + + //now we need to find out the number of unique queues we need to create + //since there aren't going to be many queues in this case we don't need + //a particularly efficient algorithm + uint32_t indices_array[] = {indices.present_queue, indices.graphics_queue}; + qsort(indices_array, ARRSIZE(indices_array), sizeof(uint32_t), cmp); + + int unique_queues[ARRSIZE(indices_array)] = {0}; + int j = 0; + + for (int i = 0; i < ARRSIZE(indices_array) - 1; i++) { + if (indices_array[i] != indices_array[i + 1]) { + unique_queues[j++] = indices_array[i]; + } + } + unique_queues[j++] = unique_queues[ARRSIZE(indices_array) - 1]; + printf("number of queues: %x\n", j); - //multiple of these will be needed once we require other kinds of queues - VkDeviceQueueCreateInfo queue_create_info = {0}; - queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queue_create_info.queueFamilyIndex = indices.graphics_queue; - queue_create_info.queueCount = 1; - float prio = 1.0f; - queue_create_info.pQueuePriorities = &prio; + VkDeviceQueueCreateInfo* queue_create_infos = calloc(j, sizeof(VkDeviceCreateInfo)); + + for (int i = 0; i < j; i++) { + queue_create_infos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queue_create_infos[i].queueFamilyIndex = unique_queues[i]; + queue_create_infos[i].queueCount = 1; + float prio = 1.0f; + queue_create_infos[i].pQueuePriorities = &prio; + } //for now we won't use any features VkPhysicalDeviceFeatures device_features = {0}; @@ -204,8 +241,8 @@ void create_logical_device(ApplicationState* state) { //now create a logical device knowing which features and queues we need VkDeviceCreateInfo create_info = {0}; create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - create_info.pQueueCreateInfos = &queue_create_info; - create_info.queueCreateInfoCount = 1; + create_info.pQueueCreateInfos = queue_create_infos; + create_info.queueCreateInfoCount = j; create_info.pEnabledFeatures = &device_features; create_info.enabledExtensionCount = 0; @@ -216,6 +253,7 @@ void create_logical_device(ApplicationState* state) { create_info.enabledLayerCount = 0;; } + printf("creating logical device\n"); if (vkCreateDevice(state->physical_device, &create_info, NULL, &state->device) != VK_SUCCESS) { printf("Error creating logical device\n"); exit(1); @@ -223,12 +261,21 @@ void create_logical_device(ApplicationState* state) { //get a handle to the queue vkGetDeviceQueue(state->device, indices.graphics_queue, 0, &state->graphics_queue); + vkGetDeviceQueue(state->device, indices.present_queue, 0, &state->present_queue); printf("Logical device created\n"); } +void create_surface(ApplicationState* state) { + if (glfwCreateWindowSurface(state->instance, state->window, NULL, &state->surface) != VK_SUCCESS) { + printf("Surface creation failed\n"); + exit(1); + } +} + void init_vulkan(ApplicationState* state) { create_instance(state); + create_surface(state); pick_physical_device(state); create_logical_device(state); } @@ -241,6 +288,7 @@ void main_loop(ApplicationState* state) { void terminate(ApplicationState* state) { vkDestroyDevice(state->device, NULL); + vkDestroySurfaceKHR(state->instance, state->surface, NULL); vkDestroyInstance(state->instance, NULL); glfwDestroyWindow(state->window); glfwTerminate();