From 007520a92c400232dfdad529c3dfb433fa83e7bd Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Mon, 15 Jan 2024 23:22:12 -0700 Subject: [PATCH] Added TextureSet for large pools of textures in a single descriptor --- include/gpu_mem.h | 6 ++ src/main.c | 223 ++++++++++++++++++++++++---------------------- 2 files changed, 120 insertions(+), 109 deletions(-) diff --git a/include/gpu_mem.h b/include/gpu_mem.h index 2ba67eb..e389a6b 100644 --- a/include/gpu_mem.h +++ b/include/gpu_mem.h @@ -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); diff --git a/src/main.c b/src/main.c index 96950de..1ca5777 100644 --- a/src/main.c +++ b/src/main.c @@ -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; }