Made material/mesh descriptor bindings parameters of the material

main
noah metz 2024-01-09 12:33:38 -07:00
parent 256980435e
commit b9befc50a2
2 changed files with 208 additions and 32 deletions

@ -1,5 +1,7 @@
#version 450 #version 450
layout(binding = 0) uniform sampler2D texSampler;
layout(location = 0) in vec3 fragColor; layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTex; layout(location = 1) in vec2 fragTex;

@ -70,15 +70,31 @@ typedef struct MeshStruct {
uint32_t index_count; uint32_t index_count;
AllocatedBuffer index_buffer; AllocatedBuffer index_buffer;
VkDescriptorSet mesh_descriptors;
} Mesh; } Mesh;
typedef struct DescriptorPoolStruct {
VkDescriptorPool handle;
uint32_t allocated;
} DescriptorPool;
typedef struct GrowingDescriptorPoolStruct {
uint32_t num_pool_sizes;
VkDescriptorPoolSize* pool_sizes;
uint32_t sets_per_pool;
VkDescriptorPoolCreateInfo pool_info;
VkDescriptorSetLayout set_layout;
uint32_t num_pools;
DescriptorPool* pools;
} GrowingDescriptorPool;
typedef struct MaterialStruct { typedef struct MaterialStruct {
VkDescriptorSetLayout material_set_layout;
VkDescriptorSetLayout mesh_set_layout;
VkPipelineLayout pipeline_layout; VkPipelineLayout pipeline_layout;
VkPipeline pipeline; VkPipeline pipeline;
VkDescriptorPool descriptor_pool;
} Material; } Material;
typedef struct VulkanContextStruct { typedef struct VulkanContextStruct {
@ -248,6 +264,122 @@ static VKAPI_ATTR VkBool32 VKAPI_CALL debug_callback(
return VK_FALSE; return VK_FALSE;
} }
GrowingDescriptorPool create_growing_descriptor_pool(VkDevice device, uint32_t num_bindings, VkDescriptorSetLayoutBinding* bindings, uint32_t sets_per_pool) {
GrowingDescriptorPool ret = {
.sets_per_pool = sets_per_pool,
};
VkDescriptorSetLayoutCreateInfo layout_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = num_bindings,
.pBindings = bindings,
};
VkDescriptorSetLayout layout;
VkResult result = vkCreateDescriptorSetLayout(device, &layout_info, 0, &layout);
if(result != VK_SUCCESS) {
return ret;
}
VkDescriptorPoolSize* pool_sizes = malloc(sizeof(VkDescriptorPoolSize)*num_bindings);
if(pool_sizes == 0) {
return ret;
}
for(uint32_t i = 0; i < num_bindings; i++) {
VkDescriptorPoolSize size = {
.type = bindings[i].descriptorType,
.descriptorCount = bindings[i].descriptorCount * sets_per_pool,
};
pool_sizes[i] = size;
}
VkDescriptorPoolCreateInfo pool_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = num_bindings,
.pPoolSizes = pool_sizes,
.maxSets = sets_per_pool,
};
DescriptorPool* pools = malloc(sizeof(DescriptorPool));
if(pools == 0) {
free(pool_sizes);
return ret;
}
result = vkCreateDescriptorPool(device, &pool_info, 0, &pools[0].handle);
if(result != VK_SUCCESS) {
free(pool_sizes);
free(pools);
}
ret.set_layout = layout;
ret.pool_info = pool_info;
ret.pools = pools;
ret.num_pools = 1;
ret.pool_info = pool_info;
ret.pool_sizes = pool_sizes;
return ret;
}
DescriptorPool* grow_descriptor_pool(VkDevice device, GrowingDescriptorPool* pool) {
VkDescriptorPool handle;
VkResult result = vkCreateDescriptorPool(device, &pool->pool_info, 0, &handle);
if(result != VK_SUCCESS) {
return 0;
}
uint32_t new_size = pool->num_pools + 1;
DescriptorPool* new_pools = realloc(pool->pools, sizeof(DescriptorPool)*new_size);
if(new_pools == 0) {
return 0;
}
new_pools[new_size-1].allocated = 0;
new_pools[new_size-1].handle = handle;
pool->pools = new_pools;
pool->num_pools = new_size;
return &new_pools[new_size-1];
}
VkDescriptorSet allocate_descriptor_set(VkDevice device, GrowingDescriptorPool* pool) {
DescriptorPool* selected_pool = 0;
uint32_t index = 0;
for(uint32_t i = 0; i < pool->num_pools; i++) {
if(pool->pools[i].allocated < pool->sets_per_pool) {
selected_pool = &pool->pools[i];
index = i;
break;
}
}
if(selected_pool == 0) {
selected_pool = grow_descriptor_pool(device, pool);
index = pool->num_pools - 1;
if(selected_pool == 0) {
return VK_NULL_HANDLE;
}
}
VkDescriptorSetAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorPool = selected_pool->handle,
.pSetLayouts = &pool->set_layout,
.descriptorSetCount = 1,
};
VkDescriptorSet new_set;
VkResult result = vkAllocateDescriptorSets(device, &alloc_info, &new_set);
if(result != VK_SUCCESS) {
return VK_NULL_HANDLE;
}
pool->pools[index].allocated += 1;
return new_set;
}
VkDescriptorSet* create_descriptor_sets(VkDevice device, VkDescriptorSetLayout layout, VkDescriptorPool pool, uint32_t count) { VkDescriptorSet* create_descriptor_sets(VkDevice device, VkDescriptorSetLayout layout, VkDescriptorPool pool, uint32_t count) {
VkDescriptorSetLayout* layouts = malloc(sizeof(VkDescriptorSetLayout)*count); VkDescriptorSetLayout* layouts = malloc(sizeof(VkDescriptorSetLayout)*count);
if(layouts == 0) { if(layouts == 0) {
@ -444,16 +576,12 @@ VkDebugUtilsMessengerEXT create_debug_messenger(VkInstance instance) {
return debug_messenger; return debug_messenger;
} }
VkDescriptorPool create_descriptor_pool(VkDevice device, VkDescriptorType type, uint32_t size) { VkDescriptorPool create_descriptor_pool(VkDevice device, VkDescriptorPoolSize* sizes, uint32_t num_sizes, uint32_t max_sets) {
VkDescriptorPoolSize pool_size = {};
pool_size.type = type;
pool_size.descriptorCount = size;
VkDescriptorPoolCreateInfo pool_info = {}; VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.poolSizeCount = 1; pool_info.poolSizeCount = num_sizes;
pool_info.pPoolSizes = &pool_size; pool_info.pPoolSizes = sizes;
pool_info.maxSets = size; pool_info.maxSets = max_sets;
VkDescriptorPool pool; VkDescriptorPool pool;
VkResult result = vkCreateDescriptorPool(device, &pool_info, 0, &pool); VkResult result = vkCreateDescriptorPool(device, &pool_info, 0, &pool);
@ -1502,7 +1630,6 @@ void record_command_buffer_mesh(Mesh mesh, VkCommandBuffer command_buffer) {
void record_command_buffer_material(Material material, uint32_t mesh_count, Mesh* meshes, VkDescriptorSet scene_ubo_descriptor, VkCommandBuffer command_buffer) { 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); 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); 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++) { for(uint32_t i = 0; i < mesh_count; i++) {
record_command_buffer_mesh(meshes[i], command_buffer); record_command_buffer_mesh(meshes[i], command_buffer);
} }
@ -1674,6 +1801,8 @@ Mesh load_simple_mesh(VkPhysicalDevice physical_device, VkDevice device, struct
return mesh; return mesh;
} }
uint32_t HARDCODED_SETS_PER_POOL = 10;
Material create_material( Material create_material(
VkDevice device, VkDevice device,
VkExtent2D extent, VkExtent2D extent,
@ -1681,8 +1810,10 @@ Material create_material(
uint32_t shader_stage_count, uint32_t shader_stage_count,
VkPipelineShaderStageCreateInfo* shader_stages, VkPipelineShaderStageCreateInfo* shader_stages,
VkDescriptorSetLayout scene_ubo_layout, VkDescriptorSetLayout scene_ubo_layout,
uint32_t set_count, uint32_t material_set_bindings_count,
VkDescriptorSetLayout* set_layouts, VkDescriptorSetLayoutBinding* material_set_bindings,
uint32_t mesh_set_bindings_count,
VkDescriptorSetLayoutBinding* mesh_set_bindings,
uint32_t pcr_count, uint32_t pcr_count,
VkPushConstantRange* pcrs, VkPushConstantRange* pcrs,
uint32_t bindings_count, uint32_t bindings_count,
@ -1694,19 +1825,45 @@ Material create_material(
.pipeline = VK_NULL_HANDLE, .pipeline = VK_NULL_HANDLE,
}; };
VkDescriptorSetLayout* all_layouts = malloc(sizeof(VkDescriptorSetLayout)*(1+set_count)); VkDescriptorSetLayout material_set_layout;
if(all_layouts == 0) { VkDescriptorSetLayout mesh_set_layout;
VkDescriptorSetLayout all_layouts[3] = {scene_ubo_layout, VK_NULL_HANDLE, VK_NULL_HANDLE};
uint32_t num_layouts = 1;
if(material_set_bindings_count > 0) {
VkDescriptorSetLayoutCreateInfo layout_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = material_set_bindings_count,
.pBindings = material_set_bindings,
};
VkResult result = vkCreateDescriptorSetLayout(device, &layout_info, 0, &material_set_layout);
if(result != VK_SUCCESS) {
return zero_material; return zero_material;
} }
all_layouts[0] = scene_ubo_layout; all_layouts[num_layouts] = material_set_layout;
for(uint32_t i = 0; i < set_count; i++) { num_layouts += 1;
all_layouts[i+1] = set_layouts[i]; }
if(mesh_set_bindings_count > 0) {
VkDescriptorSetLayoutCreateInfo layout_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.bindingCount = mesh_set_bindings_count,
.pBindings = mesh_set_bindings,
};
VkResult result = vkCreateDescriptorSetLayout(device, &layout_info, 0, &mesh_set_layout);
if(result != VK_SUCCESS) {
return zero_material;
}
all_layouts[num_layouts] = mesh_set_layout;
num_layouts += 1;
} }
VkPushConstantRange* all_pcrs = malloc(sizeof(VkPushConstantRange)*(0+pcr_count)); VkPushConstantRange* all_pcrs = malloc(sizeof(VkPushConstantRange)*(0+pcr_count));
if((all_pcrs == 0) && (pcr_count != 0)) { if((all_pcrs == 0) && (pcr_count != 0)) {
free(all_layouts);
return zero_material; return zero_material;
} }
@ -1714,9 +1871,8 @@ Material create_material(
all_pcrs[i] = pcrs[i]; all_pcrs[i] = pcrs[i];
} }
VkPipelineLayout pipeline_layout = create_pipeline_layout(device, 1+set_count, all_layouts, 0+pcr_count, all_pcrs); VkPipelineLayout pipeline_layout = create_pipeline_layout(device, num_layouts, all_layouts, pcr_count, all_pcrs);
if(pipeline_layout == VK_NULL_HANDLE) { if(pipeline_layout == VK_NULL_HANDLE) {
free(all_layouts);
free(all_pcrs); free(all_pcrs);
return zero_material; return zero_material;
} }
@ -1729,6 +1885,9 @@ Material create_material(
Material material = { Material material = {
.pipeline_layout = pipeline_layout, .pipeline_layout = pipeline_layout,
.pipeline = pipeline, .pipeline = pipeline,
.material_set_layout = material_set_layout,
.mesh_set_layout = mesh_set_layout,
}; };
return material; return material;
@ -1771,7 +1930,7 @@ Material create_simple_mesh_material(VkDevice device, VkExtent2D extent, VkRende
}, },
}; };
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, 0, 0, 0, 0, 1, bindings, 2, attributes); return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, 0, 0, 0, 0, 0, 0, 1, bindings, 2, attributes);
} }
Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout) { Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRenderPass render_pass, VkDescriptorSetLayout scene_ubo_layout) {
@ -1796,7 +1955,7 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
shader_stages[1].module = frag_shader; shader_stages[1].module = frag_shader;
shader_stages[1].pName = "main"; shader_stages[1].pName = "main";
VkVertexInputBindingDescription bindings[1] = { VkVertexInputBindingDescription bindings[] = {
{ {
.binding = 0, .binding = 0,
.stride = sizeof(struct TextureVertex), .stride = sizeof(struct TextureVertex),
@ -1804,7 +1963,7 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
}, },
}; };
VkVertexInputAttributeDescription attributes[3] = { VkVertexInputAttributeDescription attributes[] = {
{ {
.binding = 0, .binding = 0,
.location = 0, .location = 0,
@ -1825,7 +1984,17 @@ Material create_texture_mesh_material(VkDevice device, VkExtent2D extent, VkRend
}, },
}; };
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, 0, 0, 0, 0, 1, bindings, 3, attributes); VkDescriptorSetLayoutBinding mesh_set_bindings[] = {
{
.binding = 1,
.descriptorCount = 1,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.pImmutableSamplers = 0,
.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT,
},
};
return create_material(device, extent, render_pass, 2, shader_stages, scene_ubo_layout, 0, 0, 1, mesh_set_bindings, 0, 0, 1, bindings, 3, attributes);
} }
VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) { VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
@ -1985,7 +2154,13 @@ VulkanContext* init_vulkan(GLFWwindow* window, uint32_t max_frames_in_flight) {
context->in_flight_fences = if_fences; context->in_flight_fences = if_fences;
} }
VkDescriptorPool scene_ubo_pool = create_descriptor_pool(device, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, max_frames_in_flight); VkDescriptorPoolSize ubo_pool_sizes[] = {
{
.type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = max_frames_in_flight,
}
};
VkDescriptorPool scene_ubo_pool = create_descriptor_pool(device, ubo_pool_sizes, 1, max_frames_in_flight);
if(scene_ubo_pool == VK_NULL_HANDLE) { if(scene_ubo_pool == VK_NULL_HANDLE) {
fprintf(stderr, "failed to create vulkan scene descriptor pool\n"); fprintf(stderr, "failed to create vulkan scene descriptor pool\n");
return 0; return 0;
@ -2314,7 +2489,6 @@ VkResult update_scene_ubo(void** buffers, uint32_t frame_index, vec3 world_posit
glm_perspective(90.0f, aspect_ratio, 0.1, 100, ubo.proj); glm_perspective(90.0f, aspect_ratio, 0.1, 100, ubo.proj);
glm_quat_look(world_position, world_rotation, ubo.view); glm_quat_look(world_position, world_rotation, ubo.view);
//glm_look(world_position, dir, up, ubo.view);
memcpy(buffers[frame_index], (void*)&ubo, sizeof(ubo)); memcpy(buffers[frame_index], (void*)&ubo, sizeof(ubo));