/** * @file descriptor_builder.c * @author Piotr Krygier (everyonecancode@gmail.com) * @brief * @version 0.1 * @date 2025-03-14 * * @copyright Copyright (c) 2025 * */ #include "descriptor_builder.h" #include #include #include #include "src/graphics_context.h" #include "src/vulkan_commons.h" #include "utilities/commons.h" #include "utilities/errors_common.h" #include "vulkan/vulkan_core.h" #define POOL_MAX_SETS (32U) rse_err_t descriptor_pool_add_type(struct graphics_context_t* context, VkDescriptorType type, uint32_t count) { context->descriptor_data.pool_sizes[context->descriptor_data.pool_sizes_count].type = type; context->descriptor_data.pool_sizes[context->descriptor_data.pool_sizes_count].descriptorCount = count; context->descriptor_data.pool_sizes_count++; return RSE_ERROR_NO_ERROR; } rse_err_t descriptor_pool_initialize(struct graphics_context_t* context) { VkDescriptorPoolCreateInfo create_info = {0}; create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO; create_info.pNext = NULL; create_info.flags = 0U; create_info.maxSets = POOL_MAX_SETS; create_info.poolSizeCount = context->descriptor_data.pool_sizes_count; create_info.pPoolSizes = context->descriptor_data.pool_sizes; if (vkCreateDescriptorPool(context->vulkan_handles.device, &create_info, NULL, &context->descriptor_data.descriptor_pool) != VK_SUCCESS) { SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create descriptor pool"); return RSE_ERROR_INTERNAL_ERROR; } return RSE_ERROR_NO_ERROR; } rse_err_t descriptor_create_new_set(struct graphics_context_t* context, rse_id_t* set_id) { if (context->descriptor_data.descriptor_sets_count >= DESCRIPTOR_MAX_SETS) { SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Reached maximum number of available descriptor sets"); return RSE_ERROR_INTERNAL_ERROR; } *set_id = context->descriptor_data.descriptor_sets_count++; return RSE_ERROR_NO_ERROR; } rse_err_t descriptor_add_layout(struct descriptor_set_layout_bindings_t* layout_bindings, uint32_t binding, VkDescriptorType type, uint32_t descriptor_count, VkShaderStageFlags shader_stages) { layout_bindings->layout_bindings[layout_bindings->layout_bindings_count].binding = binding; layout_bindings->layout_bindings[layout_bindings->layout_bindings_count].descriptorType = type; layout_bindings->layout_bindings[layout_bindings->layout_bindings_count].descriptorCount = descriptor_count; layout_bindings->layout_bindings[layout_bindings->layout_bindings_count].stageFlags = shader_stages; layout_bindings->layout_bindings_count++; return RSE_ERROR_NO_ERROR; } rse_err_t descriptor_set_finish(struct graphics_context_t* context, struct descriptor_set_layout_bindings_t* layout_bindings, rse_id_t set_id) { VkDescriptorSetLayoutCreateInfo create_info = {0}; create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; create_info.bindingCount = layout_bindings->layout_bindings_count; create_info.pBindings = layout_bindings->layout_bindings; if (VK_SUCCESS != vkCreateDescriptorSetLayout(context->vulkan_handles.device, &create_info, NULL, &context->descriptor_data.set_layouts[set_id])) { SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create descriptor sets layout"); return RSE_ERROR_INTERNAL_ERROR; } layout_bindings->layout_bindings_count = 0U; rse_memset(layout_bindings->layout_bindings, 0, sizeof(VkDescriptorSetLayoutBinding) * DESCRIPTOR_MAX_SETS); return RSE_ERROR_NO_ERROR; } rse_err_t descriptor_build_sets(struct graphics_context_t* context) { VkDescriptorSetAllocateInfo alloc_info = {0}; if (NULL == context) { SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Provided NULL context"); return RSE_ERROR_NULL_POINTER; } if (context->descriptor_data.descriptor_pool == VK_NULL_HANDLE) { SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Requested descriptor build, but descriptor pool has not been initialized"); } /* Allocate descriptors from the pool */ alloc_info.descriptorPool = context->descriptor_data.descriptor_pool; alloc_info.descriptorSetCount = context->descriptor_data.descriptor_sets_count; alloc_info.pSetLayouts = context->descriptor_data.set_layouts; alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO; if (VK_SUCCESS != vkAllocateDescriptorSets(context->vulkan_handles.device, &alloc_info, context->descriptor_data.descriptor_sets)) { SDL_LogCritical(SDL_LOG_CATEGORY_GPU, "Failed to create descriptor sets"); return RSE_ERROR_INTERNAL_ERROR; } return RSE_ERROR_NO_ERROR; } rse_err_t descriptor_attach_images(struct graphics_context_t* context, rse_id_t descriptor_set_id, rse_id_t* texture_ids, size_t images_count, VkSampler sampler, uint32_t binding) { size_t iter = 0U; VkDescriptorImageInfo* image_infos = NULL; VkWriteDescriptorSet write_set = {0}; rse_malloc(image_infos, sizeof(VkDescriptorImageInfo) * images_count); for (iter = 0U; iter < images_count; ++iter) { image_infos[iter].sampler = sampler; image_infos[iter].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; image_infos[iter].imageView = context->texture_images[texture_ids[iter]].image_view; } write_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_set.pImageInfo = image_infos; write_set.dstSet = context->descriptor_data.descriptor_sets[descriptor_set_id]; write_set.dstBinding = binding; write_set.dstArrayElement = 0U; write_set.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; // TODO: Maybe not only samplers? write_set.descriptorCount = images_count; vkUpdateDescriptorSets(context->vulkan_handles.device, 1U, &write_set, 0, NULL); rse_free(image_infos); return RSE_ERROR_NO_ERROR; } rse_err_t descriptor_attach_buffer(struct graphics_context_t* context, rse_id_t descriptor_set_id, struct vulkan_buffer_t* buffer, uint32_t binding, VkDescriptorType type) { VkDescriptorBufferInfo buffer_info = {0}; VkWriteDescriptorSet write_set = {0}; buffer_info.buffer = buffer->buffer; buffer_info.offset = 0U; buffer_info.range = buffer->allocated_size; write_set.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; write_set.pBufferInfo = &buffer_info; write_set.dstSet = context->descriptor_data.descriptor_sets[descriptor_set_id]; write_set.dstBinding = binding; write_set.dstArrayElement = 0U; write_set.descriptorType = type; write_set.descriptorCount = 1; vkUpdateDescriptorSets(context->vulkan_handles.device, 1U, &write_set, 0, NULL); return RSE_ERROR_NO_ERROR; } void destroy_descriptors(struct graphics_context_t* context) { size_t iter = 0U; for (iter = 0U; iter < context->descriptor_data.descriptor_sets_count; ++iter) { vkDestroyDescriptorSetLayout(context->vulkan_handles.device, context->descriptor_data.set_layouts[iter], NULL); } vkDestroyDescriptorPool(context->vulkan_handles.device, context->descriptor_data.descriptor_pool, NULL); }