diff --git a/gpu.c b/gpu.c index 25fb473..3404aa1 100644 --- a/gpu.c +++ b/gpu.c @@ -477,23 +477,6 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config) assert(result == VK_SUCCESS); } - // Create vertex buffer - ctx->vertex_data_size = config->vertex_data_size; - const VkMemoryPropertyFlags vertex_buf_props - = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT - | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - create_buffer( - ctx, ctx->vertex_data_size, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - vertex_buf_props, &ctx->vertex_buf, &ctx->vertex_buf_mem); - - // Copy vertex data into vertex buffer - void *vertex_buf_ptr; - vkMapMemory( - ctx->dev, ctx->vertex_buf_mem, 0, ctx->vertex_data_size, 0, - &vertex_buf_ptr); - memcpy(vertex_buf_ptr, config->vertex_data, ctx->vertex_data_size); - vkUnmapMemory(ctx->dev, ctx->vertex_buf_mem); - // Create command pool const VkCommandPoolCreateInfo cmd_pool_config = { .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO, @@ -532,12 +515,59 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config) result = vkCreateFence(ctx->dev, &fence_config, nullptr, &ctx->in_flight); assert(result == VK_SUCCESS); + + // Set up staging and vertex buffers + ctx->vertex_data_size = config->vertex_data_size; + VkBuffer staging_buf; + VkDeviceMemory staging_buf_mem; + create_buffer( + ctx, ctx->vertex_data_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, + VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT + | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, + &staging_buf, &staging_buf_mem); + create_buffer( + ctx, ctx->vertex_data_size, + VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, &ctx->vertex_buf, + &ctx->vertex_buf_mem); + + // Copy vertex data into staging buffer + void *staging_buf_ptr; + vkMapMemory( + ctx->dev, staging_buf_mem, 0, ctx->vertex_data_size, 0, + &staging_buf_ptr); + memcpy(staging_buf_ptr, config->vertex_data, ctx->vertex_data_size); + vkUnmapMemory(ctx->dev, staging_buf_mem); + + // Copy staging buffer to vertex buffer + VkCommandBufferBeginInfo cmd_begin = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + .flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, + }; + vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin); + VkBufferCopy cmd_copy = { .size = ctx->vertex_data_size }; + vkCmdCopyBuffer( + ctx->cmd_buf, staging_buf, ctx->vertex_buf, 1, &cmd_copy); + vkEndCommandBuffer(ctx->cmd_buf); + VkSubmitInfo copy_submit = { + .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO, + .commandBufferCount = 1, + .pCommandBuffers = &ctx->cmd_buf, + }; + vkQueueSubmit(ctx->queue, 1, ©_submit, VK_NULL_HANDLE); + vkQueueWaitIdle(ctx->queue); + + // Clean up staging buffer + vkDestroyBuffer(ctx->dev, staging_buf, nullptr); + vkFreeMemory(ctx->dev, staging_buf_mem, nullptr); } void gpu_cleanup(const gpu_ctx_t *ctx) { vkDeviceWaitIdle(ctx->dev); + vkDestroyBuffer(ctx->dev, ctx->vertex_buf, nullptr); + vkFreeMemory(ctx->dev, ctx->vertex_buf_mem, nullptr); vkDestroySemaphore(ctx->dev, ctx->img_avail, nullptr); vkDestroySemaphore(ctx->dev, ctx->render_fin, nullptr); vkDestroyFence(ctx->dev, ctx->in_flight, nullptr); @@ -552,8 +582,6 @@ void gpu_cleanup(const gpu_ctx_t *ctx) vkDestroyImageView(ctx->dev, ctx->swapchain_img_views[i], nullptr); } vkDestroySwapchainKHR(ctx->dev, ctx->swapchain, nullptr); - vkDestroyBuffer(ctx->dev, ctx->vertex_buf, nullptr); - vkFreeMemory(ctx->dev, ctx->vertex_buf_mem, nullptr); vkDestroyDevice(ctx->dev, nullptr); vkDestroySurfaceKHR(ctx->inst, ctx->surface, nullptr); vkDestroyInstance(ctx->inst, nullptr); diff --git a/gpu.h b/gpu.h index 2a50499..f7d5fe0 100644 --- a/gpu.h +++ b/gpu.h @@ -31,9 +31,9 @@ typedef struct { VkFence in_flight; VkSemaphore render_fin; VkSemaphore img_avail; + size_t vertex_data_size; VkBuffer vertex_buf; VkDeviceMemory vertex_buf_mem; - size_t vertex_data_size; } gpu_ctx_t; typedef struct {