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_index;
uint32_t transfer_family;
uint32_t transfer_index;
} QueueIndices;
typedef struct QueuesStruct {
VkQueue graphics;
VkQueue present;
VkQueue transfer;
} Queues;
typedef struct SwapchainDetailsStruct {
@ -79,10 +83,12 @@ typedef struct VulkanContextStruct {
VkRenderPass render_pass;
VkCommandPool graphics_command_pool;
VkCommandPool transfer_command_pool;
VkPipelineLayout triangle_pipeline_layout;
VkPipeline triangle_pipeline;
AllocatedBuffer triangle_buffer;
AllocatedBuffer triangle_vertex_buffer;
AllocatedBuffer triangle_index_buffer;
uint32_t current_frame;
} VulkanContext;
@ -93,13 +99,22 @@ struct Vertex{
};
const struct Vertex vertices[] = {
{.pos = { 0.0f, -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, 0.0f, 1.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, 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[] = {
"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 *);
@ -266,17 +281,20 @@ VkPhysicalDevice get_best_physical_device(VkInstance instance) {
return device;
}
struct MaybeQueueIndices {
bool valid;
QueueIndices indices;
};
bool check_queue_indices(QueueIndices indices) {
return ((indices.graphics_family != 0xFFFFFFFF)
&& (indices.present_family != 0xFFFFFFFF)
&& (indices.transfer_family != 0xFFFFFFFF));
}
struct MaybeQueueIndices get_queue_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface) {
struct MaybeQueueIndices ret = {};
ret.indices.graphics_family = 0xFFFFFFFF;
ret.indices.graphics_index = 0xFFFFFFFF;
ret.indices.present_family = 0xFFFFFFFF;
ret.indices.present_index = 0xFFFFFFFF;
QueueIndices get_queue_indices(VkPhysicalDevice physical_device, VkSurfaceKHR surface) {
QueueIndices indices = {};
indices.graphics_family = 0xFFFFFFFF;
indices.graphics_index = 0xFFFFFFFF;
indices.present_family = 0xFFFFFFFF;
indices.present_index = 0xFFFFFFFF;
indices.transfer_family = 0xFFFFFFFF;
indices.transfer_index = 0xFFFFFFFF;
uint32_t queue_family_count;
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);
for(uint32_t i = 0;
(i < queue_family_count)
&& ((ret.indices.graphics_family == 0xFFFFFFFF) || (ret.indices.present_family == 0xFFFFFFFF));
i++) {
if(queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
ret.indices.graphics_family = i;
ret.indices.graphics_index = 0;
}
VkBool32 present_support = false;
vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support);
if(present_support == VK_TRUE) {
ret.indices.present_family = i;
ret.indices.present_index = 0;
for(uint32_t family_idx = 0; family_idx < queue_family_count; family_idx++) {
VkBool32 present_support;
vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, family_idx, surface, &present_support);
for(uint32_t queue_idx = 0; queue_idx < queue_families[family_idx].queueCount; queue_idx++) {
if(((indices.graphics_family == 0xFFFFFFFF)
|| (indices.present_family == 0xFFFFFFFF)
|| (indices.present_family != indices.graphics_family))
&& (queue_families[family_idx].queueFlags & VK_QUEUE_GRAPHICS_BIT)
&& (present_support == VK_TRUE)) {
fprintf(stderr, "Selected %d:%d for graphics and present queues\n", family_idx, queue_idx);
indices.graphics_family = family_idx;
indices.graphics_index = queue_idx;
indices.present_family = family_idx;
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);
return ret;
return indices;
}
VkDebugUtilsMessengerEXT create_debug_messenger(VkInstance instance) {
@ -318,7 +348,7 @@ VkDebugUtilsMessengerEXT create_debug_messenger(VkInstance instance) {
VkDebugUtilsMessengerCreateInfoEXT messenger_info = {};
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.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.pUserData = 0;
@ -390,35 +420,50 @@ VkInstance create_instance() {
VkDevice create_logical_device(VkPhysicalDevice physical_device, QueueIndices queue_indices) {
VkDevice device;
VkDeviceQueueCreateInfo queue_create_info[2] = {};
uint32_t queue_create_count;
float default_queue_priority = 1.0f;
if(queue_indices.graphics_family == queue_indices.present_family) {
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_count = 1;
} 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;
uint32_t unique_families[3] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
uint32_t unique_family_queues[3] = {0, 0, 0};
uint32_t unique_family_count = 0;
uint32_t queue_family[] = {queue_indices.transfer_family, queue_indices.graphics_family, queue_indices.present_family};
uint32_t unique_queue_count = 3;
if((queue_indices.graphics_family == queue_indices.present_family)
&& (queue_indices.graphics_index == queue_indices.present_index)) {
unique_queue_count = 2;
}
for(uint32_t queue_idx = 0; queue_idx < unique_queue_count; queue_idx++) {
uint32_t idx = 0xFFFFFFFF;
for(uint32_t check_idx = 0; check_idx < unique_family_count; check_idx++) {
if(queue_family[queue_idx] == unique_families[check_idx]) {
idx = check_idx;
break;
}
}
queue_create_info[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info[1].queueFamilyIndex = queue_indices.present_family;
queue_create_info[1].queueCount = 1;
queue_create_info[1].pQueuePriorities = &default_queue_priority;
queue_create_count = 2;
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 = {};
VkDeviceCreateInfo device_create_info = {};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_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.enabledExtensionCount = device_extension_count;
@ -753,51 +798,150 @@ uint32_t find_memory_type(VkPhysicalDevice physical_device, uint32_t type_filter
return 0xFFFFFFFF;
}
AllocatedBuffer create_vertex_buffer(VkPhysicalDevice physical_device, VkDevice device, void* data, uint32_t size) {
AllocatedBuffer allocated_buffer = {};
allocated_buffer.buffer = VK_NULL_HANDLE;
allocated_buffer.memory = VK_NULL_HANDLE;
AllocatedBuffer allocate_buffer(VkPhysicalDevice physical_device, VkDevice device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties) {
AllocatedBuffer ret = {};
ret.memory = VK_NULL_HANDLE;
ret.buffer = VK_NULL_HANDLE;
VkBufferCreateInfo buffer_info = {};
buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buffer_info.size = size;
buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
buffer_info.usage = usage;
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) {
return allocated_buffer;
ret.buffer = VK_NULL_HANDLE;
ret.memory = VK_NULL_HANDLE;
return ret;
}
VkMemoryRequirements memory_requirements;
vkGetBufferMemoryRequirements(device, allocated_buffer.buffer, &memory_requirements);
vkGetBufferMemoryRequirements(device, ret.buffer, &memory_requirements);
VkMemoryAllocateInfo alloc_info = {};
alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
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, &ret.memory);
if(result != VK_SUCCESS) {
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;
}
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) {
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;
}
result = vkAllocateMemory(device, &alloc_info, 0, &allocated_buffer.memory);
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) {
return allocated_buffer;
vkFreeCommandBuffers(device, transfer_pool, 1, &command_buffer);
return result;
}
result = vkBindBufferMemory(device, allocated_buffer.buffer, allocated_buffer.memory, 0);
result = vkQueueWaitIdle(transfer_queue);
if(result != VK_SUCCESS) {
return allocated_buffer;
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;
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) {
return allocated_buffer;
deallocate_buffer(device, staging_buffer);
return vertex_buffer;
}
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) {
@ -943,7 +1087,7 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) {
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 = {};
begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
begin_info.flags = 0;
@ -971,6 +1115,7 @@ VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t
VkBuffer vertex_buffers[] = {vertex_buffer};
VkDeviceSize offsets[] = {0};
vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets);
vkCmdBindIndexBuffer(command_buffer, index_buffer, 0, VK_INDEX_TYPE_UINT16);
VkViewport viewport = {};
viewport.x = 0.0f;
@ -987,7 +1132,7 @@ VkResult record_command_buffer_triangle(VkCommandBuffer command_buffer, uint32_t
scissor.extent = extent;
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);
return vkEndCommandBuffer(command_buffer);
@ -1088,12 +1233,12 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->surface = surface;
}
struct MaybeQueueIndices maybe_indices = get_queue_indices(context->physical_device, context->surface);
if(maybe_indices.valid == false) {
QueueIndices queue_indices = get_queue_indices(context->physical_device, context->surface);
if(check_queue_indices(queue_indices) == false) {
fprintf(stderr, "failed to get vulkan queue indices\n");
return 0;
} else {
context->queue_indices = maybe_indices.indices;
context->queue_indices = 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.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);
if(maybe_details.valid == false) {
@ -1159,12 +1305,20 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->swapchain_framebuffers = framebuffers;
}
VkCommandPool command_pool = create_command_pool(context->device, context->queue_indices.graphics_family);
if(command_pool == VK_NULL_HANDLE) {
VkCommandPool graphics_command_pool = create_command_pool(context->device, context->queue_indices.graphics_family);
if(graphics_command_pool == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create vulkan graphics command pool");
return 0;
} 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;
@ -1217,11 +1371,18 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->triangle_pipeline = triangle_pipeline;
}
AllocatedBuffer triangle_buffer = create_vertex_buffer(context->physical_device, context->device, (void*)vertices, sizeof(vertices));
if(triangle_buffer.memory == VK_NULL_HANDLE) {
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_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");
} else {
context->triangle_buffer = triangle_buffer;
context->triangle_index_buffer = triangle_index_buffer;
}
return context;
@ -1250,7 +1411,7 @@ VkResult draw_frame(VulkanContext* context) {
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) {
return result;
}