From 78977dd7abed5131bc9f36c32ee34f7d121bfa71 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Fri, 12 Jan 2024 22:07:43 -0700 Subject: [PATCH] Switched to using push constants for model matrices --- shader_src/basic.vert | 7 +- shader_src/texture.vert | 7 +- src/main.c | 270 +++++++++++++--------------------------- 3 files changed, 92 insertions(+), 192 deletions(-) diff --git a/shader_src/basic.vert b/shader_src/basic.vert index a665b19..99bb2b5 100644 --- a/shader_src/basic.vert +++ b/shader_src/basic.vert @@ -3,22 +3,19 @@ layout( push_constant ) uniform constants { mat4 view; mat4 proj; + mat4 model; } scene; layout(set = 0, binding = 0) uniform SceneUniform { mat4 test; } scene_ubo; -layout(set = 2, binding = 0) uniform ModelUniform { - mat4 model; -} model_ubo; - layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; layout(location = 0) out vec3 fragColor; void main() { - gl_Position = scene.proj * scene.view * model_ubo.model * vec4(inPosition, 1.0); + gl_Position = scene.proj * scene.view * scene.model * vec4(inPosition, 1.0); fragColor = inColor; } diff --git a/shader_src/texture.vert b/shader_src/texture.vert index 6270cf4..90422c9 100644 --- a/shader_src/texture.vert +++ b/shader_src/texture.vert @@ -3,16 +3,13 @@ layout( push_constant ) uniform constants { mat4 view; mat4 proj; + mat4 model; } scene_pc; layout(set = 0, binding = 0) uniform SceneUniformBuffer { mat4 test; } scene_ubo; -layout(set = 2, binding = 1) uniform ObjectUniformBuffer { - mat4 model; -} object_ubo; - layout(location = 0) in vec3 inPosition; layout(location = 1) in vec3 inColor; layout(location = 2) in vec2 inTex; @@ -21,7 +18,7 @@ layout(location = 0) out vec3 fragColor; layout(location = 1) out vec2 fragTex; void main() { - gl_Position = scene_pc.proj * scene_pc.view * object_ubo.model * vec4(inPosition, 1.0); + gl_Position = scene_pc.proj * scene_pc.view * scene_pc.model * vec4(inPosition, 1.0); fragColor = inColor; fragTex = inTex; } diff --git a/src/main.c b/src/main.c index 10fefdb..d825978 100644 --- a/src/main.c +++ b/src/main.c @@ -91,6 +91,7 @@ typedef struct MappingStruct { #define ATTRIBUTE_ID_DESCRIPTORS 0x00000003 // void***(array of array of data pointers) #define ATTRIBUTE_ID_DESCRIPTOR_SETS 0x00000004 // VkDescriptorSet* #define ATTRIBUTE_ID_POSITION 0x00000005 // Position* +#define ATTRIBUTE_ID_PUSH_CONSTANTS 0x00000006 // void* typedef struct ObjectStruct { Map attributes; @@ -105,13 +106,16 @@ typedef struct MeshTypeStruct { VkVertexInputAttributeDescription* attributes; } MeshType; -// Defines what descriptors are bound at two different upate rates for the pipeline typedef struct PipelineLayoutStruct { uint32_t object_bindings_count; VkDescriptorSetLayoutBinding* object_bindings; uint32_t material_bindings_count; VkDescriptorSetLayoutBinding* material_bindings; + + uint32_t object_pcr_size; + uint32_t material_pcr_size; + Mapping object_pcr_mapping; } PipelineLayout; typedef struct MeshStruct { @@ -134,6 +138,9 @@ typedef struct MaterialStruct { uint32_t material_descriptors_count; Map object_descriptor_mappings; + + PipelineLayout pipeline_layout; + void* material_pcr_ptr; } Material; typedef struct VulkanContextStruct { @@ -190,7 +197,7 @@ typedef struct SceneContextStruct { VkDescriptorSet* descriptors; GPUBuffer* ubos; void** ubo_ptrs; - VkPushConstantRange pcr; + uint32_t pcr_size; } SceneContext; struct TextureVertex { @@ -208,6 +215,10 @@ struct ModelUBO { mat4 model; }; +struct ObjectPC { + mat4 model; +}; + struct SceneUBO { mat4 test; }; @@ -1550,11 +1561,22 @@ void command_draw_object(Material material, Object object, uint32_t frame_num, V Mesh* mesh = maybe_mesh.value; - VkBuffer vertex_buffers[] = {mesh->vertex_buffer.handle}; - VkDeviceSize offsets[] = {0}; + if(material.pipeline_layout.object_pcr_size > 0) { + MaybeValue maybe_attribute = map_lookup(object.attributes, material.pipeline_layout.object_pcr_mapping.index); + if(maybe_attribute.has_value == false) { + return; + } - vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); - vkCmdBindIndexBuffer(command_buffer, mesh->index_buffer.handle, 0, VK_INDEX_TYPE_UINT16); + MaybeValue maybe_pc = map_lookup(object.attributes, ATTRIBUTE_ID_PUSH_CONSTANTS); + if(maybe_pc.has_value == false) { + return; + } + + void** pc_ptrs = maybe_pc.value; + + mapping_functions[material.pipeline_layout.object_pcr_mapping.mapping_type](pc_ptrs[frame_num], maybe_attribute.value); + vkCmdPushConstants(command_buffer, material.layout, VK_SHADER_STAGE_VERTEX_BIT, sizeof(struct ScenePC) + material.pipeline_layout.material_pcr_size, material.pipeline_layout.object_pcr_size, pc_ptrs[frame_num]); + } if(material.object_set_layout != VK_NULL_HANDLE) { MaybeValue maybe_descriptors = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTOR_SETS); @@ -1564,16 +1586,25 @@ void command_draw_object(Material material, Object object, uint32_t frame_num, V VkDescriptorSet* descriptor_sets = maybe_descriptors.value; vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 2, 1, &descriptor_sets[frame_num], 0, 0); - } else { - fprintf(stderr, "test\n"); } + VkBuffer vertex_buffers[] = {mesh->vertex_buffer.handle}; + VkDeviceSize offsets[] = {0}; + + vkCmdBindVertexBuffers(command_buffer, 0, 1, vertex_buffers, offsets); + vkCmdBindIndexBuffer(command_buffer, mesh->index_buffer.handle, 0, VK_INDEX_TYPE_UINT16); + vkCmdDrawIndexed(command_buffer, mesh->index_count, 1, 0, 0, 0); } void command_draw_material(Material material, uint32_t object_count, Object* objects, uint32_t frame_num, VkDescriptorSet* scene_descriptors, struct ScenePC* scene_constants, VkCommandBuffer command_buffer) { vkCmdBindPipeline(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.pipeline); vkCmdPushConstants(command_buffer, material.layout, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(struct ScenePC), scene_constants); + + if(material.material_pcr_ptr != NULL && material.pipeline_layout.material_pcr_size > 0) { + vkCmdPushConstants(command_buffer, material.material_pcr_ptr, VK_SHADER_STAGE_VERTEX_BIT, sizeof(struct ScenePC), material.pipeline_layout.material_pcr_size, material.material_pcr_ptr); + } + vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 0, 1, &scene_descriptors[frame_num], 0, 0); if(material.material_descriptors != 0) { vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, material.layout, 1, 1, &material.material_descriptors[frame_num], 0, 0); @@ -1737,13 +1768,22 @@ Object create_object(uint32_t max_frames_in_flight, uint32_t descriptor_count) { return ret; } -Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_sets_count, VkDescriptorSet* descriptor_sets, uint32_t max_frames_in_flight) { +Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_sets_count, VkDescriptorSet* descriptor_sets, uint32_t pc_size, uint32_t max_frames_in_flight) { Object zero = { .attributes = { .buckets = 0, }, }; + void** pc_ptrs = malloc(sizeof(void*)*max_frames_in_flight); + if(pc_ptrs == NULL) { + return zero; + } + + for(uint32_t i = 0; i < max_frames_in_flight; i++) { + pc_ptrs[i] = malloc(pc_size); + } + Object object = create_object(max_frames_in_flight, descriptor_sets_count); if(object.attributes.buckets == 0) { return zero; @@ -1770,6 +1810,13 @@ Object create_renderable(Mesh* mesh, Material* material, uint32_t descriptor_set map_destroy(object.attributes); return zero; } + + result = map_add(&object.attributes, ATTRIBUTE_ID_PUSH_CONSTANTS, pc_ptrs); + if(result == false) { + map_destroy(object.attributes); + return zero; + } + return object; } @@ -1780,7 +1827,7 @@ Material create_material( uint32_t shader_stage_count, VkPipelineShaderStageCreateInfo* shader_stages, VkDescriptorSetLayout scene_ubo_layout, - VkPushConstantRange scene_pcr, + uint32_t scene_pcr_size, PipelineLayout pipeline_layout, MeshType mesh_type, uint32_t max_frames_in_flight, @@ -1876,13 +1923,19 @@ Material create_material( } VkDescriptorSetLayout all_layouts[3] = {scene_ubo_layout, material_set_layout, object_set_layout}; + VkPushConstantRange pcr = { + .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, + .offset = 0, + .size = scene_pcr_size + pipeline_layout.material_pcr_size + pipeline_layout.object_pcr_size, + }; + VkPipelineLayout layout; VkPipelineLayoutCreateInfo layout_info = { .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .setLayoutCount = 3, .pSetLayouts = all_layouts, .pushConstantRangeCount = 1, - .pPushConstantRanges = &scene_pcr, + .pPushConstantRanges = &pcr, }; result = vkCreatePipelineLayout(device, &layout_info, 0, &layout); @@ -1906,12 +1959,14 @@ Material create_material( .material_descriptor_pool = material_descriptor_pool, .material_descriptors_count = max_frames_in_flight, .object_descriptor_mappings = object_descriptor_mappings, + + .pipeline_layout = pipeline_layout, }; return material; } -Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, VkPushConstantRange scene_pcr, uint32_t max_frames_in_flight) { +Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t scene_pcr_size, uint32_t max_frames_in_flight) { VkShaderModule vert_shader = load_shader_file("shader_src/basic.vert.spv", device); VkShaderModule frag_shader = load_shader_file("shader_src/basic.frag.spv", device); VkPipelineShaderStageCreateInfo shader_stages[2] = { @@ -1929,7 +1984,6 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende }, }; - VkVertexInputBindingDescription bindings[1] = { { .binding = 0, // Which buffer 'binding' to use @@ -1960,58 +2014,21 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende .attributes_count = sizeof(attributes)/sizeof(VkVertexInputAttributeDescription), }; - VkDescriptorSetLayoutBinding object_set_bindings[] = { - { - .binding = 0, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pImmutableSamplers = 0, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - }, - }; - PipelineLayout simple_layout = { - .object_bindings = object_set_bindings, - .object_bindings_count = sizeof(object_set_bindings)/sizeof(VkDescriptorSetLayoutBinding), + .object_pcr_size = sizeof(struct ObjectPC), + .object_pcr_mapping = { + .mapping_type = MAPPING_POSITION_TO_MATRIX, + .index = ATTRIBUTE_ID_POSITION, + }, }; - Map object_descriptor_mappings = map_create(8, 2); - if(object_descriptor_mappings.buckets == 0) { - Material tmp = {}; - return tmp; - } - - Mapping* position_mapping = malloc(sizeof(Mapping)); - if(position_mapping == 0) { - map_destroy(object_descriptor_mappings); - Material tmp = {}; - return tmp; - } - position_mapping->mapping_type = MAPPING_POSITION_TO_MATRIX; - position_mapping->index = 0; - - bool map_result = map_add(&object_descriptor_mappings, ATTRIBUTE_ID_POSITION, position_mapping); - if(map_result != true) { - map_destroy(object_descriptor_mappings); - free(position_mapping); - Material tmp = {}; - return tmp; - } - - return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr, simple_layout, simple_mesh_type, max_frames_in_flight, object_descriptor_mappings); + Map object_descriptor_mappings = {0}; + return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr_size, simple_layout, simple_mesh_type, max_frames_in_flight, object_descriptor_mappings); } -Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, VkPushConstantRange scene_pcr, uint32_t max_frames_in_flight) { +Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout, uint32_t scene_pcr_size, uint32_t max_frames_in_flight) { VkShaderModule vert_shader = load_shader_file("shader_src/texture.vert.spv", device); - if(vert_shader == VK_NULL_HANDLE) { - Material tmp = {}; - return tmp; - } VkShaderModule frag_shader = load_shader_file("shader_src/texture.frag.spv", device); - if(frag_shader == VK_NULL_HANDLE) { - Material tmp = {}; - return tmp; - } VkPipelineShaderStageCreateInfo shader_stages[2] = { { .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, @@ -2065,13 +2082,6 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend .pImmutableSamplers = 0, .stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT, }, - { - .binding = 1, - .descriptorCount = 1, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .pImmutableSamplers = 0, - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - }, }; MeshType textured_mesh_type = { @@ -2084,32 +2094,16 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend PipelineLayout texture_layout = { .object_bindings_count = sizeof(mesh_set_bindings)/sizeof(VkDescriptorSetLayoutBinding), .object_bindings = mesh_set_bindings, - }; - Map object_descriptor_mappings = map_create(8, 2); - if(object_descriptor_mappings.buckets == 0) { - Material tmp = {}; - return tmp; - } - - Mapping* position_mapping = malloc(sizeof(Mapping)); - if(position_mapping == 0) { - map_destroy(object_descriptor_mappings); - Material tmp = {}; - return tmp; - } - position_mapping->mapping_type = MAPPING_POSITION_TO_MATRIX; - position_mapping->index = 0; - - bool map_result = map_add(&object_descriptor_mappings, ATTRIBUTE_ID_POSITION, position_mapping); - if(map_result != true) { - map_destroy(object_descriptor_mappings); - free(position_mapping); - Material tmp = {}; - return tmp; - } + .object_pcr_size = sizeof(struct ObjectPC), + .object_pcr_mapping = { + .mapping_type = MAPPING_POSITION_TO_MATRIX, + .index = ATTRIBUTE_ID_POSITION, + }, + }; - return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); + Map object_descriptor_mappings = {0}; + return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, scene_pcr_size, texture_layout, textured_mesh_type, max_frames_in_flight, object_descriptor_mappings); } VkResult command_copy_to_buffer(VkDevice device, GPUBuffer staging, VkBuffer destination, void* data, VkDeviceSize size, VkDeviceSize offset, VkCommandPool pool, VkQueue queue) { @@ -2521,11 +2515,7 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert .descriptors = sets, .ubos = ubos, .ubo_ptrs = ubo_ptrs, - .pcr = { - .offset = 0, - .size = sizeof(struct ScenePC), - .stageFlags = VK_SHADER_STAGE_VERTEX_BIT, - }, + .pcr_size = sizeof(struct ScenePC), }; return scene; @@ -2862,7 +2852,7 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic return zero; } - Object object = create_renderable(mesh, simple_mesh_material, 1, sets, max_frames_in_flight); + Object object = create_renderable(mesh, simple_mesh_material, 1, sets, sizeof(struct ObjectPC), max_frames_in_flight); if(object.attributes.buckets == 0) { return zero; } @@ -2883,45 +2873,6 @@ Object create_simple_mesh_object(Material* simple_mesh_material, VkPhysicalDevic return zero; } - GPUBuffer* position_buffers = malloc(sizeof(GPUBuffer)*max_frames_in_flight); - if(position_buffers == NULL) { - return zero; - } - - for(uint32_t i = 0; i < max_frames_in_flight; i++) { - result = gpu_buffer_malloc(device, transfer_memory, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &position_buffers[i]); - if(result != VK_SUCCESS) { - return zero; - } - } - - MaybeValue maybe_ptrs = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTORS); - if(maybe_ptrs.has_value == false) { - return zero; - } - - void*** ptrs = maybe_ptrs.value; - for(uint32_t i = 0; i < max_frames_in_flight; i++) { - *ptrs[i] = position_buffers[i].page->ptr + position_buffers[i].memory->offset; - VkDescriptorBufferInfo buffer_info = { - .buffer = position_buffers[i].handle, - .offset = 0, - .range = sizeof(struct ModelUBO), - }; - - VkWriteDescriptorSet write_info = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = sets[i], - .dstBinding = 0, - .dstArrayElement = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .pBufferInfo = &buffer_info, - }; - - vkUpdateDescriptorSets(device, 1, &write_info, 0, 0); - } - return object; } @@ -2977,7 +2928,7 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev return zero; } - Object object = create_renderable(mesh, texture_mesh_material, 1, sets, max_frames_in_flight); + Object object = create_renderable(mesh, texture_mesh_material, 1, sets, sizeof(struct ObjectPC), max_frames_in_flight); if(object.attributes.buckets == 0) { return zero; } @@ -2998,47 +2949,6 @@ Object create_texture_mesh_object(Material* texture_mesh_material, VkPhysicalDev return zero; } - GPUBuffer* position_buffers = malloc(sizeof(GPUBuffer)*max_frames_in_flight); - if(position_buffers == NULL) { - return zero; - } - - for(uint32_t i = 0; i < max_frames_in_flight; i++) { - result = gpu_buffer_malloc(device, transfer_memory, sizeof(struct ModelUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &position_buffers[i]); - if(result != VK_SUCCESS) { - return zero; - } - } - - MaybeValue maybe_ptrs = map_lookup(object.attributes, ATTRIBUTE_ID_DESCRIPTORS); - if(maybe_ptrs.has_value == false) { - return zero; - } - - void*** ptrs = maybe_ptrs.value; - - for(uint32_t i = 0; i < max_frames_in_flight; i++) { - *ptrs[i] = position_buffers[i].page->ptr + position_buffers[i].memory->offset; - - VkDescriptorBufferInfo buffer_info = { - .buffer = position_buffers[i].handle, - .offset = 0, - .range = sizeof(struct ModelUBO), - }; - - VkWriteDescriptorSet write_info = { - .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, - .dstSet = sets[i], - .dstBinding = 1, - .dstArrayElement = 0, - .descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = 1, - .pBufferInfo = &buffer_info, - }; - - vkUpdateDescriptorSets(device, 1, &write_info, 0, 0); - } - VkExtent2D texture_size = { .width = 10, .height = 10, @@ -3102,7 +3012,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { return; } - Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr, context->max_frames_in_flight); + Material simple_mesh_material = create_simple_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr_size, context->max_frames_in_flight); if(simple_mesh_material.pipeline == VK_NULL_HANDLE) { fprintf(stderr, "failed to create simple mesh material\n"); return; @@ -3135,7 +3045,7 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { return; } - Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr, context->max_frames_in_flight); + Material texture_mesh_material = create_texture_mesh_material(context->device, context->swapchain_extent, context->render_pass, scene.descriptor_layout, scene.pcr_size, context->max_frames_in_flight); if(texture_mesh_material.pipeline == VK_NULL_HANDLE) { fprintf(stderr, "failed to create texture mesh material\n"); return; @@ -3146,10 +3056,6 @@ void main_loop(GLFWwindow* window, VulkanContext* context) { .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorCount = context->max_frames_in_flight, }, - { - .type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, - .descriptorCount = context->max_frames_in_flight, - }, }; VkDescriptorPoolCreateInfo texture_pool_info = {