diff --git a/gpu.c b/gpu.c index 573f621..b274299 100644 --- a/gpu.c +++ b/gpu.c @@ -540,10 +540,17 @@ void gpu_init(gpu_ctx_t *ctx, GLFWwindow *window, const char *name) }; // Create pipeline layout + const VkPushConstantRange push_constant_range = { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = sizeof(vp_t), + }; const VkPipelineLayoutCreateInfo pipeline_layout_config = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 1, .pSetLayouts = &ctx->desc_set_layout, + .pushConstantRangeCount = 1, + .pPushConstantRanges = &push_constant_range, }; result = vkCreatePipelineLayout( ctx->dev, &pipeline_layout_config, nullptr, &ctx->pipeline_layout); @@ -807,15 +814,16 @@ void gpu_model_load( ctx->dev, &desc_sets_alloc_config, out->desc_sets); assert(result == VK_SUCCESS); - // Create and map MVP buffer - const size_t mvp_size = ctx->swapchain_img_count * sizeof(mvp_t); + // Create and map transform buffer + const size_t transform_size = ctx->swapchain_img_count * sizeof(mat4_t); create_buffer( - ctx, mvp_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, + ctx, transform_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, - &out->mvp_buf, &out->mvp_mem); + &out->transform_buf, &out->transform_mem); vkMapMemory( - ctx->dev, out->mvp_mem, 0, mvp_size, 0, (void **)&out->mvp_ptr); + ctx->dev, out->transform_mem, 0, transform_size, 0, + (void **)&out->transform_ptr); // Create and map bone matrix buffer const size_t bone_size @@ -828,7 +836,7 @@ void gpu_model_load( vkMapMemory( ctx->dev, out->bone_mem, 0, bone_size, 0, (void **)&out->bone_ptr); - // Configure descriptor sets to use MVP and bone matrix buffers + // Configure descriptor sets to use transform and bone matrix buffers for (unsigned i = 0; i < ctx->swapchain_img_count; ++i) { const VkWriteDescriptorSet desc_writes[] = { { @@ -839,9 +847,9 @@ void gpu_model_load( .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, .descriptorCount = 1, .pBufferInfo = &(VkDescriptorBufferInfo) { - .buffer = out->mvp_buf, - .offset = i * sizeof(mvp_t), - .range = sizeof(mvp_t), + .buffer = out->transform_buf, + .offset = i * sizeof(mat4_t), + .range = sizeof(mat4_t), }, }, { @@ -870,8 +878,8 @@ void gpu_model_cleanup(const gpu_ctx_t *ctx, const gpu_model_t *model) vkDestroyBuffer(ctx->dev, model->bone_buf, nullptr); vkFreeMemory(ctx->dev, model->bone_mem, nullptr); - vkDestroyBuffer(ctx->dev, model->mvp_buf, nullptr); - vkFreeMemory(ctx->dev, model->mvp_mem, nullptr); + vkDestroyBuffer(ctx->dev, model->transform_buf, nullptr); + vkFreeMemory(ctx->dev, model->transform_mem, nullptr); vkDestroyBuffer(ctx->dev, model->index_buf, nullptr); vkFreeMemory(ctx->dev, model->index_mem, nullptr); @@ -879,7 +887,7 @@ 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) +void gpu_render_begin(gpu_ctx_t *ctx, vp_t vp) { VkResult result; @@ -901,7 +909,6 @@ void gpu_render_begin(gpu_ctx_t *ctx) result = vkBeginCommandBuffer(ctx->cmd_buf, &cmd_begin); assert(result == VK_SUCCESS); - // Start render pass VkClearValue clear_values[] = { [0] = { .color = { { 0.0, 0.0, 0.0, 1.0 } } }, [1] = { .depthStencil = { 1.0, 0.0 } }, @@ -918,15 +925,19 @@ void gpu_render_begin(gpu_ctx_t *ctx) ctx->cmd_buf, &render_pass_begin, VK_SUBPASS_CONTENTS_INLINE); vkCmdBindPipeline( ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pipeline); + + vkCmdPushConstants( + ctx->cmd_buf, ctx->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0, + sizeof(vp_t), &vp); } void gpu_render_model( - const gpu_ctx_t *ctx, const gpu_model_t *model, const mvp_t *mvp, - const mat4_t *bone_matrices) + 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); - memcpy(model->mvp_ptr + ctx->active_img_index, mvp, sizeof(mvp_t)); + 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)); diff --git a/gpu.h b/gpu.h index c181fbc..4aa013b 100644 --- a/gpu.h +++ b/gpu.h @@ -10,10 +10,9 @@ #define MAX_FRAMES_IN_FLIGHT 4 typedef struct { - mat4_t model; mat4_t view; mat4_t proj; -} mvp_t; +} vp_t; typedef struct { VkInstance inst; @@ -49,15 +48,15 @@ typedef struct { } gpu_ctx_t; typedef struct { - mvp_t *mvp_ptr; + mat4_t *transform_ptr; mat4_t *bone_ptr; VkBuffer vertex_buf; VkDeviceMemory vertex_mem; VkBuffer index_buf; VkDeviceMemory index_mem; VkDescriptorSet desc_sets[MAX_FRAMES_IN_FLIGHT]; - VkBuffer mvp_buf; - VkDeviceMemory mvp_mem; + VkBuffer transform_buf; + VkDeviceMemory transform_mem; VkBuffer bone_buf; VkDeviceMemory bone_mem; size_t index_count; @@ -71,11 +70,10 @@ 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); +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 mvp_t *mvp, - - const mat4_t *bone_matrices); + 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); #endif diff --git a/main.c b/main.c index 868261b..f86dd10 100644 --- a/main.c +++ b/main.c @@ -62,32 +62,28 @@ int main(int argc, char *argv[]) const vec3_t cam = { 0, 4, -4 }; const vec3_t tgt = { 0, 0.5, 0 }; - mvp_t mvp1 = { - .model = 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 }, - }), - .view = mat4_lookat(cam, tgt, (vec3_t) { 0, 1, 0 }), - .proj = mat4_perspective((float)W / H, PI / 8, 0.1, 10.0), - }; - mvp_t mvp2 = { - .model = 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 vp_t vp = { .view = mat4_lookat(cam, tgt, (vec3_t) { 0, 1, 0 }), .proj = mat4_perspective((float)W / H, PI / 8, 0.1, 10.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 }, + })); const mat4_t rot1 = MAT4_ROTATE_Y(PI / 170); const mat4_t rot2 = MAT4_ROTATE_Y(-PI / 340); @@ -96,13 +92,13 @@ int main(int argc, char *argv[]) while (!glfwWindowShouldClose(window)) { glfwPollEvents(); - mvp1.model = mat4_mul(rot1, mvp1.model); - mvp2.model = mat4_mul(rot2, mvp2.model); + transform1 = mat4_mul(rot1, transform1); + transform2 = mat4_mul(rot2, transform2); animation_update(&anim, &model, DT); - gpu_render_begin(&gpu); - gpu_render_model(&gpu, &gpu_model1, &mvp1, anim.bone_matrices); - gpu_render_model(&gpu, &gpu_model2, &mvp2, anim.bone_matrices); + 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); } diff --git a/vert.glsl b/vert.glsl index 2ab6447..d346515 100644 --- a/vert.glsl +++ b/vert.glsl @@ -7,11 +7,14 @@ layout(location = 3) in vec4 weights; layout(location = 0) out vec3 frag_normal; -layout(binding = 0) uniform mvp_t { - mat4 model; +layout(push_constant) uniform vp_t { mat4 view; mat4 proj; -} mvp; +} vp; + +layout(binding = 0) uniform transform_t { + mat4 model; +} transform; layout(binding = 1) uniform skeleton_t { mat4 matrices[32]; @@ -23,8 +26,8 @@ void main() { + weights.y * bones.matrices[bone_indices.y] + weights.z * bones.matrices[bone_indices.z] + weights.w * bones.matrices[bone_indices.w]; - gl_Position = mvp.proj * mvp.view * mvp.model * skinning_matrix + gl_Position = vp.proj * vp.view * transform.model * skinning_matrix * vec4(position, 1.0); - frag_normal - = transpose(inverse(mat3(mvp.model * skinning_matrix))) * normal; + frag_normal = transpose( + inverse(mat3(transform.model * skinning_matrix))) * normal; }