diff --git a/src/main.c b/src/main.c index 4f3fb41..46bc3ba 100644 --- a/src/main.c +++ b/src/main.c @@ -21,8 +21,19 @@ typedef struct ApplicationState { GLFWwindow* window; //information about the connection between application and vulkan itself VkInstance instance; + //the physical gpu + VkPhysicalDevice physical_device; + //the logical device including the features we wish to use + VkDevice device; + //the queue for draw commands + VkQueue graphics_queue; } ApplicationState; +typedef struct QueueFamilyIndices { + bool graphics_present; + uint32_t graphics_queue; +} QueueFamilyIndices; + void create_window(ApplicationState* state) { glfwInit(); @@ -56,6 +67,8 @@ bool check_validation_layer_support() { } } + free (available_layers); + return true; } @@ -118,8 +131,106 @@ void create_instance(ApplicationState* state) { free(extensions); } +QueueFamilyIndices find_queue_families(VkPhysicalDevice device) { + struct QueueFamilyIndices ret = {0}; + uint32_t queue_family_count = 0; + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, NULL); + VkQueueFamilyProperties* queue_fam_props = malloc(sizeof(VkQueueFamilyProperties) * queue_family_count); + vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_family_count, queue_fam_props); + + for (int i = 0; i < queue_family_count; i++) { + if (queue_fam_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { + ret.graphics_present = true; + ret.graphics_queue = i; + } + } + + free(queue_fam_props); + + return ret; +} + +void pick_physical_device(ApplicationState* state) { + uint32_t device_count = 0; + vkEnumeratePhysicalDevices(state->instance, &device_count, NULL); + + if (device_count == 0) { + printf("vulkan is not supported\n"); + exit(1); + } + + VkPhysicalDevice* devices = malloc(sizeof(VkPhysicalDevice) * device_count); + vkEnumeratePhysicalDevices(state->instance, &device_count, devices); + + //now let's check if any device is suitable for our usage + int i; + for (i = 0; i < device_count; i++) { + VkPhysicalDevice device = devices[i]; + + VkPhysicalDeviceProperties device_props; + vkGetPhysicalDeviceProperties(device, &device_props); + + VkPhysicalDeviceFeatures device_features; + vkGetPhysicalDeviceFeatures(device, &device_features); + + QueueFamilyIndices families = find_queue_families(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); + break; + } + } + + state->physical_device = devices[i]; + free(devices); +} + +void create_logical_device(ApplicationState* state) { + //we already ensured that a graphics queue exists + QueueFamilyIndices indices = find_queue_families(state->physical_device); + + //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; + + //for now we won't use any features + VkPhysicalDeviceFeatures device_features = {0}; + + //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.pEnabledFeatures = &device_features; + create_info.enabledExtensionCount = 0; + + if (VALIDATE) { + create_info.enabledLayerCount = ARRSIZE(validation_layers); + create_info.ppEnabledLayerNames = validation_layers; + } else { + create_info.enabledLayerCount = 0;; + } + + if (vkCreateDevice(state->physical_device, &create_info, NULL, &state->device) != VK_SUCCESS) { + printf("Error creating logical device\n"); + exit(1); + } + + //get a handle to the queue + vkGetDeviceQueue(state->device, indices.graphics_queue, 0, &state->graphics_queue); + + printf("Logical device created\n"); +} + void init_vulkan(ApplicationState* state) { create_instance(state); + pick_physical_device(state); + create_logical_device(state); } void main_loop(ApplicationState* state) { @@ -129,6 +240,7 @@ void main_loop(ApplicationState* state) { } void terminate(ApplicationState* state) { + vkDestroyDevice(state->device, NULL); vkDestroyInstance(state->instance, NULL); glfwDestroyWindow(state->window); glfwTerminate();