Added TextureSet for large pools of textures in a single descriptor

main
noah metz 2024-01-15 23:22:12 -07:00
parent 4a321a1ce3
commit 007520a92c
2 changed files with 120 additions and 109 deletions

@ -42,10 +42,16 @@ typedef struct GPUImageStruct {
GPUMemoryType pick_memory(VkPhysicalDeviceMemoryProperties memories, uint32_t filter, VkMemoryPropertyFlags include, VkMemoryPropertyFlags exclude);
VkResult gpu_page_allocate(VkDevice device, VkPhysicalDeviceMemoryProperties memories, VkDeviceSize size, uint32_t filter, VkMemoryPropertyFlags include, VkMemoryPropertyFlags exclude, VkMemoryAllocateFlags allocate_flags, GPUPage** handle);
void gpu_page_free(VkDevice device, GPUPage* page);
VkResult gpu_buffer_malloc(VkDevice device, GPUPage* page, VkDeviceSize size, VkBufferUsageFlags usage, GPUBuffer* buffer);
VkResult gpu_image_malloc(VkDevice device, GPUPage* page, VkImageCreateInfo* info, GPUImage* image);
void gpu_buffer_free(VkDevice device, GPUBuffer buffer);
void gpu_image_free(VkDevice device, GPUImage image);
void gpu_free(GPUPage* page, GPUMemoryChunk* memory);

@ -108,8 +108,7 @@ typedef struct MeshStruct {
typedef struct GraphicsPipelineInfoStruct {
VkDescriptorSetLayout scene_layout;
VkDescriptorSetLayoutCreateInfo descriptor_info;
VkDescriptorSetLayout set_layout;
VkPipelineVertexInputStateCreateInfo input_info;
@ -123,7 +122,6 @@ typedef struct GraphicsPipelineStruct {
VkDescriptorPool descriptor_pool;
VkDescriptorSet* descriptors;
VkDescriptorSetLayout descriptors_layout;
VkPipelineLayout layout;
VkPipeline pipeline;
@ -1604,6 +1602,70 @@ Object create_renderable(Mesh* mesh, GraphicsPipeline* pipeline) {
return object;
}
typedef struct TextureSetStruct {
uint32_t max_images;
GPUImage** images;
VkDescriptorSet descriptor;
VkDescriptorPool pool;
} TextureSet;
VkResult create_texture_set(VkDevice device, VkDescriptorSetLayout layout, uint32_t max_images, TextureSet* out) {
if(out == NULL) {
return VK_ERROR_VALIDATION_FAILED_EXT;
}
out->max_images = max_images;
out->images = malloc(sizeof(GPUImage*)*max_images);
if(out->images == NULL) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
VkDescriptorPoolSize sizes[] = {
{
.type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = max_images,
},
};
VkDescriptorPoolCreateInfo pool_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
.maxSets = 1,
.pPoolSizes = sizes,
.poolSizeCount = sizeof(sizes) / sizeof(VkDescriptorPoolSize),
.pNext = NULL,
};
VkResult result = vkCreateDescriptorPool(device, &pool_info, 0, &out->pool);
if(result != VK_SUCCESS) {
free(out->images);
return result;
};
VkDescriptorSetLayout layouts[] = {
layout,
};
VkDescriptorSetAllocateInfo set_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.pSetLayouts = layouts,
.descriptorSetCount = 1,
.descriptorPool = out->pool,
.pNext = NULL,
};
result = vkAllocateDescriptorSets(device, &set_info, &out->descriptor);
if(result != VK_SUCCESS) {
free(out->images);
vkDestroyDescriptorPool(device, out->pool, 0);
return result;
}
return VK_SUCCESS;
}
VkResult create_graphics_pipeline(
VkDevice device,
VkExtent2D extent,
@ -1620,71 +1682,21 @@ VkResult create_graphics_pipeline(
out->max_frames_in_flight = max_frames_in_flight;
VkResult result = vkCreateDescriptorSetLayout(device, &pipeline_info.descriptor_info, 0, &out->descriptors_layout);
if(result != VK_SUCCESS) {
return result;
}
if(pipeline_info.descriptor_info.bindingCount > 0) {
VkDescriptorPoolSize* pool_sizes = malloc(sizeof(VkDescriptorPool)*(1 + pipeline_info.descriptor_info.bindingCount));
if(pool_sizes == 0) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
for(uint32_t i = 0; i < pipeline_info.descriptor_info.bindingCount; i++) {
VkDescriptorPoolSize pool_size = {
.type = pipeline_info.descriptor_info.pBindings[i].descriptorType,
.descriptorCount = pipeline_info.descriptor_info.pBindings[i].descriptorCount*max_frames_in_flight,
};
pool_sizes[i] = pool_size;
}
VkDescriptorPoolCreateInfo pool_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = pipeline_info.descriptor_info.bindingCount,
.maxSets = max_frames_in_flight,
.pPoolSizes = pool_sizes,
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT,
};
result = vkCreateDescriptorPool(device, &pool_info, 0, &out->descriptor_pool);
free(pool_sizes);
if(result != VK_SUCCESS) {
return result;
}
if(pipeline_info.set_layout != VK_NULL_HANDLE) {
out->descriptors = malloc(sizeof(VkDescriptorSet)*max_frames_in_flight);
if(out->descriptors == 0) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
VkDescriptorSetLayout* set_layouts = malloc(sizeof(VkDescriptorSetLayout)*max_frames_in_flight);
if(set_layouts == 0) {
vkDestroyDescriptorPool(device, out->descriptor_pool, 0);
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
set_layouts[i] = out->descriptors_layout;
}
VkDescriptorSetAllocateInfo alloc_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.descriptorSetCount = max_frames_in_flight,
.descriptorPool = out->descriptor_pool,
.pSetLayouts = set_layouts,
};
result = vkAllocateDescriptorSets(device, &alloc_info, out->descriptors);
free(set_layouts);
if(result != VK_SUCCESS) {
vkDestroyDescriptorPool(device, out->descriptor_pool, 0);
return result;
out->descriptors[i] = VK_NULL_HANDLE;
}
}
VkDescriptorSetLayout all_layouts[2] = {pipeline_info.scene_layout, out->descriptors_layout};
VkDescriptorSetLayout all_layouts[2] = {pipeline_info.scene_layout, pipeline_info.set_layout};
uint32_t num_sets = 1;
if(pipeline_info.set_layout != VK_NULL_HANDLE) {
num_sets += 1;
}
VkPushConstantRange pcr = {
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
@ -1694,13 +1706,13 @@ VkResult create_graphics_pipeline(
VkPipelineLayoutCreateInfo layout_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 2,
.setLayoutCount = num_sets,
.pSetLayouts = all_layouts,
.pushConstantRangeCount = 1,
.pPushConstantRanges = &pcr,
};
result = vkCreatePipelineLayout(device, &layout_info, 0, &out->layout);
VkResult result = vkCreatePipelineLayout(device, &layout_info, 0, &out->layout);
if(result != VK_SUCCESS) {
return result;
}
@ -1924,23 +1936,6 @@ VkResult create_simple_mesh_pipeline(VkDevice device, VkExtent2D extent, VkRende
},
};
VkDescriptorSetLayoutBinding set_bindings[] = {
{
.binding = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
.descriptorCount = 1,
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
.pImmutableSamplers = 0,
},
};
VkDescriptorSetLayoutCreateInfo set_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
.pBindings = set_bindings,
.bindingCount = sizeof(set_bindings)/sizeof(VkDescriptorSetLayoutBinding),
.pNext = NULL,
};
VkPipelineVertexInputStateCreateInfo input_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pVertexBindingDescriptions = bindings,
@ -1950,7 +1945,7 @@ VkResult create_simple_mesh_pipeline(VkDevice device, VkExtent2D extent, VkRende
};
GraphicsPipelineInfo pipeline_info = {
.descriptor_info = set_info,
.set_layout = VK_NULL_HANDLE,
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
.shader_stages = shader_stages,
.scene_layout = scene_layout,
@ -2041,6 +2036,18 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
.pNext = &set_flags_info,
};
VkDescriptorSetLayout set_layout = VK_NULL_HANDLE;
VkResult result = vkCreateDescriptorSetLayout(device, &set_info, 0, &set_layout);
if(result != VK_SUCCESS) {
return result;
}
TextureSet texture_set = {0};
result = create_texture_set(device, set_layout, 1000, &texture_set);
if(result != VK_SUCCESS) {
return result;
}
VkPipelineVertexInputStateCreateInfo input_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pVertexBindingDescriptions = bindings,
@ -2050,7 +2057,7 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
};
GraphicsPipelineInfo pipeline_info = {
.descriptor_info = set_info,
.set_layout = set_layout,
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
.shader_stages = shader_stages,
.scene_layout = scene_layout,
@ -2058,7 +2065,7 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
};
GPUPage* memory = NULL;
VkResult result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, &memory);
result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, &memory);
if(result != VK_SUCCESS) {
return result;
}
@ -2068,12 +2075,6 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
return result;
}
GPUPage* tex_memory = NULL;
result = gpu_page_allocate(device, memories, 100000, 0xFFFFFFFF, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, 0, &tex_memory);
if(result != VK_SUCCESS) {
return result;
}
VkExtent2D texture_size = {
.width = 10,
.height = 10,
@ -2127,27 +2128,32 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
Texture test_texture = load_texture(device, texture_memory, staging, transfer_pool, transfer_queue, graphics_pool, graphics_queue, texture_size, VK_FORMAT_R8G8B8A8_SRGB, texture_data, transfer_family, graphics_family);
for(uint32_t i = 0; i < out->max_frames_in_flight; i++) {
VkDescriptorImageInfo image_info = {
.sampler = test_texture.sampler,
.imageView = test_texture.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
texture_set.images[0] = &test_texture.image;
VkWriteDescriptorSet descriptor_write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = out->descriptors[i],
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 1,
.pBufferInfo = 0,
.pImageInfo = &image_info,
.pTexelBufferView = 0,
};
VkDescriptorImageInfo image_info = {
.sampler = test_texture.sampler,
.imageView = test_texture.view,
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
};
vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0);
VkWriteDescriptorSet descriptor_write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = texture_set.descriptor,
.dstBinding = 0,
.dstArrayElement = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = 1,
.pBufferInfo = 0,
.pImageInfo = &image_info,
.pTexelBufferView = 0,
};
vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 0);
for(uint32_t i = 0; i < out->max_frames_in_flight; i++) {
fprintf(stderr, "descriptor[%d]: %p\n", i, out->descriptors[i]);
out->descriptors[i] = texture_set.descriptor;
}
return VK_SUCCESS;
}
@ -2699,8 +2705,8 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert
};
result = vkAllocateDescriptorSets(device, &set_alloc_info, sets);
free(layouts);
if(result != VK_SUCCESS) {
free(layouts);
free(sets);
vkDestroyDescriptorPool(device, pool, 0);
return ret;
@ -2720,7 +2726,6 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
result = gpu_buffer_malloc(device, scene_ubo_memory, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &ubos[i]);
if(result != VK_SUCCESS) {
free(layouts);
free(sets);
free(ubos);
vkFreeDescriptorSets(device, pool, max_frames_in_flight, sets);
@ -2731,7 +2736,6 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert
void** ubo_ptrs = malloc(sizeof(void*)*max_frames_in_flight);
if(ubo_ptrs == 0) {
free(layouts);
free(sets);
vkFreeDescriptorSets(device, pool, max_frames_in_flight, sets);
vkDestroyDescriptorPool(device, pool, 0);
@ -3109,6 +3113,7 @@ Object create_simple_mesh_object(PlyMesh ply_mesh, GraphicsPipeline* simple_mesh
}
Mesh* mesh = load_mesh_to_buffer(device, mesh_memory, transfer_buffer, ply_mesh.vertex_count, sizeof(struct Vertex), (void*)tmp, ply_mesh.index_count, sizeof(uint16_t), (void*)ply_mesh.index, transfer_pool, transfer_queue);
free(tmp);
if(mesh == 0) {
return zero;
}