diff options
author | kartofen <mladenovnasko0@gmail.com> | 2023-10-29 13:06:40 +0200 |
---|---|---|
committer | kartofen <mladenovnasko0@gmail.com> | 2023-10-29 13:06:40 +0200 |
commit | 4512fafc57d2ad95b83c8476781ce105a2cdc4e5 (patch) | |
tree | a37817c9bfa2f183f02439a31dcb38f78a7a0ccc | |
parent | ff5bf11c5f319f9c90de7a59eb4f8f338a74a38f (diff) |
index buffer and staging
-rw-r--r-- | src/graphics.c | 247 | ||||
-rw-r--r-- | src/graphics.h | 9 | ||||
-rw-r--r-- | src/main.c | 13 |
3 files changed, 181 insertions, 88 deletions
diff --git a/src/graphics.c b/src/graphics.c index 0e77c3a..95f6630 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -6,15 +6,14 @@ #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: the amount of vertices is currently +// hardcoded in command_buffer_record +// thats bad // TODO: add more error checking // TODO: add log output // TODO: check for memory leaks +// TODO: vkAllocateMemory shouldn't be called for every buffer, +// a memory allocator should be used (the offset parameter) #define SWAP_CHAIN_IMAGES 3 @@ -47,6 +46,9 @@ struct queue_family_idx { u32 present_family; bool has_present_family; + + u32 transfer_family; + bool has_transfer_family; }; struct swap_chain_support_details { @@ -78,8 +80,13 @@ static void destroy_swap_chain(graphics_t graphics); // static void destroy_command_pool(graphics_t graphics); static void destroy_sync_objects(graphics_t graphics); +static int buffer_create(graphics_t graphics, size_t size, VkBufferUsageFlags usageflg, + VkMemoryPropertyFlags propflg, buffer_t *buffer); +static int buffer_copy(graphics_t graphics, buffer_t dest, buffer_t src, size_t size); +static void buffer_destroy(graphics_t graphics, buffer_t buffer); + // --- Helper Functions --- -static char *str_VkResult(VkResult result); +static int buffer_find_memory_type(VkPhysicalDevice device, u32 type_filter, VkMemoryPropertyFlags flags, u32 *memory_type_idx); static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface); static bool device_has_extension_support(VkPhysicalDevice phy_device); @@ -95,21 +102,18 @@ static int swap_chain_choose_format(VkSurfaceFormatKHR* formats, u32 nformats, V static int swap_chain_choose_present_mode(VkPresentModeKHR *modes, u32 nmodes, VkPresentModeKHR *mode); static int swap_chain_get_extent(VkSurfaceCapabilitiesKHR capabilities, VkExtent2D *extent); -#define CMND graphics->command +#define CMND graphics->command_graphics +#define CMND_TRNS graphics->command_transfer static int command_buffer_record(graphics_t graphics, u32 image_index); #define SYNC graphics->sync #define VBFF graphics->vertex_buffer +#define IBFF graphics->index_buffer +static int graphics_buffer_create(graphics_t graphics, VkBufferUsageFlags flags, void *data, size_t size, buffer_t *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); - +static char *str_VkResult(VkResult result); F_LOAD_FILE_ALIGNED(u32) // from config.h // --- Debug Functions --- @@ -170,8 +174,8 @@ 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_vertex_buffer); CCHECK(create_sync_objects); return graphics; @@ -189,8 +193,10 @@ void graphics_destroy(graphics_t graphics) destroy_sync_objects(graphics); vkDestroyCommandPool(graphics->logical_device, CMND.pool, NULL); + vkDestroyCommandPool(graphics->logical_device, CMND_TRNS.pool, NULL); - buffer_destroy(graphics->logical_device, VBFF); + buffer_destroy(graphics, VBFF); + buffer_destroy(graphics, IBFF); destroy_swap_chain(graphics); destroy_pipeline(graphics); @@ -397,7 +403,7 @@ static int create_logical_device(graphics_t graphics, struct graphics_info *info // queue infos u32 unique_queue_family_count = 0; u32 queue_indices[] = { - indices.graphics_family, indices.present_family, + indices.graphics_family, indices.present_family, indices.transfer_family }; VkDeviceQueueCreateInfo queue_infos[ARR_SIZE(queue_indices)] = {0}; @@ -448,6 +454,7 @@ static int create_logical_device(graphics_t graphics, struct graphics_info *info vkGetDeviceQueue(graphics->logical_device, indices.graphics_family, 0, &graphics->graphics_queue); vkGetDeviceQueue(graphics->logical_device, indices.present_family, 0, &graphics->present_queue); + vkGetDeviceQueue(graphics->logical_device, indices.transfer_family, 0, &graphics->transfer_queue); ret = 0; exit: @@ -791,22 +798,40 @@ static int create_command_pool(graphics_t graphics, struct graphics_info *info) struct queue_family_idx indices; device_queue_families(graphics->physical_device, graphics->surface, &indices); - - VkCommandPoolCreateInfo pool_info = {0}; - pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - pool_info.queueFamilyIndex = indices.graphics_family; - VCHECK(vkCreateCommandPool, graphics->logical_device, &pool_info, NULL, &CMND.pool); + // graphics pool + VkCommandPoolCreateInfo graphics_pool_info = {0}; + graphics_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + graphics_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + graphics_pool_info.queueFamilyIndex = indices.graphics_family; + + VCHECK(vkCreateCommandPool, graphics->logical_device, &graphics_pool_info, NULL, &CMND.pool); + + // graphics buffer + VkCommandBufferAllocateInfo graphics_allocate_info = {0}; + graphics_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + graphics_allocate_info.commandPool = CMND.pool; + graphics_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + graphics_allocate_info.commandBufferCount = 1; + + VCHECK(vkAllocateCommandBuffers, graphics->logical_device, &graphics_allocate_info, &CMND.buffer); + + // transfer pool + VkCommandPoolCreateInfo transfer_pool_info = {0}; + transfer_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; + transfer_pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; + transfer_pool_info.queueFamilyIndex = indices.transfer_family; - // allocate the command buffer(s) - VkCommandBufferAllocateInfo allocate_info = {0}; - allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocate_info.commandPool = CMND.pool; - allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocate_info.commandBufferCount = 1; + VCHECK(vkCreateCommandPool, graphics->logical_device, &transfer_pool_info, NULL, &CMND_TRNS.pool); - VCHECK(vkAllocateCommandBuffers, graphics->logical_device, &allocate_info, &CMND.buffer); + // graphics buffer + VkCommandBufferAllocateInfo transfer_allocate_info = {0}; + transfer_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + transfer_allocate_info.commandPool = CMND_TRNS.pool; + transfer_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + transfer_allocate_info.commandBufferCount = 1; + + VCHECK(vkAllocateCommandBuffers, graphics->logical_device, &transfer_allocate_info, &CMND_TRNS.buffer); ret = 0; exit: @@ -843,26 +868,94 @@ static void destroy_sync_objects(graphics_t graphics) static int create_vertex_buffer(graphics_t graphics, struct graphics_info *info) { - (void)info; + graphics_buffer_create(graphics, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, info->vertices, + sizeof(*info->vertices) *info->nvertices, &VBFF); + graphics_buffer_create(graphics, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, info->indices, + sizeof(*info->indices) * info->nindices, &IBFF); + return 0; +} + +static int buffer_create(graphics_t graphics, size_t size, VkBufferUsageFlags usageflg, VkMemoryPropertyFlags propflg, buffer_t *buffer) +{ int ret = 1; - size_t size = sizeof(*info->vertices) * info->nvertices; + VkBufferCreateInfo buffer_info = {0}; + buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; + buffer_info.size = size; + buffer_info.usage = usageflg; - 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); + // share between the graphics nad transfer queue families + struct queue_family_idx indices; + device_queue_families(graphics->physical_device, graphics->surface, &indices); + u32 queue_family_indices[] = { indices.graphics_family, indices.transfer_family }; + + // buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; + buffer_info.sharingMode = VK_SHARING_MODE_CONCURRENT; + buffer_info.pQueueFamilyIndices = queue_family_indices; + buffer_info.queueFamilyIndexCount = ARR_SIZE(queue_family_indices); + + VCHECK(vkCreateBuffer, graphics->logical_device, &buffer_info, NULL, &buffer->buffer); - void *data; - vkMapMemory(graphics->logical_device, VBFF.memory, 0, size, 0, &data); - memcpy(data, info->vertices, size); - vkUnmapMemory(graphics->logical_device, VBFF.memory); + VkMemoryRequirements memory_requirements; + vkGetBufferMemoryRequirements(graphics->logical_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(graphics->physical_device, memory_requirements.memoryTypeBits, propflg, &memory_type_idx); + allocate_info.memoryTypeIndex = memory_type_idx; + + VCHECK(vkAllocateMemory, graphics->logical_device, &allocate_info, NULL, &buffer->memory); + VCHECK(vkBindBufferMemory, graphics->logical_device, buffer->buffer, buffer->memory, 0); + ret = 0; exit: return ret; } +static int buffer_copy(graphics_t graphics, buffer_t dest, buffer_t src, size_t size) +{ + // TODO: add error checking + int ret = 1; + + vkResetCommandBuffer(CMND_TRNS.buffer, 0); + + VkCommandBufferBeginInfo begin_info = {0}; + begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; + begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT; + + vkBeginCommandBuffer(CMND_TRNS.buffer, &begin_info); + + VkBufferCopy copy_region = {0}; + copy_region.srcOffset = 0; // Optional + copy_region.dstOffset = 0; // Optional + copy_region.size = size; + + vkCmdCopyBuffer(CMND_TRNS.buffer, src.buffer, dest.buffer, 1, ©_region); + + vkEndCommandBuffer(CMND_TRNS.buffer); + + VkSubmitInfo submit_info = {0}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &CMND_TRNS.buffer; + + vkQueueSubmit(graphics->transfer_queue, 1, &submit_info, VK_NULL_HANDLE); + vkQueueWaitIdle(graphics->transfer_queue); + + ret = 0; +exit: + return ret; +} + +static void buffer_destroy(graphics_t graphics, buffer_t buffer) +{ + vkDestroyBuffer(graphics->logical_device, buffer.buffer, NULL); + vkFreeMemory(graphics->logical_device, buffer.memory, NULL); +} + static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surface, struct queue_family_idx *queue_family) { u32 count = 0; @@ -877,6 +970,11 @@ static int device_queue_families(VkPhysicalDevice phy_device, VkSurfaceKHR surfa queue_family->has_graphics_family = true; } + if(properties[i].queueFlags & VK_QUEUE_TRANSFER_BIT) { + queue_family->transfer_family = i; + queue_family->has_transfer_family = true; + } + VkBool32 present_support = false; vkGetPhysicalDeviceSurfaceSupportKHR(phy_device, i, surface, &present_support); @@ -897,7 +995,9 @@ static bool device_is_suitable(VkPhysicalDevice phy_device, VkSurfaceKHR surface return (device_queue_families(phy_device, surface, &indices), - indices.has_graphics_family && indices.has_present_family) + indices.has_graphics_family && + indices.has_present_family && + indices.has_transfer_family) && (device_has_extension_support(phy_device)) && @@ -1056,6 +1156,8 @@ static int command_buffer_record(graphics_t graphics, u32 image_index) VkDeviceSize offsets[] = {0}; vkCmdBindVertexBuffers(CMND.buffer, 0, 1, vertex_buffers, offsets); + vkCmdBindIndexBuffer(CMND.buffer, IBFF.buffer, 0, VK_INDEX_TYPE_UINT32); + VkViewport viewport = {0}; viewport.x = 0.0f; viewport.y = 0.0f; @@ -1073,7 +1175,7 @@ static int command_buffer_record(graphics_t graphics, u32 image_index) // 3 is the number of vertices // TODO: fix this - vkCmdDraw(CMND.buffer, 3, 1, 0, 0); + vkCmdDrawIndexed(CMND.buffer, 6, 1, 0, 0, 0); // Cleaning up vkCmdEndRenderPass(CMND.buffer); @@ -1085,6 +1187,26 @@ exit: return ret; } +static int graphics_buffer_create(graphics_t graphics, VkBufferUsageFlags flags, void *data, size_t size, buffer_t *buffer) +{ + buffer_t staging; + buffer_create(graphics, size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + (VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | + VK_MEMORY_PROPERTY_HOST_COHERENT_BIT), &staging); + + void *dest_data; + vkMapMemory(graphics->logical_device, staging.memory, 0, size, 0, &dest_data); + memcpy(dest_data, data, size); + vkUnmapMemory(graphics->logical_device, staging.memory); + + buffer_create(graphics, size, (flags | VK_BUFFER_USAGE_TRANSFER_DST_BIT), + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffer); + + buffer_copy(graphics, *buffer, staging, size); + buffer_destroy(graphics, staging); + return 0; +} + static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding_desc, VkVertexInputAttributeDescription *attribute_desc) { binding_desc->binding = 0; @@ -1104,45 +1226,6 @@ static int vertex_populate_descriptions(VkVertexInputBindingDescription *binding 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; diff --git a/src/graphics.h b/src/graphics.h index 470ea9b..71a8889 100644 --- a/src/graphics.h +++ b/src/graphics.h @@ -33,6 +33,7 @@ typedef struct graphics { VkQueue graphics_queue; VkQueue present_queue; + VkQueue transfer_queue; VkSurfaceKHR surface; @@ -57,16 +58,16 @@ typedef struct graphics { struct command { VkCommandPool pool; VkCommandBuffer buffer; - } command; + } command_graphics, command_transfer; struct sync { VkSemaphore semph_image_available; VkSemaphore semph_render_finished; VkFence fence_inflight; } sync; - + buffer_t vertex_buffer; - buffer_t staging_buffer; + buffer_t index_buffer; } * graphics_t; @@ -79,6 +80,8 @@ struct graphics_info { vertex_t *vertices; size_t nvertices; + u32 *indices; + size_t nindices; int (*surface_func)(VkInstance instance, VkSurfaceKHR *surface); }; @@ -11,9 +11,14 @@ graphics_t graphics; int _create_surface(VkInstance instance, VkSurfaceKHR *surface); vertex_t vertices[] = { - {{0.0f, -0.5f}, {1.0f, 0.0f, 0.0f}}, - {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, - {{-0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}} + {{-0.5f, -0.5f}, {1.0f, 0.0f, 0.0f}}, + {{0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}}, + {{0.5f, 0.5f}, {0.0f, 0.0f, 1.0f}}, + {{-0.5f, 0.5f}, {1.0f, 1.0f, 1.0f}} +}; + +u32 indices[] = { + 0, 1, 2, 2, 3, 0 }; int main(void) @@ -56,6 +61,8 @@ int main(void) grph_info.vertices = vertices; grph_info.nvertices = ARR_SIZE(vertices); + grph_info.indices = indices; + grph_info.nindices = ARR_SIZE(indices); grph_info.surface_func = _create_surface; |