From ff5bf11c5f319f9c90de7a59eb4f8f338a74a38f Mon Sep 17 00:00:00 2001 From: kartofen Date: Sat, 28 Oct 2023 00:16:54 +0300 Subject: added vertex buffers --- src/graphics.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 136 insertions(+), 9 deletions(-) (limited to 'src/graphics.c') diff --git a/src/graphics.c b/src/graphics.c index 8da9c43..0e77c3a 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1,10 +1,17 @@ #include #include +#include #include #include "graphics.h" #include "common.h" +// TODO: finish buffer_copy + +// TODO: explicitly make a transfer queue for +// the buffer staging/copying +// TODO: vkAllocateMemory shouldn't be called for every buffer, +// a memory allocator should be used (the offset parameter) // TODO: add more error checking // TODO: add log output // TODO: check for memory leaks @@ -62,11 +69,12 @@ static int create_physical_device(graphics_t graphics, struct graphics_info *inf static int create_logical_device(graphics_t graphics, struct graphics_info *info); static int create_pipeline(graphics_t graphics, struct graphics_info *info); static int create_swap_chain(graphics_t graphics, struct graphics_info *info); +static int create_vertex_buffer(graphics_t graphics, struct graphics_info *info); static int create_command_pool(graphics_t graphics, struct graphics_info *info); static int create_sync_objects(graphics_t graphics, struct graphics_info *info); -static void destroy_swap_chain(graphics_t graphics); static void destroy_pipeline(graphics_t graphics); +static void destroy_swap_chain(graphics_t graphics); // static void destroy_command_pool(graphics_t graphics); static void destroy_sync_objects(graphics_t graphics); @@ -92,6 +100,16 @@ static int command_buffer_record(graphics_t graphics, u32 image_index); #define SYNC graphics->sync +#define VBFF graphics->vertex_buffer +static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding_desc, VkVertexInputAttributeDescription *attribute_desc); + +static int buffer_create(VkDevice device, VkPhysicalDevice physical_device, + VkDeviceSize size, VkBufferUsageFlags usageflg, + VkMemoryPropertyFlags propflg, buffer_t *buffer); +static void buffer_destroy(VkDevice device, buffer_t buffer); +static int buffer_copy(VkBuffer dest, VkBuffer, VkBuffer src, VkDeviceSize size, VkDevice devie, VkCommandPool pool, u32 queue_idx); +static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx); + F_LOAD_FILE_ALIGNED(u32) // from config.h // --- Debug Functions --- @@ -127,7 +145,6 @@ graphics_t graphics_create(struct graphics_info *info) graphics->instance = VK_NULL_HANDLE; graphics->logical_device = VK_NULL_HANDLE; - PPLN.pipeline = VK_NULL_HANDLE; PPLN.layout = VK_NULL_HANDLE; PPLN.render_pass = VK_NULL_HANDLE; @@ -140,6 +157,9 @@ graphics_t graphics_create(struct graphics_info *info) SYNC.semph_image_available = VK_NULL_HANDLE; SYNC.semph_render_finished = VK_NULL_HANDLE; SYNC.fence_inflight = VK_NULL_HANDLE; + + VBFF.buffer = VK_NULL_HANDLE; + VBFF.memory = VK_NULL_HANDLE; CCHECK(create_instance); CCHECK(create_surface); @@ -150,6 +170,7 @@ graphics_t graphics_create(struct graphics_info *info) CCHECK(create_logical_device); CCHECK(create_pipeline); CCHECK(create_swap_chain); + CCHECK(create_vertex_buffer); CCHECK(create_command_pool); CCHECK(create_sync_objects); @@ -168,6 +189,8 @@ void graphics_destroy(graphics_t graphics) destroy_sync_objects(graphics); vkDestroyCommandPool(graphics->logical_device, CMND.pool, NULL); + + buffer_destroy(graphics->logical_device, VBFF); destroy_swap_chain(graphics); destroy_pipeline(graphics); @@ -599,13 +622,17 @@ static int create_pipeline(graphics_t graphics, struct graphics_info *info) dynamic_state.dynamicStateCount = ARR_SIZE(dynamic_states); dynamic_state.pDynamicStates = dynamic_states; - // vertex things - hard coded (for now) + // vertex things + VkVertexInputBindingDescription binding_description = {0}; + VkVertexInputAttributeDescription attribute_description[2] = {0}; + vertex_populate_descriptions(&binding_description, attribute_description); + VkPipelineVertexInputStateCreateInfo vertex_input = {0}; vertex_input.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertex_input.vertexBindingDescriptionCount = 0; - vertex_input.pVertexBindingDescriptions = NULL; - vertex_input.vertexAttributeDescriptionCount = 0; - vertex_input.pVertexAttributeDescriptions = NULL; + vertex_input.vertexBindingDescriptionCount = 1; + vertex_input.pVertexBindingDescriptions = &binding_description; + vertex_input.vertexAttributeDescriptionCount = ARR_SIZE(attribute_description); + vertex_input.pVertexAttributeDescriptions = attribute_description; VkPipelineInputAssemblyStateCreateInfo input_assembly = {0}; input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; @@ -814,6 +841,28 @@ static void destroy_sync_objects(graphics_t graphics) vkDestroyFence(graphics->logical_device, SYNC.fence_inflight, NULL); } +static int create_vertex_buffer(graphics_t graphics, struct graphics_info *info) +{ + (void)info; + int ret = 1; + + size_t size = sizeof(*info->vertices) * info->nvertices; + + buffer_create(graphics->logical_device, graphics->physical_device, + size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), &VBFF); + + void *data; + vkMapMemory(graphics->logical_device, VBFF.memory, 0, size, 0, &data); + memcpy(data, info->vertices, size); + vkUnmapMemory(graphics->logical_device, VBFF.memory); + + ret = 0; +exit: + return ret; +} + static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family) { u32 count = 0; @@ -1003,6 +1052,10 @@ static int command_buffer_record(graphics_t graphics, u32 image_index) // Begin the drawing commands vkCmdBindPipeline(CMND.buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, PPLN.pipeline); + VkBuffer vertex_buffers[] = { VBFF.buffer }; + VkDeviceSize offsets[] = {0}; + vkCmdBindVertexBuffers(CMND.buffer, 0, 1, vertex_buffers, offsets); + VkViewport viewport = {0}; viewport.x = 0.0f; viewport.y = 0.0f; @@ -1018,8 +1071,8 @@ static int command_buffer_record(graphics_t graphics, u32 image_index) scissor.extent = SWCH.extent; vkCmdSetScissor(CMND.buffer, 0, 1, &scissor); - // 3 vertices, 1 instance (for instanced rendering) - // 0 is the first vertex, 0 is the fist instance + // 3 is the number of vertices + // TODO: fix this vkCmdDraw(CMND.buffer, 3, 1, 0, 0); // Cleaning up @@ -1032,6 +1085,80 @@ exit: return ret; } +static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding_desc, VkVertexInputAttributeDescription *attribute_desc) +{ + binding_desc->binding = 0; + binding_desc->stride = sizeof(struct vertex); + binding_desc->inputRate = VK_VERTEX_INPUT_RATE_VERTEX; + + attribute_desc[0].binding = 0; + attribute_desc[0].location = 0; + attribute_desc[0].format = VK_FORMAT_R32G32_SFLOAT; + attribute_desc[0].offset = offsetof(struct vertex, pos); + + attribute_desc[1].binding = 0; + attribute_desc[1].location = 1; + attribute_desc[1].format = VK_FORMAT_R32G32B32_SFLOAT; + attribute_desc[1].offset = offsetof(struct vertex, color); + + return 0; +} + +static int buffer_create(VkDevice device, VkPhysicalDevice physical_device, + VkDeviceSize size, VkBufferUsageFlags usageflg, + VkMemoryPropertyFlags propflg, buffer_t *buffer) +{ + int ret = 1; + + VkBufferCreateInfo buffer_info = {0}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = size; + buffer_info.usage = usageflg; + buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + + VCHECK(vkCreateBuffer, device, &buffer_info, NULL, &buffer->buffer); + + VkMemoryRequirements memory_requirements; + vkGetBufferMemoryRequirements(device, buffer->buffer, &memory_requirements); + + VkMemoryAllocateInfo allocate_info = {0}; + allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; + allocate_info.allocationSize = memory_requirements.size; + + u32 memory_type_idx; + buffer_find_memory_type(physical_device, memory_requirements.memoryTypeBits, propflg, &memory_type_idx); + allocate_info.memoryTypeIndex = memory_type_idx; + + VCHECK(vkAllocateMemory, device, &allocate_info, NULL, &buffer->memory); + VCHECK(vkBindBufferMemory, device, buffer->buffer, buffer->memory, 0); + + ret = 0; +exit: + return ret; +} + +static void buffer_destroy(VkDevice device, buffer_t buffer) +{ + vkDestroyBuffer(device, buffer.buffer, NULL); + vkFreeMemory(device, buffer.memory, NULL); +} + +static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx) +{ + VkPhysicalDeviceMemoryProperties properties; + vkGetPhysicalDeviceMemoryProperties(device, &properties); + + for(u32 i = 0; i < properties.memoryTypeCount; i++) { + if((type_filter & (i << i)) && ((properties.memoryTypes[i].propertyFlags & flags) == flags)) { + *memory_type_idx = i; + return 0; + } + } + + err("No suitable memory type was found"); + return 1; +} + #define X_VK_RESULT_TABLE(X) \ X(VK_SUCCESS) \ X(VK_NOT_READY) \ -- cgit v1.2.3