b7a472fe45
Updated descriptor set build to use function parameters instead of global vars Signed-off-by: Piotr Krygier <piotrkrygier@everyonecancode@xyz>
206 lines
7.9 KiB
C
206 lines
7.9 KiB
C
/**
|
|
* @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 <SDL3/SDL_log.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#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, uint32_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,
|
|
uint32_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,
|
|
uint32_t descriptor_set_id,
|
|
uint16_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,
|
|
uint32_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);
|
|
}
|