From 04618af2fb9e41a0d66f9385b58659b76c8b9a6b Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Mon, 8 Jan 2024 16:44:14 -0700 Subject: [PATCH] Moved scene UBO to a descriptor in the vulkan context. Need to figure out how to deal with materials that give out descriptors per loaded mesh. --- shader_src/basic.vert | 3 +- src/main.c | 275 +++++++++++++++++++++++------------------- 2 files changed, 151 insertions(+), 127 deletions(-) diff --git a/shader_src/basic.vert b/shader_src/basic.vert index 7ce15ef..da91a21 100644 --- a/shader_src/basic.vert +++ b/shader_src/basic.vert @@ -1,7 +1,6 @@ #version 450 layout(binding = 0) uniform UniformBufferObject { - mat4 model; mat4 view; mat4 proj; } ubo; @@ -12,6 +11,6 @@ layout(location = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; void main() { - gl_Position = ubo.proj * ubo.view * ubo.model * vec4(inPosition, 0.0, 1.0); + gl_Position = ubo.proj * ubo.view * vec4(inPosition, 0.0, 1.0); fragColor = inColor; } diff --git a/src/main.c b/src/main.c index e3e892b..b9cf570 100644 --- a/src/main.c +++ b/src/main.c @@ -51,20 +51,8 @@ typedef struct AllocatedBufferStruct { } AllocatedBuffer; typedef struct MaterialStruct { - uint32_t descriptor_set_layouts_count; - VkDescriptorSetLayout* descriptor_set_layouts; - - uint32_t push_constant_ranges_count; - VkPushConstantRange* push_constant_ranges; - VkPipelineLayout pipeline_layout; VkPipeline pipeline; - - VkDescriptorPool descriptor_pool; - uint32_t frame_count; - VkDescriptorSet* descriptor_sets; - AllocatedBuffer* uniform_buffers; - void** uniform_buffer_ptrs; } Material; typedef struct MeshStruct { @@ -110,6 +98,12 @@ typedef struct VulkanContextStruct { VkCommandPool graphics_command_pool; VkCommandPool transfer_command_pool; + VkDescriptorPool scene_ubo_pool; + VkDescriptorSetLayout scene_ubo_layout; + VkDescriptorSet* scene_ubo_descriptors; + AllocatedBuffer* scene_ubos; + void** scene_ubo_ptrs; + Mesh triangle_mesh; Material simple_mesh_material; @@ -121,8 +115,7 @@ struct Vertex{ vec3 color; }; -struct ShaderUBO { - mat4 model; +struct SceneUBO { mat4 view; mat4 proj; }; @@ -441,9 +434,9 @@ VkDebugUtilsMessengerEXT create_debug_messenger(VkInstance instance) { return debug_messenger; } -VkDescriptorPool create_descriptor_pool(VkDevice device, uint32_t size) { +VkDescriptorPool create_descriptor_pool(VkDevice device, VkDescriptorType type, uint32_t size) { VkDescriptorPoolSize pool_size = {}; - pool_size.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + pool_size.type = type; pool_size.descriptorCount = size; VkDescriptorPoolCreateInfo pool_info = {}; @@ -1062,21 +1055,7 @@ AllocatedBuffer create_populated_buffer(VkPhysicalDevice physical_device, VkDevi return vertex_buffer; } -VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipelineLayout layout, VkRenderPass render_pass) { - VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device); - VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device); - - VkPipelineShaderStageCreateInfo shader_stages[2] = {}; - shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; - shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; - shader_stages[0].module = vert_shader; - shader_stages[0].pName = "main"; - - shader_stages[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; - shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; - shader_stages[1].module = frag_shader; - shader_stages[1].pName = "main"; - +VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipelineLayout layout, VkRenderPass render_pass, uint32_t shader_stage_count, VkPipelineShaderStageCreateInfo* shader_stages) { VkDynamicState dynamic_states[] = { VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, @@ -1165,7 +1144,7 @@ VkPipeline create_graphics_pipeline(VkDevice device, VkExtent2D extent, VkPipeli VkGraphicsPipelineCreateInfo pipeline_info = {}; pipeline_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipeline_info.stageCount = 2; + pipeline_info.stageCount = shader_stage_count; pipeline_info.pStages = shader_stages; pipeline_info.pVertexInputState = &vertex_input_info; pipeline_info.pInputAssemblyState = &input_assemvly_info; @@ -1205,7 +1184,26 @@ VkCommandPool create_command_pool(VkDevice device, uint32_t queue_family) { return command_pool; } -VkResult record_command_buffer_mesh(VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent, Material material, Mesh mesh, uint32_t current_frame) { +void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) { + VkBuffer vertex_buffers[] = {mesh.vertex_buffer.buffer}; + VkDeviceSize offsets[] = {0}; + vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); + vkCmdBindIndexBuffer(command_buffer, mesh.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16); + + + vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0); +} + +void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) { + vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline); + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline_layout, 0, 1, &scene_ubo_descriptor, 0, 0); + + for(uint32_t i = 0; i < mesh_count; i++) { + record_command_buffer_mesh(meshes[i], command_buffer); + } +} + +VkResult record_command_buffer_scene(uint32_t materials_count, Material* materials, uint32_t* mesh_counts, Mesh** meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer, VkRenderPass render_pass, VkFramebuffer framebuffer, VkExtent2D extent) { VkCommandBufferBeginInfo begin_info = {}; begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; begin_info.flags = 0; @@ -1228,12 +1226,6 @@ VkResult record_command_buffer_mesh(VkCommandBuffer command_buffer, VkRenderPass render_pass_info.pClearValues = &clear_color; vkCmdBeginRenderPass(command_buffer, &render_pass_info, VK_SUBPASS_CONTENTS_INLINE); - vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline); - - VkBuffer vertex_buffers[] = {mesh.vertex_buffer.buffer}; - VkDeviceSize offsets[] = {0}; - vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); - vkCmdBindIndexBuffer(command_buffer, mesh.index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16); VkViewport viewport = {}; viewport.x = 0.0f; @@ -1250,8 +1242,10 @@ VkResult record_command_buffer_mesh(VkCommandBuffer command_buffer, VkRenderPass scissor.extent = extent; vkCmdSetScissor(command_buffer, 0, 1, &scissor); - vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline_layout, 0, 1, &material.descriptor_sets[current_frame], 0, 0); - vkCmdDrawIndexed(command_buffer, mesh.index_count, 1, 0, 0, 0); + for(uint i = 0; i < materials_count; i++) { + record_command_buffer_material(materials[i], mesh_counts[i], meshes[i], scene_ubo_descriptor, command_buffer); + } + vkCmdEndRenderPass(command_buffer); return vkEndCommandBuffer(command_buffer); @@ -1346,106 +1340,48 @@ Mesh load_mesh(VkPhysicalDevice physical_device, VkDevice device, struct Vertex* return mesh; } -Material create_simple_mesh_material(VkPhysicalDevice physical_device, VkDevice device, VkExtent2D extent, VkRenderPass render_pass, uint32_t num_frames) { +Material create_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, uint32_t shader_stage_count, VkPipelineShaderStageCreateInfo* shader_stages, VkDescriptorSetLayout scene_ubo_layout, uint32_t set_count, VkDescriptorSetLayout* set_layouts, uint32_t pcr_count, VkPushConstantRange* pcrs) { Material zero_material = { .pipeline = VK_NULL_HANDLE, }; - AllocatedBuffer* uniform_buffers = allocate_buffers(physical_device, device, sizeof(struct ShaderUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, num_frames); - if(uniform_buffers == 0) { + VkDescriptorSetLayout* all_layouts = malloc(sizeof(VkDescriptorSetLayout)*(1+set_count)); + if(all_layouts == 0) { return zero_material; } - void** uniform_buffer_ptrs = malloc(sizeof(void*)*num_frames); - if(uniform_buffer_ptrs == 0) { - free(uniform_buffers); - return zero_material; - } - - for(uint32_t i = 0; i < num_frames; i++) { - VkResult result = vkMapMemory(device, uniform_buffers[i].memory, 0, sizeof(struct ShaderUBO), 0, &uniform_buffer_ptrs[i]); - if(result != VK_SUCCESS) { - for(uint32_t j = 0; j < i; j++) { - vkUnmapMemory(device, uniform_buffers[j].memory); - } - - free(uniform_buffers); - free(uniform_buffer_ptrs); - return zero_material; - } - } - - VkDescriptorPool descriptor_pool = create_descriptor_pool(device, num_frames); - if(descriptor_pool == VK_NULL_HANDLE) { - for(uint32_t i = 0; i < num_frames; i++) { - vkUnmapMemory(device, uniform_buffers[i].memory); - } - - free(uniform_buffers); - free(uniform_buffer_ptrs); - return zero_material; + all_layouts[0] = scene_ubo_layout; + for(uint32_t i = 0; i < set_count; i++) { + all_layouts[i+1] = set_layouts[i]; } - VkDescriptorSetLayoutBinding ubo_layout_binding = { - .binding = 0, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .pImmutableSamplers = 0, - }; - - VkDescriptorSetLayout descriptor_set_layout = create_descriptor_set_layout(device, &ubo_layout_binding, 1); - if(descriptor_set_layout == VK_NULL_HANDLE) { + VkPushConstantRange* all_pcrs = malloc(sizeof(VkPushConstantRange)*(0+pcr_count)); + if((all_pcrs == 0) && (pcr_count != 0)) { + free(all_layouts); return zero_material; } - VkDescriptorSet* descriptor_sets = create_descriptor_sets(device, descriptor_set_layout, descriptor_pool, num_frames); - if(descriptor_sets == 0) { - return zero_material; + for(uint32_t i = 0; i < pcr_count; i++) { + all_pcrs[i] = pcrs[i]; } - for(uint32_t i = 0; i < num_frames; i++) { - VkDescriptorBufferInfo buffer_info = {}; - buffer_info.buffer = uniform_buffers[i].buffer; - buffer_info.offset = 0; - buffer_info.range = sizeof(struct ShaderUBO); - - VkWriteDescriptorSet descriptor_write = {}; - descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptor_write.dstSet = descriptor_sets[i]; - descriptor_write.dstBinding = 0; - descriptor_write.dstArrayElement = 0; - descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; - descriptor_write.descriptorCount = 1; - descriptor_write.pBufferInfo = &buffer_info; - descriptor_write.pImageInfo = 0; - descriptor_write.pTexelBufferView = 0; - - vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0); - } - - VkPipelineLayout pipeline_layout = create_pipeline_layout(device, 1, &descriptor_set_layout, 0, 0); + VkPipelineLayout pipeline_layout = create_pipeline_layout(device, 1+set_count, all_layouts, 0+pcr_count, all_pcrs); if(pipeline_layout == VK_NULL_HANDLE) { + free(all_layouts); + free(all_pcrs); return zero_material; } + free(all_layouts); + free(all_pcrs); - VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass); + VkPipeline pipeline = create_graphics_pipeline(device, extent, pipeline_layout, render_pass, shader_stage_count, shader_stages); if(pipeline == VK_NULL_HANDLE) { return zero_material; } Material material = { - .descriptor_set_layouts_count = 1, - .descriptor_set_layouts = &descriptor_set_layout, - .push_constant_ranges_count = 0, - .push_constant_ranges = 0, .pipeline_layout = pipeline_layout, .pipeline = pipeline, - .descriptor_pool = descriptor_pool, - .frame_count = num_frames, - .descriptor_sets = descriptor_sets, - .uniform_buffers = uniform_buffers, - .uniform_buffer_ptrs = uniform_buffer_ptrs, }; return material; @@ -1608,7 +1544,99 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { context->in_flight_fences = if_fences; } - Material simple_mesh_material = create_simple_mesh_material(context->physical_device, context->device, context->swapchain_extent, context->render_pass, max_frames_in_flight); + VkDescriptorPool scene_ubo_pool = create_descriptor_pool(device, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, max_frames_in_flight); + if(scene_ubo_pool == VK_NULL_HANDLE) { + fprintf(stderr, "failed to create vulkan scene descriptor pool\n"); + return 0; + } else { + context->scene_ubo_pool = scene_ubo_pool; + } + + VkDescriptorSetLayoutBinding scene_ubo_layout_binding = { + .binding = 0, + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, + .descriptorCount = 1, + .pImmutableSamplers = 0, + }; + + VkDescriptorSetLayout scene_ubo_layout = create_descriptor_set_layout(device, &scene_ubo_layout_binding, 1); + if(scene_ubo_layout == VK_NULL_HANDLE) { + fprintf(stderr, "failed to create vulkan scene descriptor layout\n"); + return 0; + } else { + context->scene_ubo_layout = scene_ubo_layout; + } + + VkDescriptorSet* scene_ubo_descriptors = create_descriptor_sets(context->device, context->scene_ubo_layout, context->scene_ubo_pool, max_frames_in_flight); + if(scene_ubo_descriptors == 0) { + fprintf(stderr, "failed to create vulkan scene descriptore\n"); + return 0; + } else { + context->scene_ubo_descriptors = scene_ubo_descriptors; + } + + AllocatedBuffer* scene_ubos = allocate_buffers(context->physical_device, context->device, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, max_frames_in_flight); + if(scene_ubos == 0) { + fprintf(stderr, "failed to create vulkan scnene ubo buffers\n"); + return 0; + } else { + context->scene_ubos = scene_ubos; + } + + void** scene_ubo_ptrs = malloc(sizeof(void*)*max_frames_in_flight); + if(scene_ubo_ptrs == 0) { + return 0; + } else { + context->scene_ubo_ptrs = scene_ubo_ptrs; + } + + for(uint32_t i = 0; i < max_frames_in_flight; i++) { + VkResult result = vkMapMemory(device, context->scene_ubos[i].memory, 0, sizeof(struct SceneUBO), 0, &context->scene_ubo_ptrs[i]); + if(result != VK_SUCCESS) { + for(uint32_t j = 0; j < i; j++) { + vkUnmapMemory(device, context->scene_ubos[j].memory); + } + + fprintf(stderr, "failed to map vulkan buffers to pointers for scene ubos\n"); + return 0; + } + } + + for(uint32_t i = 0; i < max_frames_in_flight; i++) { + VkDescriptorBufferInfo buffer_info = {}; + buffer_info.buffer = context->scene_ubos[i].buffer; + buffer_info.offset = 0; + buffer_info.range = sizeof(struct SceneUBO); + + VkWriteDescriptorSet descriptor_write = {}; + descriptor_write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptor_write.dstSet = context->scene_ubo_descriptors[i]; + descriptor_write.dstBinding = 0; + descriptor_write.dstArrayElement = 0; + descriptor_write.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + descriptor_write.descriptorCount = 1; + descriptor_write.pBufferInfo = &buffer_info; + descriptor_write.pImageInfo = 0; + descriptor_write.pTexelBufferView = 0; + + vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0); + } + + VkShaderModule vert_shader = load_shader_file(2048, "shader_src/basic.vert.spv", device); + VkShaderModule frag_shader = load_shader_file(2048, "shader_src/basic.frag.spv", device); + VkPipelineShaderStageCreateInfo shader_stages[2] = {}; + shader_stages[0].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; + shader_stages[0].stage = VK_SHADER_STAGE_VERTEX_BIT; + shader_stages[0].module = vert_shader; + shader_stages[0].pName = "main"; + + shader_stages[1].sType = VK_STRUCTURE_TYPE_SHADER_CREATE_INFO_EXT; + shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + shader_stages[1].module = frag_shader; + shader_stages[1].pName = "main"; + + Material simple_mesh_material = create_material(context->device, context->swapchain_extent, context->render_pass, 2, shader_stages, context->scene_ubo_layout, 0, 0, 0, 0); if(simple_mesh_material.pipeline == VK_NULL_HANDLE) { fprintf(stderr, "failed to create simple mesh material\n"); return 0; @@ -1626,23 +1654,18 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { return context; } -uint32_t counter = 0; VkResult update_ubo(void** buffers, uint32_t frame_index) { - struct ShaderUBO ubo = {}; + struct SceneUBO ubo = {}; glm_mat4_identity(ubo.proj); glm_mat4_identity(ubo.view); - vec3 axis = {0.0f, 0.0f, 1.0f}; - glm_rotate_make(ubo.model, counter/100.0f, axis); - memcpy(buffers[frame_index], (void*)&ubo, sizeof(ubo)); - counter += 1; return VK_SUCCESS; } VkResult draw_frame(VulkanContext* context) { - update_ubo(context->simple_mesh_material.uniform_buffer_ptrs, context->current_frame); + update_ubo(context->scene_ubo_ptrs, context->current_frame); VkResult result; result = vkWaitForFences(context->device, 1, &context->in_flight_fences[context->current_frame], VK_TRUE, UINT64_MAX); @@ -1666,7 +1689,9 @@ VkResult draw_frame(VulkanContext* context) { return result; } - result = record_command_buffer_mesh(context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent, context->simple_mesh_material, context->triangle_mesh, context->current_frame); + uint32_t mesh_counts[] = {1}; + Mesh* meshes[] = {&context->triangle_mesh}; + result = record_command_buffer_scene(1, &context->simple_mesh_material, (uint32_t*)&mesh_counts, (Mesh**)meshes, context->scene_ubo_descriptors[context->current_frame], context->swapchain_command_buffers[context->current_frame], context->render_pass, context->swapchain_framebuffers[image_index], context->swapchain_extent); if(result != VK_SUCCESS) { return result; }