Switch to using uniform buffer for MVP matrices

This commit is contained in:
Camden Dixie O'Brien committed 2025-09-29 17:11:32 +01:00
1 parent f82f829980
commit e75498ff71
3 files changed
+100 -14

No files matched your search

+93 -13
View File
@@ -409,6 +409,78 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config, model_t model)
},
};
// Create descriptor set layout
const VkDescriptorSetLayoutCreateInfo desc_set_layout_config = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = 1,
.pBindings = &(VkDescriptorSetLayoutBinding) {
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
},
};
result = vkCreateDescriptorSetLayout(
ctx->dev, &desc_set_layout_config, nullptr, &ctx->desc_set_layout);
assert(result == VK_SUCCESS);
// Create descriptor pool
const VkDescriptorPoolCreateInfo desc_pool_config = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = 1,
.pPoolSizes = &(VkDescriptorPoolSize) {
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = swapchain_img_count,
},
.maxSets = swapchain_img_count,
};
result = vkCreateDescriptorPool(
ctx->dev, &desc_pool_config, nullptr, &ctx->desc_pool);
assert(result == VK_SUCCESS);
// Create and configure descriptor sets
VkDescriptorSetLayout desc_set_layouts[swapchain_img_count];
for (unsigned i = 0; i < swapchain_img_count; ++i)
desc_set_layouts[i] = ctx->desc_set_layout;
const VkDescriptorSetAllocateInfo desc_sets_alloc_config = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = ctx->desc_pool,
.descriptorSetCount = swapchain_img_count,
.pSetLayouts = desc_set_layouts,
};
result = vkAllocateDescriptorSets(
ctx->dev, &desc_sets_alloc_config, ctx->desc_sets);
assert(result == VK_SUCCESS);
// Create and map MVP buffer
const size_t mvp_buffer_size = swapchain_img_count * sizeof(mvp_t);
create_buffer(
ctx, mvp_buffer_size, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
| VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
&ctx->mvp_buffer, &ctx->mvp_buffer_mem);
vkMapMemory(
ctx->dev, ctx->mvp_buffer_mem, 0, mvp_buffer_size, 0,
(void **)&ctx->mvps);
// Configure descriptor sets to use MVP buffer
for (unsigned i = 0; i < swapchain_img_count; ++i) {
const VkWriteDescriptorSet desc_write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = ctx->desc_sets[i],
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.pBufferInfo = &(VkDescriptorBufferInfo) {
.buffer = ctx->mvp_buffer,
.offset = i * sizeof(mvp_t),
.range = sizeof(mvp_t),
},
};
vkUpdateDescriptorSets(ctx->dev, 1, &desc_write, 0, nullptr);
}
// Set up input configuration
const VkVertexInputBindingDescription input_binding_descs[] = {
{
@@ -490,15 +562,10 @@ void gpu_init(gpu_ctx_t *ctx, const gpu_config_t *config, model_t model)
};
// Create pipeline layout
const VkPushConstantRange mvp_range = {
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.offset = 0,
.size = sizeof(mvp_t),
};
const VkPipelineLayoutCreateInfo pipeline_layout_config = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &mvp_range,
.setLayoutCount = 1,
.pSetLayouts = &ctx->desc_set_layout,
};
result = vkCreatePipelineLayout(
ctx->dev, &pipeline_layout_config, nullptr, &ctx->pipeline_layout);
@@ -723,6 +790,14 @@ void gpu_cleanup(const gpu_ctx_t *ctx)
vkDestroyPipeline(ctx->dev, ctx->pipeline, nullptr);
vkDestroyRenderPass(ctx->dev, ctx->render_pass, nullptr);
vkDestroyPipelineLayout(ctx->dev, ctx->pipeline_layout, nullptr);
vkUnmapMemory(ctx->dev, ctx->mvp_buffer_mem);
vkDestroyBuffer(ctx->dev, ctx->mvp_buffer, nullptr);
vkFreeMemory(ctx->dev, ctx->mvp_buffer_mem, nullptr);
vkDestroyDescriptorPool(ctx->dev, ctx->desc_pool, nullptr);
vkDestroyDescriptorSetLayout(ctx->dev, ctx->desc_set_layout, nullptr);
vkDestroyShaderModule(ctx->dev, ctx->vert_shader, nullptr);
vkDestroyShaderModule(ctx->dev, ctx->frag_shader, nullptr);
@@ -756,6 +831,9 @@ void gpu_render(const gpu_ctx_t *ctx, const mvp_t *mvp)
&img_index);
assert(result == VK_SUCCESS);
// Copy MVP matricies into uniform buffer for this image
memcpy(ctx->mvps + img_index, mvp, sizeof(mvp_t));
// Reset command buffer, then begin writing
vkResetCommandBuffer(ctx->cmd_buf, 0);
const VkCommandBufferBeginInfo cmd_begin = {
@@ -782,16 +860,18 @@ void gpu_render(const gpu_ctx_t *ctx, const mvp_t *mvp)
vkCmdBindPipeline(
ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pipeline);
// Push MVP
vkCmdPushConstants(
ctx->cmd_buf, ctx->pipeline_layout, VK_SHADER_STAGE_VERTEX_BIT, 0,
sizeof(mvp_t), mvp);
// Bind vertex and index buffers then draw
// Bind vertex and index buffers
vkCmdBindVertexBuffers(
ctx->cmd_buf, 0, 1, &ctx->vertex_buf, &(VkDeviceSize) { 0 });
vkCmdBindIndexBuffer(
ctx->cmd_buf, ctx->index_buf, 0, VK_INDEX_TYPE_UINT16);
// Bind descriptor set for this frame
vkCmdBindDescriptorSets(
ctx->cmd_buf, VK_PIPELINE_BIND_POINT_GRAPHICS, ctx->pipeline_layout,
0, 1, ctx->desc_sets + img_index, 0, nullptr);
// Draw
vkCmdDrawIndexed(ctx->cmd_buf, ctx->index_count, 1, 0, 0, 0);
// Finish render pass and end writing to command buffer
+6
View File
@@ -31,6 +31,12 @@ typedef struct {
VkFramebuffer framebuffers[SWAPCHAIN_IMG_BUFFER_SIZE];
VkShaderModule vert_shader;
VkShaderModule frag_shader;
VkDescriptorSetLayout desc_set_layout;
VkDescriptorPool desc_pool;
VkDescriptorSet desc_sets[SWAPCHAIN_IMG_BUFFER_SIZE];
VkBuffer mvp_buffer;
VkDeviceMemory mvp_buffer_mem;
mvp_t *mvps;
VkPipelineLayout pipeline_layout;
VkRenderPass render_pass;
VkPipeline pipeline;
+1 -1
View File
@@ -5,7 +5,7 @@ layout(location = 1) in vec3 normal;
layout(location = 0) out vec3 frag_normal;
layout(push_constant) uniform MVP {
layout(binding = 0) uniform mvp_t {
mat4 model;
mat4 view;
mat4 proj;