|
|
|
@ -27,11 +27,17 @@ typedef struct ApplicationState {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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); |
|
|
|
|
|
|
|
|
|
//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; |
|
|
|
|
//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); |
|
|
|
|
|
|
|
|
|
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_info.pQueuePriorities = &prio; |
|
|
|
|
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) {
@@ -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) {
@@ -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) {
@@ -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) {
@@ -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(); |
|
|
|
|