diff --git a/gpu.c b/gpu.c index 2b207a1..49ddd58 100644 --- a/gpu.c +++ b/gpu.c @@ -795,8 +795,6 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) ctx->dev, &transient_cmd_pool_config, nullptr, &ctx->transient_cmd_pool); assert(result == VK_SUCCESS); - - ctx->active_img_index = UINT32_MAX; } void gpu_cleanup(const gpu_ctx_t *ctx) @@ -957,7 +955,10 @@ void gpu_model_cleanup(const gpu_ctx_t *ctx, const gpu_model_t *model) vkFreeMemory(ctx->dev, model->vertex_mem, nullptr); } -void gpu_render_begin(gpu_ctx_t *ctx, vp_t vp) +void gpu_render( + const gpu_ctx_t *ctx, vp_t vp, size_t model_count, + const gpu_model_t *models, const mat4_t **bone_matrices, + const mat4_t *model_transforms) { VkResult result; @@ -966,9 +967,10 @@ void gpu_render_begin(gpu_ctx_t *ctx, vp_t vp) vkResetFences(ctx->dev, 1, &ctx->in_flight); // Aquire image from swapchain + uint32_t curr_img; result = vkAcquireNextImageKHR( ctx->dev, ctx->swapchain, UINT64_MAX, ctx->img_avail, VK_NULL_HANDLE, - &ctx->active_img_index); + &curr_img); assert(result == VK_SUCCESS); // Reset command buffer, then begin writing @@ -986,7 +988,7 @@ void gpu_render_begin(gpu_ctx_t *ctx, vp_t vp) VkRenderPassBeginInfo render_pass_begin = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderPass = ctx->render_pass, - .framebuffer = ctx->framebuffers[ctx->active_img_index], + .framebuffer = ctx->framebuffers[curr_img], .renderArea.extent = ctx->swapchain_extent, .clearValueCount = 2, .pClearValues = clear_values, @@ -1002,40 +1004,31 @@ void gpu_render_begin(gpu_ctx_t *ctx, vp_t vp) 0, sizeof(vp_t), &vp); vkCmdDraw(ctx->cmd_buf, 4, 1, 0, 0); + // Draw models vkCmdBindPipeline( ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->model_pipeline); vkCmdPushConstants( ctx->cmd_buf, ctx->model_pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(vp_t), &vp); -} + for (unsigned i = 0; i < model_count; ++i) { + models[i].transform_ptr[curr_img] = model_transforms[i]; + memcpy( + models[i].bone_ptr + (models[i].bone_count * curr_img), + bone_matrices[i], models[i].bone_count * sizeof(mat4_t)); -void gpu_render_model( - const gpu_ctx_t *ctx, const gpu_model_t *model, - const mat4_t *bone_matrices, mat4_t transform) -{ - assert(ctx->active_img_index < ctx->swapchain_img_count); + vkCmdBindVertexBuffers( + ctx->cmd_buf, 0, 1, &models[i].vertex_buf, + &(VkDeviceSize) { 0 }); + vkCmdBindIndexBuffer( + ctx->cmd_buf, models[i].index_buf, 0, VK_INDEX_TYPE_UINT16); - model->transform_ptr[ctx->active_img_index] = transform; - memcpy( - model->bone_ptr + (model->bone_count * ctx->active_img_index), - bone_matrices, model->bone_count * sizeof(mat4_t)); + vkCmdBindDescriptorSets( + ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, + ctx->model_pipeline_layout, 0, 1, models[i].desc_sets + curr_img, + 0, nullptr); - vkCmdBindVertexBuffers( - ctx->cmd_buf, 0, 1, &model->vertex_buf, &(VkDeviceSize) { 0 }); - vkCmdBindIndexBuffer( - ctx->cmd_buf, model->index_buf, 0, VK_INDEX_TYPE_UINT16); - - vkCmdBindDescriptorSets( - ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, - ctx->model_pipeline_layout, 0, 1, - model->desc_sets + ctx->active_img_index, 0, nullptr); - - vkCmdDrawIndexed(ctx->cmd_buf, model->index_count, 1, 0, 0, 0); -} - -void gpu_render_submit(gpu_ctx_t *ctx) -{ - VkResult result; + vkCmdDrawIndexed(ctx->cmd_buf, models[i].index_count, 1, 0, 0, 0); + } // Finish render pass and end writing to command buffer vkCmdEndRenderPass(ctx->cmd_buf); @@ -1065,10 +1058,8 @@ void gpu_render_submit(gpu_ctx_t *ctx) .pWaitSemaphores = &ctx->render_fin, .swapchainCount = 1, .pSwapchains = &ctx->swapchain, - .pImageIndices = &ctx->active_img_index, + .pImageIndices = &curr_img, }; result = vkQueuePresentKHR(ctx->queue, &present_info); assert(result == VK_SUCCESS); - - ctx->active_img_index = UINT32_MAX; } diff --git a/gpu.h b/gpu.h index 61cb62a..236163e 100644 --- a/gpu.h +++ b/gpu.h @@ -47,7 +47,6 @@ typedef struct { VkDeviceMemory staging_mem; void *staging_ptr; VkCommandPool transient_cmd_pool; - uint32_t active_img_index; } gpu_ctx_t; typedef struct { @@ -73,10 +72,9 @@ void gpu_model_load( const gpu_ctx_t *ctx, const model_t *model, gpu_model_t *out); void gpu_model_cleanup(const gpu_ctx_t *ctx, const gpu_model_t *model); -void gpu_render_begin(gpu_ctx_t *ctx, vp_t vp); -void gpu_render_model( - const gpu_ctx_t *ctx, const gpu_model_t *model, - const mat4_t *bone_matrices, mat4_t transform); -void gpu_render_submit(gpu_ctx_t *ctx); +void gpu_render( + const gpu_ctx_t *ctx, vp_t vp, size_t model_count, + const gpu_model_t *models, const mat4_t **bone_matrices, + const mat4_t *model_transforms); #endif diff --git a/main.c b/main.c index 9b518b3..28851a8 100644 --- a/main.c +++ b/main.c @@ -52,13 +52,10 @@ int main(int argc, char *argv[]) // Initialise GPU and load model gpu_ctx_t gpu; - gpu_model_t gpu_model1, gpu_model2; + gpu_model_t gpu_models[2]; gpu_init(&gpu, window, "Foo"); - gpu_model_load(&gpu, &model, &gpu_model1); - gpu_model_load(&gpu, &model, &gpu_model2); - - // Initialise animation - animation_state_t anim = animation_init(&model); + gpu_model_load(&gpu, &model, gpu_models + 0); + gpu_model_load(&gpu, &model, gpu_models + 1); const vec3_t cam = { 0, 4, -8 }; const vec3_t tgt = { 0, 0, 0 }; @@ -66,46 +63,48 @@ int main(int argc, char *argv[]) .view = mat4_lookat(cam, tgt, (vec3_t) { 0, 1, 0 }), .proj = mat4_perspective((float)W / H, PI / 8, 0.1, 100.0), }; - mat4_t transform1 = mat4_mul( - MAT4_TRANSLATE(1, 0, 0), - (mat4_t) { - { 0, 0, -1, 0 }, - { -1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 0, 1 }, - }); - mat4_t transform2 = mat4_mul( - MAT4_TRANSLATE(2, 0, 0), - mat4_mul( - MAT4_ROTATE_Y(PI), - (mat4_t) { - { 0, 0, -1, 0 }, - { -1, 0, 0, 0 }, - { 0, 1, 0, 0 }, - { 0, 0, 0, 1 }, - })); + mat4_t transforms[] = { + mat4_mul( + MAT4_TRANSLATE(1, 0, 0), + (mat4_t) { + { 0, 0, -1, 0 }, + { -1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 0, 1 }, + }), + mat4_mul( + MAT4_TRANSLATE(2, 0, 0), + mat4_mul( + MAT4_ROTATE_Y(PI), + (mat4_t) { + { 0, 0, -1, 0 }, + { -1, 0, 0, 0 }, + { 0, 1, 0, 0 }, + { 0, 0, 0, 1 }, + })), + }; - const mat4_t rot1 = MAT4_ROTATE_Y(PI / 170); - const mat4_t rot2 = MAT4_ROTATE_Y(-PI / 340); + // Set up animation + animation_state_t anim = animation_init(&model); animation_start(&anim, &model, 0); while (!glfwWindowShouldClose(window)) { glfwPollEvents(); - transform1 = mat4_mul(rot1, transform1); - transform2 = mat4_mul(rot2, transform2); + transforms[0] = mat4_mul(MAT4_ROTATE_Y(PI / 170), transforms[0]); + transforms[1] = mat4_mul(MAT4_ROTATE_Y(-PI / 340), transforms[1]); + animation_update(&anim, &model, DT); - gpu_render_begin(&gpu, vp); - gpu_render_model(&gpu, &gpu_model1, anim.bone_matrices, transform1); - gpu_render_model(&gpu, &gpu_model2, anim.bone_matrices, transform2); - gpu_render_submit(&gpu); + const mat4_t *bone_matrices[] + = { anim.bone_matrices, anim.bone_matrices }; + gpu_render(&gpu, vp, 2, gpu_models, bone_matrices, transforms); } // Clean up animation_cleanup(&anim); - gpu_model_cleanup(&gpu, &gpu_model1); - gpu_model_cleanup(&gpu, &gpu_model2); + gpu_model_cleanup(&gpu, gpu_models + 0); + gpu_model_cleanup(&gpu, gpu_models + 1); gpu_cleanup(&gpu); model_cleanup(&model); glfwDestroyWindow(window);