|
|
|
@ -21,8 +21,19 @@ typedef struct ApplicationState {
@@ -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() {
@@ -56,6 +67,8 @@ bool check_validation_layer_support() {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
free (available_layers); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -118,8 +131,106 @@ void create_instance(ApplicationState* state) {
@@ -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) {
@@ -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(); |
|
|
|
|