diff --git a/src/main.c b/src/main.c index 83b463a..5745a1e 100644 --- a/src/main.c +++ b/src/main.c @@ -910,38 +910,93 @@ uint32_t find_memory_type (ApplicationState* state, uint32_t type_filter, VkMemo exit(1); } -void create_vertex_buffer(ApplicationState* state) { +void create_buffer(ApplicationState* state, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, + VkBuffer* buffer, VkDeviceMemory* memory) { VkBufferCreateInfo buffer_info = {0}; buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - buffer_info.size = sizeof(Vertex) * ARRSIZE(vertices); - buffer_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; + buffer_info.size = size; + buffer_info.usage = usage; buffer_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - if (vkCreateBuffer(state->device, &buffer_info, NULL, &state->vertex_buffer) != VK_SUCCESS) { - printf("Failed to create vertex buffer\n"); + if (vkCreateBuffer(state->device, &buffer_info, NULL, buffer) != VK_SUCCESS) { + printf("Failed to create buffer\n"); exit(1); } VkMemoryRequirements mem_req; - vkGetBufferMemoryRequirements(state->device, state->vertex_buffer, &mem_req); + vkGetBufferMemoryRequirements(state->device, *buffer, &mem_req); VkMemoryAllocateInfo alloc_info = {0}; alloc_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; alloc_info.allocationSize = mem_req.size; - alloc_info.memoryTypeIndex = find_memory_type(state, mem_req.memoryTypeBits, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT); + alloc_info.memoryTypeIndex = find_memory_type(state, mem_req.memoryTypeBits, properties); - if (vkAllocateMemory(state->device, &alloc_info, NULL, &state->vertex_buffer_memory) != VK_SUCCESS) { + if (vkAllocateMemory(state->device, &alloc_info, NULL, memory) != VK_SUCCESS) { printf("failed to allocate memory for buffer\n"); exit(1); } - vkBindBufferMemory(state->device, state->vertex_buffer, state->vertex_buffer_memory, 0); + vkBindBufferMemory(state->device, *buffer, *memory, 0); +} + +void copy_buffer(ApplicationState* state, VkBuffer src, VkBuffer dst, VkDeviceSize size) { + VkCommandBufferAllocateInfo command_buf_allocate_info = {0}; + command_buf_allocate_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; + command_buf_allocate_info.commandPool = state->commandPool; + command_buf_allocate_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; + command_buf_allocate_info.commandBufferCount = 1; + + VkCommandBuffer buffer; + + if (vkAllocateCommandBuffers(state->device, &command_buf_allocate_info, &buffer) != VK_SUCCESS) { + printf("failed to allocated command buffer for transfer\n"); + exit(1); + } + + 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(buffer, &begin_info); + + VkBufferCopy copy = {0}; + copy.size = size; + vkCmdCopyBuffer(buffer, src, dst, 1, ©); + + vkEndCommandBuffer(buffer); + + VkSubmitInfo submit_info = {0}; + submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; + submit_info.commandBufferCount = 1; + submit_info.pCommandBuffers = &buffer; + + vkQueueSubmit(state->graphics_queue, 1, &submit_info, VK_NULL_HANDLE); + vkQueueWaitIdle(state->graphics_queue); + + vkFreeCommandBuffers(state->device, state->commandPool, 1, &buffer); +} + +void create_vertex_buffer(ApplicationState* state) { + VkDeviceSize buffer_size = sizeof(Vertex) * ARRSIZE(vertices); + + //we use a staging buffer for transferring data in order to use a more efficient memory type for the vertex buffer + VkBuffer staging_buffer; + VkDeviceMemory staging_buffer_memory; + create_buffer(state, buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &staging_buffer, &staging_buffer_memory); void* data; - vkMapMemory(state->device, state->vertex_buffer_memory, 0, buffer_info.size, 0, &data); - memcpy(data, vertices, buffer_info.size); - vkUnmapMemory(state->device, state->vertex_buffer_memory); + vkMapMemory(state->device, staging_buffer_memory, 0, buffer_size, 0, &data); + memcpy(data, vertices, buffer_size); + vkUnmapMemory(state->device, staging_buffer_memory); + + create_buffer(state, buffer_size, VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + &state->vertex_buffer, &state->vertex_buffer_memory); + + copy_buffer(state, staging_buffer, state->vertex_buffer, buffer_size); + + vkDestroyBuffer(state->device, staging_buffer, NULL); + vkFreeMemory(state->device, staging_buffer_memory, NULL); } void create_command_buffer(ApplicationState* state) {