[WIP] Add descriptors and pipeline builder

This commit is contained in:
Piotr Krygier committed 2025-06-20 13:44:33 +02:00
1 parent 173a82b9d1
commit f8eb98ddf4
36 files changed
+613 -458

No files matched your search

+99 -339
View File
@@ -11,6 +11,10 @@
#include "pipeline_builder.h"
#include <assert.h>
#include <stdint.h>
#include "src/graphics_context.h"
#include "utilities/commons.h"
#include "utilities/errors_common.h"
#include "utilities/file_utils.h"
@@ -22,6 +26,40 @@
#define MAX_BINDLESS_RESOURCES 1000
RSE_LINKED_LIST_DEFINE(vertex_binding_list_t, VkVertexInputBindingDescription);
RSE_LINKED_LIST_DEFINE(shader_attribute_list_t,
VkVertexInputAttributeDescription);
RSE_LINKED_LIST_DEFINE(dynamic_state_list_t, VkDynamicState);
RSE_LINKED_LIST_DEFINE(pipeline_infos_list_t, VkGraphicsPipelineCreateInfo);
RSE_STACK_DEFINE(required_dynamic_states_t, VkDynamicState, 16U);
struct pipeline_t {
VkPipeline pipeline;
uint8_t id;
/* Shader stages */
size_t shader_stages_count;
VkPipelineShaderStageCreateInfo shader_stages[MAX_SHADER_STAGES];
/* Input assembly */
VkPipelineInputAssemblyStateCreateInfo input_assembly;
/* Viewport state */
VkPipelineViewportStateCreateInfo viewport_state;
/* Rasterizer */
VkPipelineRasterizationStateCreateInfo rasterizer;
/* Multisampling */
VkPipelineMultisampleStateCreateInfo multisampling;
/* Color blending */
VkPipelineColorBlendAttachmentState color_blend_attachment;
VkPipelineColorBlendStateCreateInfo color_blending;
/* Depth stencil */
VkPipelineDepthStencilStateCreateInfo depth_stencil;
struct vertex_binding_list_t* vertex_bindings;
struct shader_attribute_list_t* shader_attributes;
struct dynamic_state_list_t* dynamic_states;
struct required_dynamic_states_t required_dynamic_states;
};
/**
* @brief Creates shader module
*
@@ -42,9 +80,9 @@ static rse_err_t create_shader_module(struct graphics_context_t* context,
RSE_LINKED_LIST_PUSH_FRONT(context->shader_modules, (VkShaderModule){0});
if (VK_SUCCESS != vkCreateShaderModule(
context->device, &create_info, NULL,
&RSE_LINKED_LIST_FRONT(context->shader_modules))) {
if (VK_SUCCESS !=
vkCreateShaderModule(context->device, &create_info, NULL,
&RSE_LINKED_LIST_FRONT(context->shader_modules))) {
LOGF(_("Failed to create a shader\n"));
return VULKAN_ERROR_SHADER_CREATION_FAILED;
}
@@ -124,7 +162,7 @@ static rse_err_t pipeline_add_multisampling(struct pipeline_t* pipeline)
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
pipeline->multisampling.pNext = NULL;
pipeline->multisampling.flags = 0U;
pipeline->multisampling.rasterizationSamples = VK_SAMPLE_COUNT_16_BIT;
pipeline->multisampling.rasterizationSamples = VK_SAMPLE_COUNT_8_BIT;
pipeline->multisampling.sampleShadingEnable = VK_FALSE;
pipeline->multisampling.minSampleShading = 1.0f;
pipeline->multisampling.pSampleMask = NULL;
@@ -212,104 +250,6 @@ static rse_err_t create_pipeline_layout(struct graphics_context_t* context)
return RSE_ERROR_NO_ERROR;
}
/**
* @brief Create a Render Pass
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_RENDERPASS_CREATION_FAILED
*/
static rse_err_t create_render_pass(struct graphics_context_t* context)
{
rse_err_t status = RSE_ERROR_NO_ERROR;
VkAttachmentDescription attachments[3] = {};
VkAttachmentDescription color_attachment = {};
VkAttachmentReference color_attachment_ref = {};
VkAttachmentDescription color_attachment_resolve = {};
VkAttachmentReference color_attachment_resolve_ref = {};
VkSubpassDescription subpass = {};
VkRenderPassCreateInfo renderpass_info = {};
VkAttachmentDescription depth_attachment = {};
VkAttachmentReference depth_attachment_ref = {};
VkSubpassDependency dependency = {};
STATUS_CHECK(find_depth_format(context, &depth_attachment.format));
depth_attachment.samples = VK_SAMPLE_COUNT_16_BIT;
depth_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
depth_attachment.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
depth_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
depth_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
depth_attachment.finalLayout =
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
depth_attachment_ref.attachment = 1;
depth_attachment_ref.layout =
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
color_attachment.flags = 0U;
color_attachment.format = IMAGE_FORMAT;
color_attachment.samples = VK_SAMPLE_COUNT_16_BIT;
color_attachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
color_attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE;
color_attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
color_attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
color_attachment.finalLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment_ref.attachment = 0;
color_attachment_ref.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
color_attachment_resolve.format = IMAGE_FORMAT;
color_attachment_resolve.samples = VK_SAMPLE_COUNT_1_BIT;
color_attachment_resolve.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment_resolve.storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
color_attachment_resolve.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
color_attachment_resolve.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
color_attachment_resolve.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
color_attachment_resolve.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
color_attachment_resolve_ref.attachment = 2;
color_attachment_resolve_ref.layout =
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
subpass.colorAttachmentCount = 1;
subpass.pColorAttachments = &color_attachment_ref;
subpass.pDepthStencilAttachment = &depth_attachment_ref;
subpass.pResolveAttachments = &color_attachment_resolve_ref;
attachments[0] = color_attachment;
attachments[1] = depth_attachment;
attachments[2] = color_attachment_resolve;
dependency.srcSubpass = VK_SUBPASS_EXTERNAL;
dependency.dstSubpass = 0;
dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.srcAccessMask = 0;
dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT |
VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT;
dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT |
VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
renderpass_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
renderpass_info.attachmentCount = 3;
renderpass_info.pAttachments = attachments;
renderpass_info.subpassCount = 1;
renderpass_info.pSubpasses = &subpass;
renderpass_info.dependencyCount = 1;
renderpass_info.pDependencies = &dependency;
if (VK_SUCCESS != vkCreateRenderPass(context->device, &renderpass_info,
NULL, &context->render_pass)) {
LOGF(_("Failed to create render pass\n"));
return VULKAN_ERROR_RENDERPASS_CREATION_FAILED;
}
return RSE_ERROR_NO_ERROR;
}
/**
* @brief Clean up pipeline builder. This function should be called after all
* pipelines are built and no more pipelines are needed. It frees all resources
@@ -339,6 +279,10 @@ static void pipeline_builder_cleanup(struct pipeline_infos_list_t* pipelines)
dynamic_states =
(VkDynamicState*)pipeline_info->pDynamicState->pDynamicStates;
rse_free((VkPipelineVertexInputStateCreateInfo*)
pipeline_info->pVertexInputState);
rse_free((VkPipelineDynamicStateCreateInfo*)
pipeline_info->pDynamicState);
rse_free(vertex_bindings);
rse_free(shader_attributes);
rse_free(dynamic_states);
@@ -351,140 +295,6 @@ static void pipeline_builder_cleanup(struct pipeline_infos_list_t* pipelines)
}
}
/**
* @brief Create a Descriptor Pool
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED
*/
static rse_err_t create_descriptor_pool(struct graphics_context_t* context, struct binding_info_t* binding_infos, size_t binding_count)
{
VkDescriptorPoolSize pool_sizes[2] = {};
VkDescriptorPoolCreateInfo pool_info = {};
pool_sizes[0].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
pool_sizes[0].descriptorCount = (uint32_t)(SWAP_BUFFER_COUNT);
pool_sizes[1].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
pool_sizes[1].descriptorCount = MAX_BINDLESS_RESOURCES;
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
pool_info.poolSizeCount = 1;
pool_info.pPoolSizes = &pool_sizes[0];
pool_info.maxSets = (uint32_t)(SWAP_BUFFER_COUNT);
if (vkCreateDescriptorPool(context->device, &pool_info, NULL,
&context->descriptor_pool) != VK_SUCCESS) {
LOGF(_("Failed to create descriptor pool\n"));
return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED;
}
pool_info.flags = VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT;
pool_info.maxSets = MAX_BINDLESS_RESOURCES * 2;
pool_info.pPoolSizes = &pool_sizes[1];
if (vkCreateDescriptorPool(context->device, &pool_info, NULL,
&context->descriptor_pool_bindless) !=
VK_SUCCESS) {
LOGF(_("Failed to create descriptor pool\n"));
return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED;
}
return RSE_ERROR_NO_ERROR;
}
/**
* @brief Create a Descriptor Sets
*
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
* VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED */
static rse_err_t create_descriptor_sets(struct graphics_context_t* context)
{
uint32_t max_binding = MAX_BINDLESS_RESOURCES - 1;
VkDescriptorSetLayout layouts[SWAP_BUFFER_COUNT] = {
context->descriptor_set_layout, context->descriptor_set_layout};
VkDescriptorSetLayout layouts_bindless[SWAP_BUFFER_COUNT] = {
context->descriptor_set_layout_bindless,
context->descriptor_set_layout_bindless};
VkDescriptorSetAllocateInfo allocInfo = {};
VkDescriptorSetAllocateInfo allocInfo_bindless = {};
VkDescriptorSetVariableDescriptorCountAllocateInfoEXT count_info = {};
count_info.sType =
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO_EXT;
count_info.descriptorSetCount = 1;
count_info.pDescriptorCounts = &max_binding;
allocInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
allocInfo.descriptorPool = context->descriptor_pool;
allocInfo.descriptorSetCount = (uint32_t)(SWAP_BUFFER_COUNT);
allocInfo.pSetLayouts = layouts;
allocInfo_bindless = allocInfo;
allocInfo_bindless.descriptorPool = context->descriptor_pool_bindless;
allocInfo_bindless.pSetLayouts = layouts_bindless;
allocInfo_bindless.pNext = &count_info;
allocInfo_bindless.descriptorSetCount = 1;
if (vkAllocateDescriptorSets(context->device, &allocInfo,
context->descriptor_sets) != VK_SUCCESS) {
LOGF(_("Failed to allocate descriptor sets\n"));
return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED;
}
if (vkAllocateDescriptorSets(context->device, &allocInfo_bindless,
&context->descriptor_sets_bindless) !=
VK_SUCCESS) {
LOGF(_("Failed to allocate descriptor sets\n"));
return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED;
}
for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) {
VkDescriptorBufferInfo buffer_info = {};
VkWriteDescriptorSet descriptor_writes[2] = {};
VkDescriptorImageInfo image_infos[RSE_MAX_IMAGE_COUNT] = {};
size_t image_iterator = 0U;
size_t image_info_iterator = 0U;
buffer_info.buffer = context->uniform_buffers[i].buffer;
buffer_info.offset = 0;
buffer_info.range = sizeof(struct uniform_buffer_object_t);
for (image_iterator = 0U; image_iterator < RSE_MAX_IMAGE_COUNT;
++image_iterator) {
if (image_exists(context, image_iterator)) {
image_infos[image_info_iterator].imageLayout =
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
image_infos[image_info_iterator].imageView =
context->swapchain_image_views[image_iterator];
image_infos[image_info_iterator].sampler = context->sampler;
image_info_iterator++;
}
}
descriptor_writes[0].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_writes[0].dstSet = context->descriptor_sets[i];
descriptor_writes[0].dstBinding = 0;
descriptor_writes[0].dstArrayElement = 0;
descriptor_writes[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
descriptor_writes[0].descriptorCount = 1;
descriptor_writes[0].pBufferInfo = &buffer_info;
descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_writes[1].dstSet = context->descriptor_sets_bindless;
descriptor_writes[1].dstBinding = 1;
descriptor_writes[1].dstArrayElement = 0;
descriptor_writes[1].descriptorType =
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
descriptor_writes[1].descriptorCount = image_info_iterator;
descriptor_writes[1].pImageInfo = image_infos;
vkUpdateDescriptorSets(context->device, 2, descriptor_writes, 0, NULL);
}
return RSE_ERROR_NO_ERROR;
}
rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline,
VkDynamicState dynamic_state)
{
@@ -498,19 +308,21 @@ rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline,
return RSE_ERROR_NO_ERROR;
}
rse_err_t pipeline_builder_init(struct pipeline_t* pipeline)
rse_err_t pipeline_builder_init(struct pipeline_t** pipeline)
{
rse_err_t status = RSE_ERROR_NO_ERROR;
struct pipeline_t* pipeline_ptr = NULL;
if (pipeline != NULL) {
if (*pipeline != NULL) {
LOGF(
_("Pipeline is not NULL. This function will initialize everything "
"for you, no need for manual allocation\n"));
return VULKAN_ERROR_PIPELINE_ALREADY_INITIALIZED;
}
rse_malloc(pipeline, sizeof(struct pipeline_t));
rse_memset(pipeline, 0, sizeof(struct pipeline_t));
rse_malloc(pipeline_ptr, sizeof(struct pipeline_t));
rse_memset(pipeline_ptr, 0, sizeof(struct pipeline_t));
*pipeline = pipeline_ptr;
return status;
}
@@ -608,95 +420,31 @@ rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline,
return RSE_ERROR_NO_ERROR;
}
rse_err_t pipeline_add_descriptor_layout(struct graphics_context_t* context,
struct binding_info_t* binding_infos,
size_t binding_count,
size_t* descriptor_set_index)
rse_err_t pipelines_build(struct graphics_context_t* context,
struct pipeline_infos_list_t* pipelines_infos_list)
{
VkDescriptorSetLayoutCreateInfo layout_info = {};
VkDescriptorSetLayoutBinding* bindings = NULL;
VkDescriptorSetLayoutBindingFlagsCreateInfoEXT extended_info = {0};
VkDescriptorBindingFlags bindless_flags =
VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT |
VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT_EXT |
VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT;
assert(NULL != context);
assert(NULL != pipelines_infos_list);
if (binding_count == 0) {
LOGF(_("No bindings in descriptor set layout\n"));
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_NO_BINDINGS;
}
if (context->pipelines_data.descriptor_set_layouts_count + 1 >
MAX_DESCRIPTOR_SETS) {
LOGF(_("Too many descriptor sets\n"));
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_TOO_MANY;
}
rse_malloc(bindings, sizeof(VkDescriptorSetLayoutBinding) * binding_count);
for (size_t i = 0; i < binding_count; i++) {
bindings[i].binding = binding_infos[i].binding;
bindings[i].descriptorType = binding_infos[i].descriptor_type;
bindings[i].descriptorCount = 1;
bindings[i].stageFlags = binding_infos[i].stage_flags;
bindings[i].pImmutableSamplers = NULL;
if (bindings[i].descriptorType ==
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
bindings[i].pImmutableSamplers = NULL;
bindings[i].descriptorCount = MAX_BINDLESS_RESOURCES;
extended_info.sType =
VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
extended_info.bindingCount++;
extended_info.pBindingFlags = &bindless_flags;
layout_info.pNext = &extended_info;
layout_info.flags =
VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
}
}
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layout_info.bindingCount = (uint32_t)binding_count;
layout_info.pBindings = bindings;
if (vkCreateDescriptorSetLayout(
context->device, &layout_info, NULL,
&context->pipelines_data.descriptor_set_layouts
[context->pipelines_data.descriptor_set_layouts_count]) !=
VK_SUCCESS) {
LOGF(_("Failed to create descriptor set layout\n"));
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
}
*descriptor_set_index =
context->pipelines_data.descriptor_set_layouts_count;
context->pipelines_data.descriptor_set_layouts_count++;
rse_free(bindings);
return RSE_ERROR_NO_ERROR;
}
rse_err_t build_pipelines(struct graphics_context_t* context,
struct pipeline_infos_list_t* pipelines)
{
size_t i = 0U;
rse_err_t status = RSE_ERROR_NO_ERROR;
size_t pipelines_count = RSE_LINKED_LIST_SIZE(pipelines);
size_t pipelines_count = RSE_LINKED_LIST_SIZE(pipelines_infos_list);
VkGraphicsPipelineCreateInfo* pipeline_infos = NULL;
context->pipelines_data.pipelines_count = pipelines_count;
create_pipeline_layout(context);
create_render_pass(context);
create_descriptor_pool(context, NULL, 0);
STATUS_CHECK(create_pipeline_layout(context));
rse_malloc(pipeline_infos,
sizeof(VkGraphicsPipelineCreateInfo) * pipelines_count);
RSE_LINKED_LIST_TO_ARRAY(pipelines, pipeline_infos);
RSE_LINKED_LIST_TO_ARRAY(pipelines_infos_list, pipeline_infos);
/* FIXME: layout is created to late. Maybe move it somewhere else so we
* don't need this loop? */
for (i = 0; i < pipelines_count; ++i) {
pipeline_infos[i].layout = context->pipelines_data.pipeline_layout;
}
if (VK_SUCCESS !=
vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE,
@@ -707,14 +455,14 @@ rse_err_t build_pipelines(struct graphics_context_t* context,
}
rse_free(pipeline_infos);
pipeline_builder_cleanup(pipelines);
pipeline_builder_cleanup(pipelines_infos_list);
return status;
}
rse_err_t add_pipeline(const struct graphics_context_t* context,
struct pipeline_t* pipeline,
struct pipeline_infos_list_t* pipelines)
struct pipeline_infos_list_t** pipelines_infos)
{
/* Check for send and required dynamic states */
rse_err_t status = RSE_ERROR_NO_ERROR;
@@ -722,14 +470,17 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
size_t vertex_bindings_count = 0U;
VkVertexInputBindingDescription* vertex_bindings = NULL;
VkPipelineVertexInputStateCreateInfo* vertex_bindings_ci = NULL;
size_t shader_attributes_count = 0U;
VkVertexInputAttributeDescription* shader_attributes = NULL;
size_t dynamic_states_count = 0U;
VkDynamicState* dynamic_states = NULL;
VkPipelineDynamicStateCreateInfo* dynamic_states_ci = NULL;
uint8_t dynamic_state_found = 0;
while (RSE_STACK_IS_EMPTY(pipeline->required_dynamic_states) == 0) {
dynamic_state_found = 0;
VkDynamicState dynamic_state =
@@ -794,15 +545,20 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
pipeline_info.flags = 0U;
pipeline_info.stageCount = pipeline->shader_stages_count;
pipeline_info.pStages = pipeline->shader_stages;
pipeline_info.pVertexInputState = &(VkPipelineVertexInputStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
.pNext = NULL,
.flags = 0U,
.vertexBindingDescriptionCount = vertex_bindings_count,
.pVertexBindingDescriptions = vertex_bindings,
.vertexAttributeDescriptionCount = shader_attributes_count,
.pVertexAttributeDescriptions = shader_attributes,
};
rse_malloc(vertex_bindings_ci,
sizeof(VkPipelineVertexInputStateCreateInfo));
vertex_bindings_ci->sType =
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertex_bindings_ci->pNext = NULL;
vertex_bindings_ci->flags = 0U;
vertex_bindings_ci->vertexBindingDescriptionCount = vertex_bindings_count;
vertex_bindings_ci->pVertexBindingDescriptions = vertex_bindings;
vertex_bindings_ci->vertexAttributeDescriptionCount =
shader_attributes_count;
vertex_bindings_ci->pVertexAttributeDescriptions = shader_attributes;
pipeline_info.pVertexInputState = vertex_bindings_ci;
pipeline_info.pInputAssemblyState = &pipeline->input_assembly;
pipeline_info.pTessellationState = NULL;
pipeline_info.pViewportState = &pipeline->viewport_state;
@@ -810,19 +566,23 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
pipeline_info.pMultisampleState = &pipeline->multisampling;
pipeline_info.pDepthStencilState = &pipeline->depth_stencil;
pipeline_info.pColorBlendState = &pipeline->color_blending;
pipeline_info.pDynamicState = &(VkPipelineDynamicStateCreateInfo){
.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
.pNext = NULL,
.flags = 0U,
.dynamicStateCount = dynamic_states_count,
.pDynamicStates = dynamic_states,
};
rse_malloc(dynamic_states_ci, sizeof(VkPipelineDynamicStateCreateInfo));
dynamic_states_ci->sType =
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
dynamic_states_ci->pNext = NULL;
dynamic_states_ci->flags = 0U;
dynamic_states_ci->dynamicStateCount = dynamic_states_count;
dynamic_states_ci->pDynamicStates = dynamic_states;
pipeline_info.pDynamicState = dynamic_states_ci;
pipeline_info.layout = context->pipelines_data.pipeline_layout;
pipeline_info.renderPass = context->render_pass;
pipeline_info.subpass = 0;
pipeline_info.basePipelineHandle =
VK_NULL_HANDLE; // TODO: Add possiblity do derive from another pipeline
pipeline_info.basePipelineIndex = -1;
RSE_LINKED_LIST_PUSH_BACK(*pipelines_infos, pipeline_info);
return status;
}
@@ -831,7 +591,7 @@ void destroy_pipelines(struct graphics_context_t* context)
{
size_t i = 0;
size_t shader_modules_count = RSE_LINKED_LIST_SIZE(context->shader_modules);
vkDestroyRenderPass(context->device, context->render_pass, NULL);
for (i = 0; i < context->pipelines_data.pipelines_count; i++) {
if (context->pipelines_data.pipelines[i] != VK_NULL_HANDLE) {
vkDestroyPipeline(context->device,
@@ -851,8 +611,8 @@ void destroy_pipelines(struct graphics_context_t* context)
for (i = 0; i < shader_modules_count; i++) {
if (RSE_LINKED_LIST_FRONT(context->shader_modules) != VK_NULL_HANDLE) {
vkDestroyShaderModule(
context->device,
RSE_LINKED_LIST_FRONT(context->shader_modules), NULL);
context->device, RSE_LINKED_LIST_FRONT(context->shader_modules),
NULL);
}
RSE_LINKED_LIST_POP_FRONT(context->shader_modules);
}