Added staged buffers and indexed triangle drawing

main
noah metz 2024-01-08 11:59:58 -07:00
parent 4e2a8cf156
commit 960f0b94ea
1 changed files with 245 additions and 84 deletions

@ -18,11 +18,15 @@ typedef struct QueueIndicesStruct {
uint32_t present_family; uint32_t present_family;
uint32_t present_index; uint32_t present_index;
uint32_t transfer_family;
uint32_t transfer_index;
} QueueIndices; } QueueIndices;
typedef struct QueuesStruct { typedef struct QueuesStruct {
VkQueue graphics; VkQueue graphics;
VkQueue present; VkQueue present;
VkQueue transfer;
} Queues; } Queues;
typedef struct SwapchainDetailsStruct { typedef struct SwapchainDetailsStruct {
@ -79,10 +83,12 @@ typedef struct VulkanContextStruct {
VkRenderPass render_pass; VkRenderPass render_pass;
VkCommandPool graphics_command_pool; VkCommandPool graphics_command_pool;
VkCommandPool transfer_command_pool;
VkPipelineLayout triangle_pipeline_layout; VkPipelineLayout triangle_pipeline_layout;
VkPipeline triangle_pipeline; VkPipeline triangle_pipeline;
AllocatedBuffer triangle_buffer; AllocatedBuffer triangle_vertex_buffer;
AllocatedBuffer triangle_index_buffer;
uint32_t current_frame; uint32_t current_frame;
} VulkanContext; } VulkanContext;
@ -93,13 +99,22 @@ struct Vertex{
}; };
const struct Vertex vertices[] = { const struct Vertex vertices[] = {
{.pos = { 0.0f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}}, {.pos = {-0.5f, -0.5f}, .color = {1.0f, 0.0f, 0.0f}},
{.pos = { 0.5f, 0.5f}, .color = {0.0f, 1.0f, 0.0f}}, {.pos = { 0.5f, -0.5f}, .color = {0.0f, 1.0f, 0.0f}},
{.pos = {-0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}}, {.pos = { 0.5f, 0.5f}, .color = {0.0f, 0.0f, 1.0f}},
{.pos = {-0.5f, 0.5f}, .color = {1.0f, 1.0f, 1.0f}},
};
const uint16_t indices[] = {
0, 1, 2, 2, 3, 0,
}; };
const char * validation_layers[] = { const char * validation_layers[] = {
"VK_LAYER_KHRONOS_validation", "VK_LAYER_KHRONOS_validation",
//"VK_LAYER_LUNARG_api_dump",
//"VK_LAYER_KHRONOS_profiles",
//"VK_LAYER_KHRONOS_synchronization2",
"VK_LAYER_KHRONOS_shader_object",
}; };
uint32_t validation_layer_count = sizeof(validation_layers) / sizeof(const char *); uint32_t validation_layer_count = sizeof(validation_layers) / sizeof(const char *);
@ -266,17 +281,20 @@ VkPhysicalDevice get_best_physical_device(VkInstance instance) {
return device; return device;
} }
struct MaybeQueueIndices { bool check_queue_indices(QueueIndices indices) {
bool valid; return ((indices.graphics_family != 0xFFFFFFFF)
QueueIndices indices; && (indices.present_family != 0xFFFFFFFF)
}; && (indices.transfer_family != 0xFFFFFFFF));
}
struct MaybeQueueIndices get_queue_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface) { QueueIndices get_queue_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface) {
struct MaybeQueueIndices ret = {}; QueueIndices indices = {};
ret.indices.graphics_family = 0xFFFFFFFF; indices.graphics_family = 0xFFFFFFFF;
ret.indices.graphics_index = 0xFFFFFFFF; indices.graphics_index = 0xFFFFFFFF;
ret.indices.present_family = 0xFFFFFFFF; indices.present_family = 0xFFFFFFFF;
ret.indices.present_index = 0xFFFFFFFF; indices.present_index = 0xFFFFFFFF;
indices.transfer_family = 0xFFFFFFFF;
indices.transfer_index = 0xFFFFFFFF;
uint32_t queue_family_count; uint32_t queue_family_count;
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, 0); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, 0);
@ -285,31 +303,43 @@ struct MaybeQueueIndices get_queue_indices(VkPhysicalDevice physical_device, VkS
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, queue_families); vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, queue_families);
for(uint32_t i = 0; for(uint32_t family_idx = 0; family_idx < queue_family_count; family_idx++) {
(i < queue_family_count) VkBool32 present_support;
&& ((ret.indices.graphics_family == 0xFFFFFFFF) || (ret.indices.present_family == 0xFFFFFFFF)); vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, family_idx, surface, &present_support);
i++) { for(uint32_t queue_idx = 0; queue_idx < queue_families[family_idx].queueCount; queue_idx++) {
if(queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) { if(((indices.graphics_family == 0xFFFFFFFF)
ret.indices.graphics_family = i; || (indices.present_family == 0xFFFFFFFF)
ret.indices.graphics_index = 0; || (indices.present_family != indices.graphics_family))
} && (queue_families[family_idx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
&& (present_support == VK_TRUE)) {
VkBool32 present_support = false; fprintf(stderr, "Selected %d:%d for graphics and present queues\n", family_idx, queue_idx);
vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support); indices.graphics_family = family_idx;
indices.graphics_index = queue_idx;
if(present_support == VK_TRUE) {
ret.indices.present_family = i; indices.present_family = family_idx;
ret.indices.present_index = 0; indices.present_index = queue_idx;
} else if((indices.graphics_family == 0xFFFFFFFF)
&& (queue_families[family_idx].queueFlags & VK_QUEUE_GRAPHICS_BIT)) {
fprintf(stderr, "Selected %d:%d for graphics queue\n", family_idx, queue_idx);
indices.graphics_family = family_idx;
indices.graphics_index = queue_idx;
} else if((indices.present_family == 0xFFFFFFFF)
&& (present_support == VK_TRUE)) {
fprintf(stderr, "Selected %d:%d for present queue\n", family_idx, queue_idx);
indices.present_family = family_idx;
indices.present_index = queue_idx;
} else if((indices.transfer_family == 0xFFFFFFFF)
&& (queue_families[family_idx].queueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))) {
fprintf(stderr, "Selected %d:%d for transfer queue\n", family_idx, queue_idx);
indices.transfer_family = family_idx;
indices.transfer_index = queue_idx;
} }
} }
if((ret.indices.graphics_family != 0xFFFFFFFF) && (ret.indices.present_family != 0xFFFFFFFF)) {
ret.valid = true;
} }
free(queue_families); free(queue_families);
return ret; return indices;
} }
VkDebugUtilsMessengerEXT create_debug_messenger(VkInstance instance) { VkDebugUtilsMessengerEXT create_debug_messenger(VkInstance instance) {
@ -318,7 +348,7 @@ VkDebugUtilsMessengerEXT create_debug_messenger(VkInstance instance) {
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {}; VkDebugUtilsMessengerCreateInfoEXT messenger_info = {};
messenger_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; messenger_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
messenger_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT; messenger_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
messenger_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; messenger_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_DEVICE_ADDRESS_BINDING_BIT_EXT;
messenger_info.pfnUserCallback = debug_callback; messenger_info.pfnUserCallback = debug_callback;
messenger_info.pUserData = 0; messenger_info.pUserData = 0;
@ -390,35 +420,50 @@ VkInstance create_instance() {
VkDevice create_logical_device(VkPhysicalDevice physical_device, QueueIndices queue_indices) { VkDevice create_logical_device(VkPhysicalDevice physical_device, QueueIndices queue_indices) {
VkDevice device; VkDevice device;
VkDeviceQueueCreateInfo queue_create_info[2] = {}; uint32_t unique_families[3] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
uint32_t queue_create_count; uint32_t unique_family_queues[3] = {0, 0, 0};
float default_queue_priority = 1.0f; uint32_t unique_family_count = 0;
if(queue_indices.graphics_family == queue_indices.present_family) {
queue_create_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; uint32_t queue_family[] = {queue_indices.transfer_family, queue_indices.graphics_family, queue_indices.present_family};
queue_create_info[0].queueFamilyIndex = queue_indices.graphics_family; uint32_t unique_queue_count = 3;
queue_create_info[0].queueCount = 1; if((queue_indices.graphics_family == queue_indices.present_family)
queue_create_info[0].pQueuePriorities = &default_queue_priority; && (queue_indices.graphics_index == queue_indices.present_index)) {
queue_create_count = 1; unique_queue_count = 2;
} else { }
queue_create_info[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info[0].queueFamilyIndex = queue_indices.graphics_family;
queue_create_info[0].queueCount = 1;
queue_create_info[0].pQueuePriorities = &default_queue_priority;
queue_create_info[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; for(uint32_t queue_idx = 0; queue_idx < unique_queue_count; queue_idx++) {
queue_create_info[1].queueFamilyIndex = queue_indices.present_family; uint32_t idx = 0xFFFFFFFF;
queue_create_info[1].queueCount = 1; for(uint32_t check_idx = 0; check_idx < unique_family_count; check_idx++) {
queue_create_info[1].pQueuePriorities = &default_queue_priority; if(queue_family[queue_idx] == unique_families[check_idx]) {
queue_create_count = 2; idx = check_idx;
break;
}
} }
if(idx == 0xFFFFFFFF) {
unique_families[unique_family_count] = queue_family[queue_idx];
unique_family_queues[unique_family_count] += 1;
unique_family_count += 1;
} else {
unique_family_queues[idx] += 1;
}
}
VkDeviceQueueCreateInfo queue_create_info[3] = {};
float default_queue_priority = 1.0f;
for(uint32_t i = 0; i < unique_family_count; i++) {
queue_create_info[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info[i].queueFamilyIndex = unique_families[i];
queue_create_info[i].queueCount = unique_family_queues[i];
queue_create_info[i].pQueuePriorities = &default_queue_priority;
}
VkPhysicalDeviceFeatures device_features = {}; VkPhysicalDeviceFeatures device_features = {};
VkDeviceCreateInfo device_create_info = {}; VkDeviceCreateInfo device_create_info = {};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.pQueueCreateInfos = queue_create_info; device_create_info.pQueueCreateInfos = queue_create_info;
device_create_info.queueCreateInfoCount = queue_create_count; device_create_info.queueCreateInfoCount = unique_family_count;
device_create_info.pEnabledFeatures = &device_features; device_create_info.pEnabledFeatures = &device_features;
device_create_info.enabledExtensionCount = device_extension_count; device_create_info.enabledExtensionCount = device_extension_count;
@ -753,51 +798,150 @@ uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter
return 0xFFFFFFFF; return 0xFFFFFFFF;
} }
AllocatedBuffer create_vertex_buffer(VkPhysicalDevice physical_device, VkDevice device, void* data, uint32_t size) { AllocatedBuffer allocate_buffer(VkPhysicalDevice physical_device, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) {
AllocatedBuffer allocated_buffer = {}; AllocatedBuffer ret = {};
allocated_buffer.buffer = VK_NULL_HANDLE; ret.memory = VK_NULL_HANDLE;
allocated_buffer.memory = VK_NULL_HANDLE; ret.buffer = VK_NULL_HANDLE;
VkBufferCreateInfo buffer_info = {}; VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size; buffer_info.size = size;
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; buffer_info.usage = usage;
buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
VkResult result = vkCreateBuffer(device, &buffer_info, 0, &allocated_buffer.buffer); VkResult result = vkCreateBuffer(device, &buffer_info, 0, &ret.buffer);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
return allocated_buffer; ret.buffer = VK_NULL_HANDLE;
ret.memory = VK_NULL_HANDLE;
return ret;
} }
VkMemoryRequirements memory_requirements; VkMemoryRequirements memory_requirements;
vkGetBufferMemoryRequirements(device, allocated_buffer.buffer, &memory_requirements); vkGetBufferMemoryRequirements(device, ret.buffer, &memory_requirements);
VkMemoryAllocateInfo alloc_info = {}; VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
alloc_info.allocationSize = memory_requirements.size; alloc_info.allocationSize = memory_requirements.size;
alloc_info.memoryTypeIndex = find_memory_type(physical_device, memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); alloc_info.memoryTypeIndex = find_memory_type(physical_device, memory_requirements.memoryTypeBits, properties);
result = vkAllocateMemory(device, &alloc_info, 0, &allocated_buffer.memory); result = vkAllocateMemory(device, &alloc_info, 0, &ret.memory);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
return allocated_buffer; vkDestroyBuffer(device, ret.buffer, 0);
ret.buffer = VK_NULL_HANDLE;
ret.memory = VK_NULL_HANDLE;
return ret;
}
result = vkBindBufferMemory(device, ret.buffer, ret.memory, 0);
if(result != VK_SUCCESS) {
vkDestroyBuffer(device, ret.buffer, 0);
ret.buffer = VK_NULL_HANDLE;
ret.memory = VK_NULL_HANDLE;
return ret;
} }
result = vkBindBufferMemory(device, allocated_buffer.buffer, allocated_buffer.memory, 0); return ret;
}
void deallocate_buffer(VkDevice device, AllocatedBuffer buffer) {
vkDestroyBuffer(device, buffer.buffer, 0);
vkFreeMemory(device, buffer.memory, 0);
};
VkResult command_copy_buffers(VkDevice device, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBuffer source, VkBuffer dest, VkDeviceSize size) {
VkCommandBufferAllocateInfo command_info = {};
command_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
command_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
command_info.commandPool = transfer_pool;
command_info.commandBufferCount = 1;
VkCommandBuffer command_buffer;
VkResult result = vkAllocateCommandBuffers(device, &command_info, &command_buffer);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
return allocated_buffer; return result;
} }
VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
result = vkBeginCommandBuffer(command_buffer, &begin_info);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
VkBufferCopy copy_region = {};
copy_region.srcOffset = 0;
copy_region.dstOffset = 0;
copy_region.size = size;
vkCmdCopyBuffer(command_buffer, source, dest, 1, &copy_region);
result = vkEndCommandBuffer(command_buffer);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
VkSubmitInfo submit_info = {};
submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submit_info.commandBufferCount = 1;
submit_info.pCommandBuffers = &command_buffer;
result = vkQueueSubmit(transfer_queue, 1, &submit_info, 0);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
result = vkQueueWaitIdle(transfer_queue);
if(result != VK_SUCCESS) {
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return VK_SUCCESS;
}
AllocatedBuffer create_populated_buffer(VkPhysicalDevice physical_device, VkDevice device, void* data, VkDeviceSize size, VkCommandPool transfer_pool, VkQueue transfer_queue, VkBufferUsageFlags usage) {
AllocatedBuffer staging_buffer = {};
AllocatedBuffer vertex_buffer = {};
staging_buffer = allocate_buffer(physical_device, device, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
if(staging_buffer.memory == VK_NULL_HANDLE) {
return vertex_buffer;
}
void* buffer_data; void* buffer_data;
result = vkMapMemory(device, allocated_buffer.memory, 0, buffer_info.size, 0, &buffer_data); VkResult result = vkMapMemory(device, staging_buffer.memory, 0, size, 0, &buffer_data);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
return allocated_buffer; deallocate_buffer(device, staging_buffer);
return vertex_buffer;
} }
memcpy(buffer_data, data, size); memcpy(buffer_data, data, size);
vkUnmapMemory(device, allocated_buffer.memory); vkUnmapMemory(device, staging_buffer.memory);
vertex_buffer = allocate_buffer(physical_device, device, size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | usage, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
if(vertex_buffer.memory == VK_NULL_HANDLE) {
deallocate_buffer(device, staging_buffer);
return vertex_buffer;
}
result = command_copy_buffers(device, transfer_pool, transfer_queue, staging_buffer.buffer, vertex_buffer.buffer, size);
if(result != VK_SUCCESS) {
deallocate_buffer(device, staging_buffer);
deallocate_buffer(device, vertex_buffer);
vertex_buffer.buffer = VK_NULL_HANDLE;
vertex_buffer.memory = VK_NULL_HANDLE;
return vertex_buffer;
}
return allocated_buffer; return vertex_buffer;
} }
VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipelineLayout layout, VkRenderPass render_pass) { VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipelineLayout layout, VkRenderPass render_pass) {
@ -943,7 +1087,7 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) {
return command_pool; return command_pool;
} }
VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t image_index, VkRenderPass render_pass, VkFramebuffer* framebuffers, VkExtent2D extent, VkPipeline graphics_pipeline, VkBuffer vertex_buffer, uint32_t num_vertices) { VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t image_index, VkRenderPass render_pass, VkFramebuffer* framebuffers, VkExtent2D extent, VkPipeline graphics_pipeline, VkBuffer vertex_buffer, VkBuffer index_buffer, uint32_t num_vertices) {
VkCommandBufferBeginInfo begin_info = {}; VkCommandBufferBeginInfo begin_info = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = 0; begin_info.flags = 0;
@ -971,6 +1115,7 @@ VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t
VkBuffer vertex_buffers[] = {vertex_buffer}; VkBuffer vertex_buffers[] = {vertex_buffer};
VkDeviceSize offsets[] = {0}; VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
vkCmdBindIndexBuffer(command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT16);
VkViewport viewport = {}; VkViewport viewport = {};
viewport.x = 0.0f; viewport.x = 0.0f;
@ -987,7 +1132,7 @@ VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t
scissor.extent = extent; scissor.extent = extent;
vkCmdSetScissor(command_buffer, 0, 1, &scissor); vkCmdSetScissor(command_buffer, 0, 1, &scissor);
vkCmdDraw(command_buffer, num_vertices, 1, 0, 0); vkCmdDrawIndexed(command_buffer, num_vertices, 1, 0, 0, 0);
vkCmdEndRenderPass(command_buffer); vkCmdEndRenderPass(command_buffer);
return vkEndCommandBuffer(command_buffer); return vkEndCommandBuffer(command_buffer);
@ -1088,12 +1233,12 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->surface = surface; context->surface = surface;
} }
struct MaybeQueueIndices maybe_indices = get_queue_indices(context->physical_device, context->surface); QueueIndices queue_indices = get_queue_indices(context->physical_device, context->surface);
if(maybe_indices.valid == false) { if(check_queue_indices(queue_indices) == false) {
fprintf(stderr, "failed to get vulkan queue indices\n"); fprintf(stderr, "failed to get vulkan queue indices\n");
return 0; return 0;
} else { } else {
context->queue_indices = maybe_indices.indices; context->queue_indices = queue_indices;
} }
VkDevice device = create_logical_device(context->physical_device, context->queue_indices); VkDevice device = create_logical_device(context->physical_device, context->queue_indices);
@ -1105,6 +1250,7 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
} }
vkGetDeviceQueue(device, context->queue_indices.graphics_family, context->queue_indices.graphics_index, &context->queues.graphics); vkGetDeviceQueue(device, context->queue_indices.graphics_family, context->queue_indices.graphics_index, &context->queues.graphics);
vkGetDeviceQueue(device, context->queue_indices.present_family, context->queue_indices.present_index, &context->queues.present); vkGetDeviceQueue(device, context->queue_indices.present_family, context->queue_indices.present_index, &context->queues.present);
vkGetDeviceQueue(device, context->queue_indices.transfer_family, context->queue_indices.transfer_index, &context->queues.transfer);
struct MaybeSwapchainDetails maybe_details = get_swapchain_details(context->physical_device, context->surface); struct MaybeSwapchainDetails maybe_details = get_swapchain_details(context->physical_device, context->surface);
if(maybe_details.valid == false) { if(maybe_details.valid == false) {
@ -1159,12 +1305,20 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->swapchain_framebuffers = framebuffers; context->swapchain_framebuffers = framebuffers;
} }
VkCommandPool command_pool = create_command_pool(context->device, context->queue_indices.graphics_family); VkCommandPool graphics_command_pool = create_command_pool(context->device, context->queue_indices.graphics_family);
if(command_pool == VK_NULL_HANDLE) { if(graphics_command_pool == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create vulkan graphics command pool"); fprintf(stderr, "failed to create vulkan graphics command pool");
return 0; return 0;
} else { } else {
context->graphics_command_pool = command_pool; context->graphics_command_pool = graphics_command_pool;
}
VkCommandPool transfer_command_pool = create_command_pool(context->device, context->queue_indices.transfer_family);
if(transfer_command_pool == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create vulkan transfer command pool");
return 0;
} else {
context->transfer_command_pool = transfer_command_pool;
} }
context->max_frames_in_flight = max_frames_in_flight; context->max_frames_in_flight = max_frames_in_flight;
@ -1217,11 +1371,18 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->triangle_pipeline = triangle_pipeline; context->triangle_pipeline = triangle_pipeline;
} }
AllocatedBuffer triangle_buffer = create_vertex_buffer(context->physical_device, context->device, (void*)vertices, sizeof(vertices)); AllocatedBuffer triangle_vertex_buffer = create_populated_buffer(context->physical_device, context->device, (void*)vertices, sizeof(vertices), context->transfer_command_pool, context->queues.transfer, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
if(triangle_buffer.memory == VK_NULL_HANDLE) { if(triangle_vertex_buffer.memory == VK_NULL_HANDLE) {
fprintf(stderr, "failed to allocate vulkan buffer for triangle buffer\n");
} else {
context->triangle_vertex_buffer = triangle_vertex_buffer;
}
AllocatedBuffer triangle_index_buffer = create_populated_buffer(context->physical_device, context->device, (void*)indices, sizeof(indices), context->transfer_command_pool, context->queues.transfer, VK_BUFFER_USAGE_INDEX_BUFFER_BIT);
if(triangle_index_buffer.memory == VK_NULL_HANDLE) {
fprintf(stderr, "failed to allocate vulkan buffer for triangle buffer\n"); fprintf(stderr, "failed to allocate vulkan buffer for triangle buffer\n");
} else { } else {
context->triangle_buffer = triangle_buffer; context->triangle_index_buffer = triangle_index_buffer;
} }
return context; return context;
@ -1250,7 +1411,7 @@ VkResult draw_frame(VulkanContext* context) {
return result; return result;
} }
result = record_command_buffer_triangle(context->swapchain_command_buffers[context->current_frame], image_index, context->render_pass, context->swapchain_framebuffers, context->swapchain_extent, context->triangle_pipeline, context->triangle_buffer.buffer, 3); result = record_command_buffer_triangle(context->swapchain_command_buffers[context->current_frame], image_index, context->render_pass, context->swapchain_framebuffers, context->swapchain_extent, context->triangle_pipeline, context->triangle_vertex_buffer.buffer, context->triangle_index_buffer.buffer, 6);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
return result; return result;
} }