Switched to using push constants for model matrices

main
noah metz 2024-01-12 22:07:43 -07:00
parent 8dea83ca37
commit 78977dd7ab
3 changed files with 92 additions and 192 deletions

@ -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;
}

@ -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;
}

@ -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 = {