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); 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); 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); void gpu_page_free(VkDevice device, GPUPage* page);
VkResult gpu_buffer_malloc(VkDevice device, GPUPage* page, VkDeviceSize size, VkBufferUsageFlags usage, GPUBuffer* buffer); 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); VkResult gpu_image_malloc(VkDevice device, GPUPage* page, VkImageCreateInfo* info, GPUImage* image);
void gpu_buffer_free(VkDevice device, GPUBuffer buffer); void gpu_buffer_free(VkDevice device, GPUBuffer buffer);
void gpu_image_free(VkDevice device, GPUImage image); void gpu_image_free(VkDevice device, GPUImage image);
void gpu_free(GPUPage* page, GPUMemoryChunk* memory); void gpu_free(GPUPage* page, GPUMemoryChunk* memory);

@ -108,8 +108,7 @@ typedef struct MeshStruct {
typedef struct GraphicsPipelineInfoStruct { typedef struct GraphicsPipelineInfoStruct {
VkDescriptorSetLayout scene_layout; VkDescriptorSetLayout scene_layout;
VkDescriptorSetLayout set_layout;
VkDescriptorSetLayoutCreateInfo descriptor_info;
VkPipelineVertexInputStateCreateInfo input_info; VkPipelineVertexInputStateCreateInfo input_info;
@ -123,7 +122,6 @@ typedef struct GraphicsPipelineStruct {
VkDescriptorPool descriptor_pool; VkDescriptorPool descriptor_pool;
VkDescriptorSet* descriptors; VkDescriptorSet* descriptors;
VkDescriptorSetLayout descriptors_layout;
VkPipelineLayout layout; VkPipelineLayout layout;
VkPipeline pipeline; VkPipeline pipeline;
@ -1604,87 +1602,101 @@ Object create_renderable(Mesh* mesh, GraphicsPipeline* pipeline) {
return object; return object;
} }
VkResult create_graphics_pipeline( typedef struct TextureSetStruct {
VkDevice device, uint32_t max_images;
VkExtent2D extent, GPUImage** images;
VkRenderPass draw_render_pass,
VkRenderPass offscreen_render_pass,
GraphicsPipelineInfo pipeline_info,
uint32_t max_frames_in_flight,
GraphicsPipeline* out
) {
VkDescriptorSet descriptor;
VkDescriptorPool pool;
} TextureSet;
VkResult create_texture_set(VkDevice device, VkDescriptorSetLayout layout, uint32_t max_images, TextureSet* out) {
if(out == NULL) { if(out == NULL) {
return VK_ERROR_VALIDATION_FAILED_EXT; return VK_ERROR_VALIDATION_FAILED_EXT;
} }
out->max_frames_in_flight = max_frames_in_flight; out->max_images = max_images;
VkResult result = vkCreateDescriptorSetLayout(device, &pipeline_info.descriptor_info, 0, &out->descriptors_layout); out->images = malloc(sizeof(GPUImage*)*max_images);
if(result != VK_SUCCESS) { if(out->images == NULL) {
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; return VK_ERROR_OUT_OF_HOST_MEMORY;
} }
for(uint32_t i = 0; i < pipeline_info.descriptor_info.bindingCount; i++) { VkDescriptorPoolSize sizes[] = {
VkDescriptorPoolSize pool_size = { {
.type = pipeline_info.descriptor_info.pBindings[i].descriptorType, .type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
.descriptorCount = pipeline_info.descriptor_info.pBindings[i].descriptorCount*max_frames_in_flight, .descriptorCount = max_images,
},
}; };
pool_sizes[i] = pool_size;
}
VkDescriptorPoolCreateInfo pool_info = { VkDescriptorPoolCreateInfo pool_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
.poolSizeCount = pipeline_info.descriptor_info.bindingCount, .flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT,
.maxSets = max_frames_in_flight, .maxSets = 1,
.pPoolSizes = pool_sizes, .pPoolSizes = sizes,
.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT, .poolSizeCount = sizeof(sizes) / sizeof(VkDescriptorPoolSize),
.pNext = NULL,
}; };
result = vkCreateDescriptorPool(device, &pool_info, 0, &out->descriptor_pool); VkResult result = vkCreateDescriptorPool(device, &pool_info, 0, &out->pool);
free(pool_sizes);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
free(out->images);
return result; return result;
} };
out->descriptors = malloc(sizeof(VkDescriptorSet)*max_frames_in_flight); VkDescriptorSetLayout layouts[] = {
if(out->descriptors == 0) { layout,
return VK_ERROR_OUT_OF_HOST_MEMORY; };
}
VkDescriptorSetAllocateInfo set_info = {
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
.pSetLayouts = layouts,
.descriptorSetCount = 1,
.descriptorPool = out->pool,
.pNext = NULL,
};
VkDescriptorSetLayout* set_layouts = malloc(sizeof(VkDescriptorSetLayout)*max_frames_in_flight); result = vkAllocateDescriptorSets(device, &set_info, &out->descriptor);
if(set_layouts == 0) { if(result != VK_SUCCESS) {
vkDestroyDescriptorPool(device, out->descriptor_pool, 0); free(out->images);
return VK_ERROR_OUT_OF_HOST_MEMORY; vkDestroyDescriptorPool(device, out->pool, 0);
return result;
} }
for(uint32_t i = 0; i < max_frames_in_flight; i++) { return VK_SUCCESS;
set_layouts[i] = out->descriptors_layout; }
VkResult create_graphics_pipeline(
VkDevice device,
VkExtent2D extent,
VkRenderPass draw_render_pass,
VkRenderPass offscreen_render_pass,
GraphicsPipelineInfo pipeline_info,
uint32_t max_frames_in_flight,
GraphicsPipeline* out
) {
if(out == NULL) {
return VK_ERROR_VALIDATION_FAILED_EXT;
} }
VkDescriptorSetAllocateInfo alloc_info = { out->max_frames_in_flight = max_frames_in_flight;
.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); if(pipeline_info.set_layout != VK_NULL_HANDLE) {
free(set_layouts); out->descriptors = malloc(sizeof(VkDescriptorSet)*max_frames_in_flight);
if(result != VK_SUCCESS) { if(out->descriptors == 0) {
vkDestroyDescriptorPool(device, out->descriptor_pool, 0); return VK_ERROR_OUT_OF_HOST_MEMORY;
return result; }
for(uint32_t i = 0; i < max_frames_in_flight; i++) {
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 = { VkPushConstantRange pcr = {
.stageFlags = VK_SHADER_STAGE_VERTEX_BIT, .stageFlags = VK_SHADER_STAGE_VERTEX_BIT,
@ -1694,13 +1706,13 @@ VkResult create_graphics_pipeline(
VkPipelineLayoutCreateInfo layout_info = { VkPipelineLayoutCreateInfo layout_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.setLayoutCount = 2, .setLayoutCount = num_sets,
.pSetLayouts = all_layouts, .pSetLayouts = all_layouts,
.pushConstantRangeCount = 1, .pushConstantRangeCount = 1,
.pPushConstantRanges = &pcr, .pPushConstantRanges = &pcr,
}; };
result = vkCreatePipelineLayout(device, &layout_info, 0, &out->layout); VkResult result = vkCreatePipelineLayout(device, &layout_info, 0, &out->layout);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
return result; 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 = { VkPipelineVertexInputStateCreateInfo input_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pVertexBindingDescriptions = bindings, .pVertexBindingDescriptions = bindings,
@ -1950,7 +1945,7 @@ VkResult create_simple_mesh_pipeline(VkDevice device, VkExtent2D extent, VkRende
}; };
GraphicsPipelineInfo pipeline_info = { GraphicsPipelineInfo pipeline_info = {
.descriptor_info = set_info, .set_layout = VK_NULL_HANDLE,
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), .shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
.shader_stages = shader_stages, .shader_stages = shader_stages,
.scene_layout = scene_layout, .scene_layout = scene_layout,
@ -2041,6 +2036,18 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
.pNext = &set_flags_info, .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 = { VkPipelineVertexInputStateCreateInfo input_info = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pVertexBindingDescriptions = bindings, .pVertexBindingDescriptions = bindings,
@ -2050,7 +2057,7 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
}; };
GraphicsPipelineInfo pipeline_info = { GraphicsPipelineInfo pipeline_info = {
.descriptor_info = set_info, .set_layout = set_layout,
.shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo), .shader_stages_count = sizeof(shader_stages)/sizeof(VkPipelineShaderStageCreateInfo),
.shader_stages = shader_stages, .shader_stages = shader_stages,
.scene_layout = scene_layout, .scene_layout = scene_layout,
@ -2058,7 +2065,7 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
}; };
GPUPage* memory = NULL; 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) { if(result != VK_SUCCESS) {
return result; return result;
} }
@ -2068,12 +2075,6 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
return result; 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 = { VkExtent2D texture_size = {
.width = 10, .width = 10,
.height = 10, .height = 10,
@ -2127,7 +2128,8 @@ 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); 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++) { texture_set.images[0] = &test_texture.image;
VkDescriptorImageInfo image_info = { VkDescriptorImageInfo image_info = {
.sampler = test_texture.sampler, .sampler = test_texture.sampler,
.imageView = test_texture.view, .imageView = test_texture.view,
@ -2136,7 +2138,7 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
VkWriteDescriptorSet descriptor_write = { VkWriteDescriptorSet descriptor_write = {
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, .sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
.dstSet = out->descriptors[i], .dstSet = texture_set.descriptor,
.dstBinding = 0, .dstBinding = 0,
.dstArrayElement = 0, .dstArrayElement = 0,
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, .descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
@ -2145,9 +2147,13 @@ VkResult create_texture_mesh_pipeline(VkDevice device, VkPhysicalDeviceMemoryPro
.pImageInfo = &image_info, .pImageInfo = &image_info,
.pTexelBufferView = 0, .pTexelBufferView = 0,
}; };
vkUpdateDescriptorSets(device, 1, &descriptor_write, 0, 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; return VK_SUCCESS;
} }
@ -2699,8 +2705,8 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert
}; };
result = vkAllocateDescriptorSets(device, &set_alloc_info, sets); result = vkAllocateDescriptorSets(device, &set_alloc_info, sets);
if(result != VK_SUCCESS) {
free(layouts); free(layouts);
if(result != VK_SUCCESS) {
free(sets); free(sets);
vkDestroyDescriptorPool(device, pool, 0); vkDestroyDescriptorPool(device, pool, 0);
return ret; return ret;
@ -2720,7 +2726,6 @@ SceneContext create_scene_context(VkDevice device, VkPhysicalDeviceMemoryPropert
for(uint32_t i = 0; i < max_frames_in_flight; i++) { 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]); result = gpu_buffer_malloc(device, scene_ubo_memory, sizeof(struct SceneUBO), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT, &ubos[i]);
if(result != VK_SUCCESS) { if(result != VK_SUCCESS) {
free(layouts);
free(sets); free(sets);
free(ubos); free(ubos);
vkFreeDescriptorSets(device, pool, max_frames_in_flight, sets); 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); void** ubo_ptrs = malloc(sizeof(void*)*max_frames_in_flight);
if(ubo_ptrs == 0) { if(ubo_ptrs == 0) {
free(layouts);
free(sets); free(sets);
vkFreeDescriptorSets(device, pool, max_frames_in_flight, sets); vkFreeDescriptorSets(device, pool, max_frames_in_flight, sets);
vkDestroyDescriptorPool(device, pool, 0); 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); 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) { if(mesh == 0) {
return zero; return zero;
} }