[WIP] Continue working on pipeline
This commit is contained in:
1 parent
f8eb98ddf4
commit
daed76f02f
28 files changed
+467
-2156
No files matched your search
@@ -22,18 +22,25 @@
|
||||
#include "vulkan/vulkan_core.h"
|
||||
#include "vulkan_errors.h"
|
||||
|
||||
RSE_LINKED_LIST_DEFINE(descriptor_set_layout_list_t,
|
||||
VkDescriptorSetLayoutBinding);
|
||||
RSE_LINKED_LIST_DEFINE(descriptor_set_layout_list_t, VkDescriptorSetLayoutBinding);
|
||||
|
||||
struct descriptor_t
|
||||
{
|
||||
uint32_t binding;
|
||||
VkDescriptorType type;
|
||||
uint32_t descriptors_count;
|
||||
uint32_t descriptor_count;
|
||||
VkShaderStageFlags shader_stages;
|
||||
VkSampler immutable_sampler;
|
||||
};
|
||||
RSE_LINKED_LIST_DEFINE(descriptors_list_t, struct descriptor_t);
|
||||
|
||||
RSE_LINKED_LIST_DEFINE(descriptor_set_list_t, struct descriptor_t);
|
||||
|
||||
struct descriptor_set_handle_t
|
||||
{
|
||||
VkDescriptorSet descriptor_sets;
|
||||
VkDescriptorPool descriptor_pool;
|
||||
VkDescriptorSetLayout descriptor_sets_layout;
|
||||
};
|
||||
|
||||
/* FIXME: When new descriptors are introduced to Vulkan, this enum has to be
|
||||
* updated */
|
||||
@@ -59,40 +66,37 @@ enum descriptor_type_id_t
|
||||
DESCRIPTOR_TYPE_ID_MAX_ENUM,
|
||||
};
|
||||
|
||||
struct descriptors_data_t
|
||||
rse_err_t descriptor_add_set(struct descriptor_set_list_t* descriptor_set_list, uint32_t binding, VkDescriptorType type,
|
||||
uint32_t descriptor_count, VkShaderStageFlags shader_stages, VkSampler sampler)
|
||||
{
|
||||
VkDescriptorPool pool;
|
||||
VkDescriptorSet set;
|
||||
struct descriptor_set_layout_list_t layouts_list;
|
||||
};
|
||||
struct descriptor_t descriptor_sets = {.binding = binding,
|
||||
.type = type,
|
||||
.descriptor_count = descriptor_count,
|
||||
.shader_stages = shader_stages,
|
||||
.immutable_sampler = sampler};
|
||||
|
||||
rse_err_t descriptor_add(struct descriptors_list_t* descriptors_list,
|
||||
uint32_t binding, VkDescriptorType type,
|
||||
uint32_t descriptors_count,
|
||||
VkShaderStageFlags shader_stages, VkSampler sampler)
|
||||
{
|
||||
struct descriptor_t descriptor = {.binding = binding,
|
||||
.type = type,
|
||||
.descriptors_count = descriptors_count,
|
||||
.shader_stages = shader_stages,
|
||||
.immutable_sampler = sampler};
|
||||
|
||||
RSE_LINKED_LIST_PUSH_BACK(descriptors_list, descriptor);
|
||||
RSE_LINKED_LIST_PUSH_BACK(descriptor_set_list, descriptor_sets);
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
rse_err_t descriptors_build(struct graphics_context_t* context,
|
||||
struct descriptors_list_t* descriptors)
|
||||
rse_err_t descriptors_build(struct graphics_context_t* context, struct descriptor_set_list_t* descriptors,
|
||||
struct descriptor_set_handle_t* descriptor_set_handle)
|
||||
{
|
||||
VkDescriptorPoolCreateInfo pool_create_info = {};
|
||||
VkDescriptorPoolCreateFlags pool_create_flags = 0U;
|
||||
VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;
|
||||
VkDescriptorPoolSize pool_sizes[DESCRIPTOR_TYPE_ID_MAX_ENUM] = {};
|
||||
VkDescriptorPoolSize requested_pool_sizes[DESCRIPTOR_TYPE_ID_MAX_ENUM] = {};
|
||||
uint32_t pool_max_sets = 0;
|
||||
size_t pool_size_count = 0U;
|
||||
size_t iterator = 0U;
|
||||
size_t pool_size_count = 0U;
|
||||
uint32_t pool_max_sets = 0U;
|
||||
uint32_t sets_per_type = 0U;
|
||||
VkDescriptorPool descriptor_pool = VK_NULL_HANDLE;
|
||||
VkDescriptorPoolCreateInfo pool_create_info = {0};
|
||||
VkDescriptorPoolCreateFlags pool_create_flags = 0U; // TODO: Flags not set anywhere
|
||||
VkDescriptorPoolSize pool_sizes[DESCRIPTOR_TYPE_ID_MAX_ENUM] = {0};
|
||||
VkDescriptorPoolSize requested_pool_sizes[DESCRIPTOR_TYPE_ID_MAX_ENUM] = {0};
|
||||
VkDescriptorSetAllocateInfo alloc_info = {0};
|
||||
VkDescriptorSetLayoutBinding layout_bindings[DESCRIPTOR_TYPE_ID_MAX_ENUM] = {0};
|
||||
VkDescriptorSetLayoutCreateInfo layout_create_info = {0};
|
||||
VkDescriptorSetLayout set_layout = VK_NULL_HANDLE;
|
||||
VkDescriptorSet descriptor_sets = VK_NULL_HANDLE;
|
||||
|
||||
if (NULL == context) {
|
||||
LOGF(_("Provided NULL context\n"));
|
||||
@@ -100,118 +104,193 @@ rse_err_t descriptors_build(struct graphics_context_t* context,
|
||||
return RSE_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
iterator = 0U;
|
||||
RSE_LINKED_LIST_FOREACH(descriptors, descriptor)
|
||||
{
|
||||
switch (descriptor->data.type) {
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLER_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLER_ID].type = VK_DESCRIPTOR_TYPE_SAMPLER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLER_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
pool_sizes[DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLED_IMAGE_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLED_IMAGE_ID].type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLED_IMAGE_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_IMAGE_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_IMAGE_ID].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_IMAGE_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID].type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID].type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_ID].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_ID].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC;
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||
pool_sizes[DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
pool_sizes[DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID].type = VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT;
|
||||
pool_sizes[DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
|
||||
pool_sizes[DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK;
|
||||
pool_sizes[DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID].type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK;
|
||||
pool_sizes[DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
|
||||
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR;
|
||||
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
|
||||
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV;
|
||||
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM:
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM;
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM:
|
||||
pool_sizes[DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM;
|
||||
pool_sizes[DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID]
|
||||
.descriptorCount++;
|
||||
pool_sizes[DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID].type = VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM;
|
||||
pool_sizes[DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID].descriptorCount++;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_MUTABLE_EXT:
|
||||
pool_sizes[DESCRIPTOR_TYPE_MUTABLE_EXT_ID].type =
|
||||
VK_DESCRIPTOR_TYPE_MUTABLE_EXT;
|
||||
pool_sizes[DESCRIPTOR_TYPE_MUTABLE_EXT_ID].type = VK_DESCRIPTOR_TYPE_MUTABLE_EXT;
|
||||
pool_sizes[DESCRIPTOR_TYPE_MUTABLE_EXT_ID].descriptorCount++;
|
||||
break;
|
||||
default:
|
||||
LOGF(_("Invalid descriptor type provided\n"));
|
||||
return VULKAN_ERROR_UNKNOWN_DESCRIPTOR_TYPE;
|
||||
}
|
||||
|
||||
layout_bindings[iterator].binding = descriptor->data.binding;
|
||||
layout_bindings[iterator].descriptorCount = descriptor->data.descriptor_count;
|
||||
layout_bindings[iterator].descriptorType = descriptor->data.type;
|
||||
layout_bindings[iterator].pImmutableSamplers = descriptor->data.immutable_sampler;
|
||||
layout_bindings[iterator].stageFlags = descriptor->data.shader_stages;
|
||||
iterator++;
|
||||
}
|
||||
|
||||
layout_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
|
||||
layout_create_info.bindingCount = iterator;
|
||||
layout_create_info.pBindings = layout_bindings;
|
||||
if (VK_SUCCESS != vkCreateDescriptorSetLayout(context->device, &layout_create_info, NULL, &set_layout)) {
|
||||
LOGF(_("Failed to create descriptor sets layout\n"));
|
||||
return VULKAN_ERROR_DESCRIPTOR_SET_LAYOUT_CREATION_FAILED;
|
||||
}
|
||||
|
||||
/* Another loop. Seems bit too many? TODO: Optimize this later.
|
||||
* What I'm doing here is calculating minimum viable number of pool max sets. This is a bit tricky, as
|
||||
* (unintuitively) we have to select the MINIMUM number of sets, not maximum. This makes sense, but is difficult to
|
||||
* wrap headr around */
|
||||
RSE_LINKED_LIST_FOREACH(descriptors, descriptor)
|
||||
{
|
||||
switch (descriptor->data.type) {
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLER:
|
||||
sets_per_type =
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLER_ID].descriptorCount / descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
|
||||
sets_per_type =
|
||||
pool_sizes[DESCRIPTOR_TYPE_SAMPLED_IMAGE_ID].descriptorCount / descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
|
||||
sets_per_type =
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_IMAGE_ID].descriptorCount / descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
|
||||
sets_per_type =
|
||||
pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_ID].descriptorCount / descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
|
||||
sets_per_type =
|
||||
pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_ID].descriptorCount / descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
|
||||
sets_per_type =
|
||||
pool_sizes[DESCRIPTOR_TYPE_INPUT_ATTACHMENT_ID].descriptorCount / descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_KHR_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_ACCELERATION_STRUCTURE_NV_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_SAMPLE_WEIGHT_IMAGE_QCOM_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM:
|
||||
sets_per_type = pool_sizes[DESCRIPTOR_TYPE_BLOCK_MATCH_IMAGE_QCOM_ID].descriptorCount /
|
||||
descriptor->data.descriptor_count;
|
||||
break;
|
||||
case VK_DESCRIPTOR_TYPE_MUTABLE_EXT:
|
||||
sets_per_type =
|
||||
pool_sizes[DESCRIPTOR_TYPE_MUTABLE_EXT_ID].descriptorCount / descriptor->data.descriptor_count;
|
||||
break;
|
||||
default:
|
||||
LOGF(_("Invalid descriptor type provided\n"));
|
||||
return VULKAN_ERROR_UNKNOWN_DESCRIPTOR_TYPE;
|
||||
}
|
||||
|
||||
if (pool_max_sets == 0 || pool_max_sets > sets_per_type) {
|
||||
pool_max_sets = sets_per_type;
|
||||
}
|
||||
}
|
||||
|
||||
/* Allocate pool based on layout */
|
||||
/* create array of required descriptors */
|
||||
for (iterator = 0U; iterator < DESCRIPTOR_TYPE_ID_MAX_ENUM; ++iterator) {
|
||||
if (pool_sizes[iterator].descriptorCount > 0) {
|
||||
requested_pool_sizes[pool_size_count].type =
|
||||
pool_sizes[iterator].type;
|
||||
requested_pool_sizes[pool_size_count].descriptorCount =
|
||||
pool_sizes[iterator].descriptorCount;
|
||||
requested_pool_sizes[pool_size_count].type = pool_sizes[iterator].type;
|
||||
requested_pool_sizes[pool_size_count].descriptorCount = pool_sizes[iterator].descriptorCount;
|
||||
pool_size_count++;
|
||||
}
|
||||
}
|
||||
@@ -219,10 +298,32 @@ rse_err_t descriptors_build(struct graphics_context_t* context,
|
||||
pool_create_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
|
||||
pool_create_info.pNext = NULL;
|
||||
pool_create_info.flags = pool_create_flags;
|
||||
pool_create_info.maxSets =
|
||||
0; // FIXME: Calculate number of sets based on layout
|
||||
pool_create_info.maxSets = pool_max_sets;
|
||||
pool_create_info.poolSizeCount = pool_size_count;
|
||||
pool_create_info.pPoolSizes = requested_pool_sizes;
|
||||
|
||||
if (VK_SUCCESS != vkCreateDescriptorPool(context->device, &pool_create_info, NULL, &descriptor_pool)) {
|
||||
LOGF(_("Failed to create descriptor pool\n"));
|
||||
return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED;
|
||||
}
|
||||
|
||||
/* Allocate descriptors from the pool */
|
||||
alloc_info.descriptorPool = &descriptor_pool;
|
||||
alloc_info.descriptorSetCount =
|
||||
pool_max_sets; /* TODO: Always allocating maximum number of sets? This might get weird */
|
||||
alloc_info.pSetLayouts = set_layout;
|
||||
alloc_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
|
||||
|
||||
if (VK_SUCCESS != vkAllocateDescriptorSets(context->device, &alloc_info, &descriptor_sets)) {
|
||||
LOGF(_("Failed to create descriptor sets\n"));
|
||||
return VULKAN_ERROR_DESCRIPTOR_SET_CREATION_FAILED;
|
||||
}
|
||||
|
||||
descriptor_set_handle->descriptor_pool = descriptor_pool;
|
||||
descriptor_set_handle->descriptor_sets = descriptor_sets;
|
||||
descriptor_set_handle->descriptor_sets_layout = set_layout;
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
rse_err_t descriptor_get_layouts()
|
||||
@@ -12,6 +12,32 @@
|
||||
#ifndef DESCRIPTOR_BUILDER_H
|
||||
#define DESCRIPTOR_BUILDER_H
|
||||
|
||||
struct descriptors_list_t;
|
||||
struct descriptor_set_handle_t;
|
||||
struct descriptor_set_list_t;
|
||||
|
||||
#endif // !DESCRIPTOR_BUILDER_H
|
||||
/**
|
||||
* @brief Add descriptor set to provided list
|
||||
*
|
||||
* @param descriptor_set_list List to be filled
|
||||
* @param binding Descriptors binding
|
||||
* @param type Type of descriptors
|
||||
* @param descriptor_count Number of descriptors in this set
|
||||
* @param shader_stages In what stages this descriptors will be used
|
||||
* @param sampler If descriptor set is a sampler, provide it here
|
||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success, error code on failure
|
||||
*/
|
||||
rse_err_t descriptor_add_set(struct descriptor_set_list_t* descriptor_set_list, uint32_t binding, VkDescriptorType type,
|
||||
uint32_t descriptor_count, VkShaderStageFlags shader_stages, VkSampler sampler);
|
||||
|
||||
/**
|
||||
* @brief Allocate descriptor sets from provided list. The data will be stored in opaque descriptor handle
|
||||
*
|
||||
* @param context Graphics context
|
||||
* @param descriptors List of descriptors to build descriptor handle from.
|
||||
* @param descriptor_set_handle Opaque descriptor handle object.
|
||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success, error code on failure
|
||||
*/
|
||||
rse_err_t descriptors_build(struct graphics_context_t* context, struct descriptor_set_list_t* descriptors,
|
||||
struct descriptor_set_handle_t* descriptor_set_handle);
|
||||
|
||||
#endif // !DESCRIPTOR_BUILDER_H
|
||||
@@ -7,20 +7,20 @@
|
||||
*
|
||||
* @copyright Copyright (c) 2024
|
||||
*
|
||||
*/
|
||||
*/
|
||||
|
||||
#ifndef GRAPHICS_CONTEXT_H
|
||||
#define GRAPHICS_CONTEXT_H
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <vma/vk_mem_alloc.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#include "utilities/linked_list.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
#include "vulkan_commons.h"
|
||||
#include "utilities/linked_list.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#define MAX_MESH_NUMBER 256
|
||||
#define MAX_INSTANCE_NUMBER 256
|
||||
@@ -31,9 +31,7 @@
|
||||
*/
|
||||
#define RSE_MAX_IMAGE_COUNT 256
|
||||
|
||||
#define MAX_DESCRIPTOR_SETS 16
|
||||
#define MAX_PIPELINE_COUNT 16
|
||||
#define MAX_DESCRIPTOR_POOLS_COUNT (16)
|
||||
|
||||
RSE_LINKED_LIST_DEFINE(shader_module_list_t, VkShaderModule);
|
||||
|
||||
@@ -89,7 +87,6 @@ struct mesh_t
|
||||
struct pipeline_internal_t
|
||||
{
|
||||
size_t pipelines_count;
|
||||
size_t descriptor_set_layouts_count;
|
||||
VkPipeline pipelines[MAX_PIPELINE_COUNT];
|
||||
VkPipelineLayout pipeline_layout;
|
||||
};
|
||||
@@ -102,12 +99,9 @@ struct graphics_context_t
|
||||
VkInstance instance;
|
||||
VkQueue graphics_queue;
|
||||
VmaAllocator allocator;
|
||||
VkSampler sampler;
|
||||
VkPhysicalDevice physical_device;
|
||||
VkCommandPool command_pool;
|
||||
VkCommandBuffer command_buffers[SWAP_BUFFER_COUNT];
|
||||
VkDescriptorSet descriptor_sets[SWAP_BUFFER_COUNT];
|
||||
VkDescriptorSet descriptor_sets_bindless;
|
||||
VkImageView* swapchain_image_views;
|
||||
VkExtent2D swapchain_extent;
|
||||
VkRenderPass render_pass;
|
||||
@@ -119,13 +113,11 @@ struct graphics_context_t
|
||||
VkSemaphore image_available_semaphores[SWAP_BUFFER_COUNT];
|
||||
VkSemaphore render_finished_semaphores[SWAP_BUFFER_COUNT];
|
||||
VkFence in_flight_fences[SWAP_BUFFER_COUNT];
|
||||
VkDescriptorPool descriptor_pool;
|
||||
VkDescriptorPool descriptor_pool_bindless;
|
||||
struct pipeline_internal_t pipelines_data;
|
||||
#ifndef NDEBUG
|
||||
VkDebugUtilsMessengerEXT debug_messenger;
|
||||
#endif // !NDEBUG
|
||||
bool is_framebuffer_resized; //TODO: Consider moving this to heap
|
||||
#endif // !NDEBUG
|
||||
bool is_framebuffer_resized; // TODO: Consider moving this to heap
|
||||
uint32_t current_frame;
|
||||
uint32_t queue_family_indices[1];
|
||||
struct vulkan_buffer_t uniform_buffers[SWAP_BUFFER_COUNT];
|
||||
|
||||
+68
-129
@@ -14,6 +14,7 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "descriptor_builder.h"
|
||||
#include "src/graphics_context.h"
|
||||
#include "utilities/commons.h"
|
||||
#include "utilities/errors_common.h"
|
||||
@@ -27,15 +28,14 @@
|
||||
#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(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 {
|
||||
struct pipeline_t
|
||||
{
|
||||
VkPipeline pipeline;
|
||||
uint8_t id;
|
||||
/* Shader stages */
|
||||
@@ -66,11 +66,10 @@ struct pipeline_t {
|
||||
* @param binary_data Shader compiled code
|
||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||
*/
|
||||
static rse_err_t create_shader_module(struct graphics_context_t* context,
|
||||
struct pipeline_t* pipeline,
|
||||
static rse_err_t create_shader_module(struct graphics_context_t* context, struct pipeline_t* pipeline,
|
||||
const char* binary_data, size_t data_size)
|
||||
{
|
||||
VkShaderModuleCreateInfo create_info = {};
|
||||
VkShaderModuleCreateInfo create_info = {0};
|
||||
|
||||
create_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;
|
||||
create_info.pNext = NULL;
|
||||
@@ -81,8 +80,7 @@ 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))) {
|
||||
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;
|
||||
}
|
||||
@@ -93,8 +91,7 @@ static rse_err_t create_shader_module(struct graphics_context_t* context,
|
||||
static rse_err_t pipeline_add_input_assembly(struct pipeline_t* pipeline)
|
||||
{
|
||||
/* For now input assebly is hardcoded */
|
||||
pipeline->input_assembly.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
pipeline->input_assembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
|
||||
pipeline->input_assembly.pNext = NULL;
|
||||
pipeline->input_assembly.flags = 0U;
|
||||
pipeline->input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
|
||||
@@ -106,27 +103,20 @@ static rse_err_t pipeline_add_input_assembly(struct pipeline_t* pipeline)
|
||||
static rse_err_t pipeline_add_viewport_state(struct pipeline_t* pipeline)
|
||||
{
|
||||
/* For now viewport is hardcoded */
|
||||
pipeline->viewport_state.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
pipeline->viewport_state.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
|
||||
pipeline->viewport_state.pNext = NULL;
|
||||
pipeline->viewport_state.flags = 0U;
|
||||
pipeline->viewport_state.viewportCount = 1U;
|
||||
pipeline->viewport_state.pViewports =
|
||||
NULL; /* This is set during rendering */
|
||||
pipeline->viewport_state.pViewports = NULL; /* This is set during rendering */
|
||||
pipeline->viewport_state.scissorCount = 1U;
|
||||
pipeline->viewport_state.pScissors =
|
||||
NULL; /* This is set during rendering */
|
||||
pipeline->viewport_state.pScissors = NULL; /* This is set during rendering */
|
||||
|
||||
if (pipeline->viewport_state.pViewports == NULL ||
|
||||
pipeline->viewport_state.viewportCount == 0U) {
|
||||
RSE_STACK_PUSH(pipeline->required_dynamic_states,
|
||||
VK_DYNAMIC_STATE_VIEWPORT);
|
||||
if (pipeline->viewport_state.pViewports == NULL || pipeline->viewport_state.viewportCount == 0U) {
|
||||
RSE_STACK_PUSH(pipeline->required_dynamic_states, VK_DYNAMIC_STATE_VIEWPORT);
|
||||
}
|
||||
|
||||
if (pipeline->viewport_state.pScissors == NULL ||
|
||||
pipeline->viewport_state.scissorCount == 0U) {
|
||||
RSE_STACK_PUSH(pipeline->required_dynamic_states,
|
||||
VK_DYNAMIC_STATE_SCISSOR);
|
||||
if (pipeline->viewport_state.pScissors == NULL || pipeline->viewport_state.scissorCount == 0U) {
|
||||
RSE_STACK_PUSH(pipeline->required_dynamic_states, VK_DYNAMIC_STATE_SCISSOR);
|
||||
}
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
@@ -135,14 +125,11 @@ static rse_err_t pipeline_add_viewport_state(struct pipeline_t* pipeline)
|
||||
static rse_err_t pipeline_add_rasterizer(struct pipeline_t* pipeline)
|
||||
{
|
||||
/* For now rasterizer is hardcoded */
|
||||
pipeline->rasterizer.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
pipeline->rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
|
||||
pipeline->rasterizer.pNext = NULL;
|
||||
pipeline->rasterizer.flags = 0U;
|
||||
pipeline->rasterizer.depthClampEnable =
|
||||
VK_FALSE; /* VK_TRUE to play with shadow maps */
|
||||
pipeline->rasterizer.rasterizerDiscardEnable =
|
||||
VK_FALSE; /* Disable/Enable output to framebuffer*/
|
||||
pipeline->rasterizer.depthClampEnable = VK_FALSE; /* VK_TRUE to play with shadow maps */
|
||||
pipeline->rasterizer.rasterizerDiscardEnable = VK_FALSE; /* Disable/Enable output to framebuffer*/
|
||||
pipeline->rasterizer.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
pipeline->rasterizer.cullMode = VK_CULL_MODE_BACK_BIT;
|
||||
pipeline->rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE;
|
||||
@@ -158,8 +145,7 @@ static rse_err_t pipeline_add_rasterizer(struct pipeline_t* pipeline)
|
||||
static rse_err_t pipeline_add_multisampling(struct pipeline_t* pipeline)
|
||||
{
|
||||
/* For now multisampling is hardcoded */
|
||||
pipeline->multisampling.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
pipeline->multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
|
||||
pipeline->multisampling.pNext = NULL;
|
||||
pipeline->multisampling.flags = 0U;
|
||||
pipeline->multisampling.rasterizationSamples = VK_SAMPLE_COUNT_8_BIT;
|
||||
@@ -176,20 +162,16 @@ static rse_err_t pipeline_add_color_blending(struct pipeline_t* pipeline)
|
||||
{
|
||||
/* For now color blending is hardcoded */
|
||||
pipeline->color_blend_attachment.colorWriteMask =
|
||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
|
||||
pipeline->color_blend_attachment.blendEnable = VK_TRUE;
|
||||
pipeline->color_blend_attachment.srcColorBlendFactor =
|
||||
VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
pipeline->color_blend_attachment.dstColorBlendFactor =
|
||||
VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
pipeline->color_blend_attachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
|
||||
pipeline->color_blend_attachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
|
||||
pipeline->color_blend_attachment.colorBlendOp = VK_BLEND_OP_ADD;
|
||||
pipeline->color_blend_attachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
|
||||
pipeline->color_blend_attachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
|
||||
pipeline->color_blend_attachment.alphaBlendOp = VK_BLEND_OP_ADD;
|
||||
|
||||
pipeline->color_blending.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
pipeline->color_blending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
|
||||
pipeline->color_blending.pNext = NULL;
|
||||
pipeline->color_blending.flags = 0U;
|
||||
pipeline->color_blending.logicOpEnable = VK_FALSE;
|
||||
@@ -207,8 +189,7 @@ static rse_err_t pipeline_add_color_blending(struct pipeline_t* pipeline)
|
||||
static rse_err_t pipeline_add_depth_stencil(struct pipeline_t* pipeline)
|
||||
{
|
||||
/* For now depth stencil is hardcoded */
|
||||
pipeline->depth_stencil.sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
pipeline->depth_stencil.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
|
||||
pipeline->depth_stencil.pNext = NULL;
|
||||
pipeline->depth_stencil.flags = 0U;
|
||||
pipeline->depth_stencil.depthTestEnable = VK_TRUE;
|
||||
@@ -228,21 +209,23 @@ static rse_err_t pipeline_add_depth_stencil(struct pipeline_t* pipeline)
|
||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success. Possible errors:
|
||||
* VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED
|
||||
*/
|
||||
static rse_err_t create_pipeline_layout(struct graphics_context_t* context)
|
||||
static rse_err_t create_pipeline_layout(struct graphics_context_t* context,
|
||||
struct descriptors_set_handle_t* descriptor_set_handle)
|
||||
{
|
||||
VkPipelineLayoutCreateInfo create_info = {};
|
||||
uint32_t descriptor_set_layouts_count = 0;
|
||||
VkDescriptorSetLayout descriptor_set_layouts = VK_NULL_HANDLE;
|
||||
|
||||
VkPipelineLayoutCreateInfo create_info = {0};
|
||||
create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
|
||||
create_info.pNext = NULL;
|
||||
create_info.flags = 0U;
|
||||
create_info.setLayoutCount =
|
||||
context->pipelines_data.descriptor_set_layouts_count;
|
||||
create_info.setLayoutCount = context->pipelines_data.descriptor_set_layouts_count;
|
||||
create_info.pSetLayouts = context->pipelines_data.descriptor_set_layouts;
|
||||
create_info.pushConstantRangeCount = 0U;
|
||||
create_info.pPushConstantRanges = NULL;
|
||||
|
||||
if (VK_SUCCESS !=
|
||||
vkCreatePipelineLayout(context->device, &create_info, NULL,
|
||||
&context->pipelines_data.pipeline_layout)) {
|
||||
vkCreatePipelineLayout(context->device, &create_info, NULL, &context->pipelines_data.pipeline_layout)) {
|
||||
LOGF(_("Failed to create pipeline layout\n"));
|
||||
return VULKAN_ERROR_PIPELINE_LAYOUT_CREATION_FAILED;
|
||||
}
|
||||
@@ -265,24 +248,18 @@ static void pipeline_builder_cleanup(struct pipeline_infos_list_t* pipelines)
|
||||
VkDynamicState* dynamic_states = NULL;
|
||||
|
||||
for (size_t i = 0; i < pipeline_count; i++) {
|
||||
VkGraphicsPipelineCreateInfo* pipeline_info =
|
||||
&RSE_LINKED_LIST_FRONT(pipelines);
|
||||
VkGraphicsPipelineCreateInfo* pipeline_info = &RSE_LINKED_LIST_FRONT(pipelines);
|
||||
if (pipeline_info != NULL) {
|
||||
vertex_bindings =
|
||||
(VkVertexInputBindingDescription*)pipeline_info
|
||||
->pVertexInputState->pVertexBindingDescriptions;
|
||||
(VkVertexInputBindingDescription*)pipeline_info->pVertexInputState->pVertexBindingDescriptions;
|
||||
|
||||
shader_attributes =
|
||||
(VkVertexInputAttributeDescription*)pipeline_info
|
||||
->pVertexInputState->pVertexAttributeDescriptions;
|
||||
(VkVertexInputAttributeDescription*)pipeline_info->pVertexInputState->pVertexAttributeDescriptions;
|
||||
|
||||
dynamic_states =
|
||||
(VkDynamicState*)pipeline_info->pDynamicState->pDynamicStates;
|
||||
dynamic_states = (VkDynamicState*)pipeline_info->pDynamicState->pDynamicStates;
|
||||
|
||||
rse_free((VkPipelineVertexInputStateCreateInfo*)
|
||||
pipeline_info->pVertexInputState);
|
||||
rse_free((VkPipelineDynamicStateCreateInfo*)
|
||||
pipeline_info->pDynamicState);
|
||||
rse_free((VkPipelineVertexInputStateCreateInfo*)pipeline_info->pVertexInputState);
|
||||
rse_free((VkPipelineDynamicStateCreateInfo*)pipeline_info->pDynamicState);
|
||||
rse_free(vertex_bindings);
|
||||
rse_free(shader_attributes);
|
||||
rse_free(dynamic_states);
|
||||
@@ -295,8 +272,7 @@ static void pipeline_builder_cleanup(struct pipeline_infos_list_t* pipelines)
|
||||
}
|
||||
}
|
||||
|
||||
rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline,
|
||||
VkDynamicState dynamic_state)
|
||||
rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline, VkDynamicState dynamic_state)
|
||||
{
|
||||
if (dynamic_state >= VK_DYNAMIC_STATE_MAX_ENUM) {
|
||||
LOGF(_("Invalid dynamic state in pipeline\n"));
|
||||
@@ -327,10 +303,8 @@ rse_err_t pipeline_builder_init(struct pipeline_t** pipeline)
|
||||
return status;
|
||||
}
|
||||
|
||||
rse_err_t pipeline_add_shader_stage(struct graphics_context_t* context,
|
||||
struct pipeline_t* pipeline,
|
||||
const char* shader_path,
|
||||
const VkShaderStageFlagBits shader_stage)
|
||||
rse_err_t pipeline_add_shader_stage(struct graphics_context_t* context, struct pipeline_t* pipeline,
|
||||
const char* shader_path, const VkShaderStageFlagBits shader_stage)
|
||||
{
|
||||
size_t i = 0;
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
@@ -359,26 +333,22 @@ rse_err_t pipeline_add_shader_stage(struct graphics_context_t* context,
|
||||
STATUS_CHECK(create_shader_module(context, pipeline, buffer, buffer_size));
|
||||
free(buffer);
|
||||
|
||||
pipeline->shader_stages[i].sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
pipeline->shader_stages[i].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
|
||||
pipeline->shader_stages[i].pNext = NULL;
|
||||
pipeline->shader_stages[i].flags = 0U;
|
||||
pipeline->shader_stages[i].stage = shader_stage;
|
||||
pipeline->shader_stages[i].module = RSE_LINKED_LIST_FRONT(
|
||||
context->shader_modules); /* This is automatically updated during
|
||||
shader module creation */
|
||||
pipeline->shader_stages[i].module = RSE_LINKED_LIST_FRONT(context->shader_modules); /* This is automatically updated
|
||||
during shader module creation */
|
||||
pipeline->shader_stages[i].pName = "main";
|
||||
pipeline->shader_stages[i].pSpecializationInfo = NULL;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
rse_err_t pipeline_add_vertex_input_binding(struct pipeline_t* pipeline,
|
||||
const uint8_t binding,
|
||||
const uint8_t stride,
|
||||
rse_err_t pipeline_add_vertex_input_binding(struct pipeline_t* pipeline, const uint8_t binding, const uint8_t stride,
|
||||
const VkVertexInputRate input_rate)
|
||||
{
|
||||
VkVertexInputBindingDescription binding_pipeline_description = {};
|
||||
VkVertexInputBindingDescription binding_pipeline_description = {0};
|
||||
if (input_rate >= VK_VERTEX_INPUT_RATE_MAX_ENUM) {
|
||||
LOGF(_("Invalid vertex input rate\n"));
|
||||
return VULKAN_ERROR_PIPELINE_INVALID_VERTEX_INPUT_RATE;
|
||||
@@ -388,18 +358,14 @@ rse_err_t pipeline_add_vertex_input_binding(struct pipeline_t* pipeline,
|
||||
binding_pipeline_description.stride = stride;
|
||||
binding_pipeline_description.inputRate = input_rate;
|
||||
|
||||
RSE_LINKED_LIST_PUSH_FRONT(pipeline->vertex_bindings,
|
||||
binding_pipeline_description);
|
||||
RSE_LINKED_LIST_PUSH_FRONT(pipeline->vertex_bindings, binding_pipeline_description);
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline,
|
||||
const uint8_t binding,
|
||||
const uint8_t location,
|
||||
const VkFormat format,
|
||||
const uint8_t offset)
|
||||
rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline, const uint8_t binding,
|
||||
const uint8_t location, const VkFormat format, const uint8_t offset)
|
||||
{
|
||||
VkVertexInputAttributeDescription attribute_description = {};
|
||||
VkVertexInputAttributeDescription attribute_description = {0};
|
||||
if (binding >= 16U) {
|
||||
LOGF(_("Invalid binding in pipeline attribute description\n"));
|
||||
return VULKAN_ERROR_PIPELINE_INVALID_BINDING;
|
||||
@@ -414,14 +380,12 @@ rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline,
|
||||
attribute_description.format = format;
|
||||
attribute_description.offset = offset;
|
||||
|
||||
RSE_LINKED_LIST_PUSH_FRONT(pipeline->shader_attributes,
|
||||
attribute_description);
|
||||
RSE_LINKED_LIST_PUSH_FRONT(pipeline->shader_attributes, attribute_description);
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||
struct pipeline_infos_list_t* pipelines_infos_list)
|
||||
rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_list_t* pipelines_infos_list)
|
||||
{
|
||||
assert(NULL != context);
|
||||
assert(NULL != pipelines_infos_list);
|
||||
@@ -435,8 +399,7 @@ rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||
|
||||
STATUS_CHECK(create_pipeline_layout(context));
|
||||
|
||||
rse_malloc(pipeline_infos,
|
||||
sizeof(VkGraphicsPipelineCreateInfo) * pipelines_count);
|
||||
rse_malloc(pipeline_infos, sizeof(VkGraphicsPipelineCreateInfo) * pipelines_count);
|
||||
|
||||
RSE_LINKED_LIST_TO_ARRAY(pipelines_infos_list, pipeline_infos);
|
||||
|
||||
@@ -446,10 +409,8 @@ rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||
pipeline_infos[i].layout = context->pipelines_data.pipeline_layout;
|
||||
}
|
||||
|
||||
if (VK_SUCCESS !=
|
||||
vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE,
|
||||
pipelines_count, pipeline_infos, NULL,
|
||||
context->pipelines_data.pipelines)) {
|
||||
if (VK_SUCCESS != vkCreateGraphicsPipelines(context->device, VK_NULL_HANDLE, pipelines_count, pipeline_infos, NULL,
|
||||
context->pipelines_data.pipelines)) {
|
||||
LOGF(_("Failed to create graphics pipelines\n"));
|
||||
status = VULKAN_ERROR_GRAPHICSPIPELINE_CREATION_FAILED;
|
||||
}
|
||||
@@ -460,13 +421,12 @@ rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||
return status;
|
||||
}
|
||||
|
||||
rse_err_t add_pipeline(const struct graphics_context_t* context,
|
||||
struct pipeline_t* pipeline,
|
||||
rse_err_t add_pipeline(const struct graphics_context_t* context, struct pipeline_t* pipeline,
|
||||
struct pipeline_infos_list_t** pipelines_infos)
|
||||
{
|
||||
/* Check for send and required dynamic states */
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
VkGraphicsPipelineCreateInfo pipeline_info = {};
|
||||
VkGraphicsPipelineCreateInfo pipeline_info = {0};
|
||||
|
||||
size_t vertex_bindings_count = 0U;
|
||||
VkVertexInputBindingDescription* vertex_bindings = NULL;
|
||||
@@ -483,8 +443,7 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
||||
|
||||
while (RSE_STACK_IS_EMPTY(pipeline->required_dynamic_states) == 0) {
|
||||
dynamic_state_found = 0;
|
||||
VkDynamicState dynamic_state =
|
||||
RSE_STACK_POP(pipeline->required_dynamic_states);
|
||||
VkDynamicState dynamic_state = RSE_STACK_POP(pipeline->required_dynamic_states);
|
||||
RSE_LINKED_LIST_FOREACH(pipeline->dynamic_states, dynamic_state_ptr)
|
||||
{
|
||||
if (dynamic_state_ptr->data == dynamic_state) {
|
||||
@@ -525,12 +484,9 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
||||
}
|
||||
|
||||
/* Convert linked list to array */
|
||||
vertex_bindings_count =
|
||||
RSE_LINKED_LIST_TO_ARRAY(pipeline->vertex_bindings, vertex_bindings);
|
||||
shader_attributes_count = RSE_LINKED_LIST_TO_ARRAY(
|
||||
pipeline->shader_attributes, shader_attributes);
|
||||
dynamic_states_count =
|
||||
RSE_LINKED_LIST_TO_ARRAY(pipeline->dynamic_states, dynamic_states);
|
||||
vertex_bindings_count = RSE_LINKED_LIST_TO_ARRAY(pipeline->vertex_bindings, vertex_bindings);
|
||||
shader_attributes_count = RSE_LINKED_LIST_TO_ARRAY(pipeline->shader_attributes, shader_attributes);
|
||||
dynamic_states_count = RSE_LINKED_LIST_TO_ARRAY(pipeline->dynamic_states, dynamic_states);
|
||||
|
||||
/* Build constant pipeline. TODO: Some parts may be customizable */
|
||||
pipeline_add_input_assembly(pipeline);
|
||||
@@ -546,16 +502,13 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
||||
pipeline_info.stageCount = pipeline->shader_stages_count;
|
||||
pipeline_info.pStages = pipeline->shader_stages;
|
||||
|
||||
rse_malloc(vertex_bindings_ci,
|
||||
sizeof(VkPipelineVertexInputStateCreateInfo));
|
||||
vertex_bindings_ci->sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
|
||||
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->vertexAttributeDescriptionCount = shader_attributes_count;
|
||||
vertex_bindings_ci->pVertexAttributeDescriptions = shader_attributes;
|
||||
pipeline_info.pVertexInputState = vertex_bindings_ci;
|
||||
|
||||
@@ -568,8 +521,7 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
||||
pipeline_info.pColorBlendState = &pipeline->color_blending;
|
||||
|
||||
rse_malloc(dynamic_states_ci, sizeof(VkPipelineDynamicStateCreateInfo));
|
||||
dynamic_states_ci->sType =
|
||||
VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
|
||||
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;
|
||||
@@ -579,8 +531,7 @@ rse_err_t add_pipeline(const struct graphics_context_t* context,
|
||||
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.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);
|
||||
|
||||
@@ -594,25 +545,13 @@ void destroy_pipelines(struct graphics_context_t* context)
|
||||
|
||||
for (i = 0; i < context->pipelines_data.pipelines_count; i++) {
|
||||
if (context->pipelines_data.pipelines[i] != VK_NULL_HANDLE) {
|
||||
vkDestroyPipeline(context->device,
|
||||
context->pipelines_data.pipelines[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < context->pipelines_data.descriptor_set_layouts_count; i++) {
|
||||
if (context->pipelines_data.descriptor_set_layouts[i] !=
|
||||
VK_NULL_HANDLE) {
|
||||
vkDestroyDescriptorSetLayout(
|
||||
context->device,
|
||||
context->pipelines_data.descriptor_set_layouts[i], NULL);
|
||||
vkDestroyPipeline(context->device, context->pipelines_data.pipelines[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
vkDestroyShaderModule(context->device, RSE_LINKED_LIST_FRONT(context->shader_modules), NULL);
|
||||
}
|
||||
RSE_LINKED_LIST_POP_FRONT(context->shader_modules);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "graphics_context.h"
|
||||
#include "utilities/commons.h"
|
||||
#include "utilities/linked_list.h"
|
||||
@@ -41,7 +42,8 @@ rse_err_t pipeline_builder_init(struct pipeline_t** pipeline);
|
||||
* @param[in] shader_stage Shader stage to add
|
||||
* @return RSE_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
rse_err_t pipeline_add_shader_stage(struct graphics_context_t* context, struct pipeline_t* pipeline, const char* shader_path, const VkShaderStageFlagBits shader_stage);
|
||||
rse_err_t pipeline_add_shader_stage(struct graphics_context_t* context, struct pipeline_t* pipeline,
|
||||
const char* shader_path, const VkShaderStageFlagBits shader_stage);
|
||||
|
||||
/**
|
||||
* @brief Add vertex input binding to pipeline
|
||||
@@ -53,7 +55,7 @@ rse_err_t pipeline_add_shader_stage(struct graphics_context_t* context, struct p
|
||||
* @return RSE_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
rse_err_t pipeline_add_vertex_input_binding(struct pipeline_t* pipeline, const uint8_t binding, const uint8_t stride,
|
||||
const VkVertexInputRate input_rate);
|
||||
const VkVertexInputRate input_rate);
|
||||
|
||||
/**
|
||||
* @brief Add vertex attribute to shader in pipeline
|
||||
@@ -66,9 +68,7 @@ rse_err_t pipeline_add_vertex_input_binding(struct pipeline_t* pipeline, const u
|
||||
* @return RSE_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline, const uint8_t binding,
|
||||
const uint8_t location,
|
||||
const VkFormat format,
|
||||
const uint8_t offset);
|
||||
const uint8_t location, const VkFormat format, const uint8_t offset);
|
||||
|
||||
/**
|
||||
* @brief Add dynamic state to pipeline
|
||||
@@ -80,40 +80,14 @@ rse_err_t pipeline_add_vertex_input_attribute(struct pipeline_t* pipeline, const
|
||||
rse_err_t pipeline_add_dynamic_state(struct pipeline_t* pipeline, const VkDynamicState dynamic_state);
|
||||
|
||||
/**
|
||||
* @brief Add descriptor pool
|
||||
*
|
||||
* @param[in] context Graphics context handle
|
||||
* @param[in] pipeline Pipeline to add descriptor pool to
|
||||
* @param[in] descriptor_type Type of descriptors to be stored in this pool.
|
||||
* @return RSE_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
rse_err_t pipeline_add_descriptor_pool(struct graphics_context_t* context,
|
||||
struct pipeline_t* pipeline,
|
||||
enum VkDescriptorType descriptor_type);
|
||||
|
||||
/**
|
||||
* @brief Add required dynamic state to pipeline
|
||||
*
|
||||
* @param[in] context Graphics context handle
|
||||
* @param[in] binding_infos Binding infos to add
|
||||
* @param[in] binding_count Number of binding infos
|
||||
* @param[out] descriptor_set_index Index of descriptor set
|
||||
* @return RSE_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief Build pipeline from added components. This function should be called after adding all necessary components. After call, pipeline is ready to be used and all added components are cleared, ready for next pipeline to be built.
|
||||
* @brief Build pipeline from added components. This function should be called after adding all necessary components.
|
||||
* After call, pipeline is ready to be used and all added components are cleared, ready for next pipeline to be built.
|
||||
*
|
||||
* param[in/out] context Graphics context handle
|
||||
* @param[in] pipeline Pipelines list to build
|
||||
* @return RSE_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||
struct pipeline_infos_list_t* pipelines);
|
||||
rse_err_t pipelines_build(struct graphics_context_t* context, struct pipeline_infos_list_t* pipelines);
|
||||
|
||||
/**
|
||||
* @brief Add pipeline to list of pipelines
|
||||
@@ -123,7 +97,8 @@ rse_err_t pipelines_build(struct graphics_context_t* context,
|
||||
* @param[out] pipeline_info List of pipelines infos, where new info should be added
|
||||
* @return RSE_SUCCESS on success, error code otherwise
|
||||
*/
|
||||
rse_err_t add_pipeline(const struct graphics_context_t* context, struct pipeline_t* pipeline, struct pipeline_infos_list_t** pipelines);
|
||||
rse_err_t add_pipeline(const struct graphics_context_t* context, struct pipeline_t* pipeline,
|
||||
struct pipeline_infos_list_t** pipelines);
|
||||
|
||||
/**
|
||||
* @brief Destroy all pipelines
|
||||
|
||||
+43
-50
@@ -1,19 +1,20 @@
|
||||
#include "rse_graphics.h"
|
||||
#include "utilities/localization.h"
|
||||
#include "window.h"
|
||||
#include "vulkan_base.h"
|
||||
|
||||
#include "descriptor_builder.h"
|
||||
#include "graphics_context.h"
|
||||
#include "math.h"
|
||||
#include "mesh_controller.h"
|
||||
#include "vulkan_commons.h"
|
||||
#include "pipeline_builder.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "utilities/commons.h"
|
||||
#include "utilities/errors_common.h"
|
||||
#include "graphics_context.h"
|
||||
#include "utilities/localization.h"
|
||||
#include "utilities/logger.h"
|
||||
#include "vulkan_base.h"
|
||||
#include "vulkan_commons.h"
|
||||
#include "window.h"
|
||||
|
||||
#include "math.h"
|
||||
|
||||
struct rse_graphics_context_t {
|
||||
struct rse_graphics_context_t
|
||||
{
|
||||
struct graphics_context_t* context;
|
||||
};
|
||||
|
||||
@@ -46,7 +47,8 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
||||
size_t ubo_index = 0;
|
||||
size_t sampler_index = 0;
|
||||
struct pipeline_t* pipeline = NULL;
|
||||
struct binding_info_t binding_infos[2] = {0};
|
||||
struct descriptor_set_list_t* descriptor_set_list;
|
||||
struct descriptor_set_handle_t* descriptor_set_handle;
|
||||
struct pipeline_infos_list_t* pipeline_infos = NULL;
|
||||
|
||||
// status = load_texture_from_file("../../test_image.jpg", &tex_id_2);
|
||||
@@ -58,40 +60,31 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
||||
|
||||
// FIXME: Temporary array of vertices, for testing purposes
|
||||
struct vertex_t vertices[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}},
|
||||
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
|
||||
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}};
|
||||
{{0.5f, -0.5f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 0.0f}},
|
||||
{{0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}};
|
||||
|
||||
struct vertex_t vertices2[] = {{{-0.5f, -0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 0.0f}},
|
||||
{{0.5f, -0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}},
|
||||
{{0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}};
|
||||
{{0.5f, -0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}},
|
||||
{{0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}},
|
||||
{{-0.5f, 0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {0.0f, 1.0f}}};
|
||||
|
||||
// FIXME: Temporary array of vertices, for testing purposes
|
||||
uint16_t indices[] = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
uint16_t mesh_id = create_mesh(context, vertices, indices, 6, 6);
|
||||
create_mesh_instance(context, mesh_id, (struct instance_data_t){
|
||||
{0.0f, 0.0f, 2.4f},
|
||||
{0.0f, 0.0f, math_deg_to_radians(45.0f)},
|
||||
1.0f,
|
||||
tex_id_2
|
||||
});
|
||||
create_mesh_instance(
|
||||
context, mesh_id,
|
||||
(struct instance_data_t){{0.0f, 0.0f, 2.4f}, {0.0f, 0.0f, math_deg_to_radians(45.0f)}, 1.0f, tex_id_2});
|
||||
|
||||
create_mesh_instance(context, mesh_id, (struct instance_data_t){
|
||||
{-0.5f, 0.0f, -1.0f},
|
||||
{0.0f, 0.0f, math_deg_to_radians(10.0f)},
|
||||
1.0f,
|
||||
tex_id_2
|
||||
});
|
||||
create_mesh_instance(
|
||||
context, mesh_id,
|
||||
(struct instance_data_t){{-0.5f, 0.0f, -1.0f}, {0.0f, 0.0f, math_deg_to_radians(10.0f)}, 1.0f, tex_id_2});
|
||||
|
||||
mesh_id = create_mesh(context, vertices2, indices, 6, 6);
|
||||
create_mesh_instance(context, mesh_id, (struct instance_data_t){
|
||||
{2.0f, 1.0f, 0.0f},
|
||||
{0.0f, 0.0f, math_deg_to_radians(0.0f)},
|
||||
1.0f,
|
||||
tex_id_2
|
||||
});
|
||||
create_mesh_instance(
|
||||
context, mesh_id,
|
||||
(struct instance_data_t){{2.0f, 1.0f, 0.0f}, {0.0f, 0.0f, math_deg_to_radians(0.0f)}, 1.0f, tex_id_2});
|
||||
|
||||
// fonts_load_from_file("/usr/share/fonts/JetBrainsMonoNerdFont/JetBrainsMonoNerdFont-Medium.ttf");
|
||||
// print_text("Hello World!", (struct vec3_t){-1.0f, 0.0f, 0.9f}, 0.3f);
|
||||
@@ -100,7 +93,8 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
||||
pipeline_builder_init(&pipeline);
|
||||
|
||||
pipeline_add_shader_stage(context, pipeline, "../graphics/shaders/shader.vert.num", VK_SHADER_STAGE_VERTEX_BIT);
|
||||
pipeline_add_shader_stage(context, pipeline, "../graphics/shaders/solid_objects.frag.num", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
pipeline_add_shader_stage(context, pipeline, "../graphics/shaders/solid_objects.frag.num",
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
|
||||
pipeline_add_vertex_input_binding(pipeline, 0, sizeof(struct vertex_t), VK_VERTEX_INPUT_RATE_VERTEX);
|
||||
pipeline_add_vertex_input_binding(pipeline, 1, sizeof(struct vertex_t), VK_VERTEX_INPUT_RATE_INSTANCE);
|
||||
@@ -108,34 +102,33 @@ void rse_graphics_test_function(struct rse_graphics_context_t* rse_context)
|
||||
pipeline_add_vertex_input_attribute(pipeline, 0, 0, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, pos));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 0, 1, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct vertex_t, color));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 0, 2, VK_FORMAT_R32G32_SFLOAT, offsetof(struct vertex_t, tex_coords));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 1, 3, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct instance_data_t, pos));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 1, 4, VK_FORMAT_R32G32B32_SFLOAT, offsetof(struct instance_data_t, rot));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 1, 3, VK_FORMAT_R32G32B32_SFLOAT,
|
||||
offsetof(struct instance_data_t, pos));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 1, 4, VK_FORMAT_R32G32B32_SFLOAT,
|
||||
offsetof(struct instance_data_t, rot));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 1, 5, VK_FORMAT_R32_SFLOAT, offsetof(struct instance_data_t, scale));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 1, 6, VK_FORMAT_R32_UINT, offsetof(struct instance_data_t, texture_id));
|
||||
pipeline_add_vertex_input_attribute(pipeline, 1, 6, VK_FORMAT_R32_UINT,
|
||||
offsetof(struct instance_data_t, texture_id));
|
||||
|
||||
pipeline_add_dynamic_state(pipeline, VK_DYNAMIC_STATE_VIEWPORT);
|
||||
pipeline_add_dynamic_state(pipeline, VK_DYNAMIC_STATE_SCISSOR);
|
||||
|
||||
binding_infos[0].binding = 0;
|
||||
binding_infos[0].descriptor_type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
|
||||
binding_infos[0].stage_flags = VK_SHADER_STAGE_VERTEX_BIT;
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
|
||||
binding_infos[1].binding = 1;
|
||||
binding_infos[1].descriptor_type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
|
||||
binding_infos[1].stage_flags = VK_SHADER_STAGE_FRAGMENT_BIT;
|
||||
create_sampler(context, sampler);
|
||||
|
||||
pipeline_add_descriptor_pool(context, pipeline, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
|
||||
pipeline_add_descriptor_pool(context, pipeline, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
|
||||
descriptor_add_set(descriptor_set_list, 0, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT, NULL);
|
||||
descriptor_add_set(descriptor_set_list, 1, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1,
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT, sampler);
|
||||
|
||||
pipeline_add_descriptor_layout(context, &binding_infos[0], 1, &ubo_index);
|
||||
pipeline_add_descriptor_layout(context, &binding_infos[1], 1, &sampler_index);
|
||||
descriptors_build(context, descriptor_set_list, descriptor_set_handle);
|
||||
|
||||
add_pipeline(context, pipeline, &pipeline_infos);
|
||||
|
||||
build_pipelines(context, pipeline_infos);
|
||||
|
||||
//TODO: Add a shader for text rendering
|
||||
// pipeline_add_shader_stage("../graphics/shaders/on_screen_text.frag.num", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
// TODO: Add a shader for text rendering
|
||||
// pipeline_add_shader_stage("../graphics/shaders/on_screen_text.frag.num", VK_SHADER_STAGE_FRAGMENT_BIT);
|
||||
}
|
||||
|
||||
rse_err_t rse_graphics_run(struct rse_graphics_context_t* rse_context)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
/* VMA allows C linkage, but it must be compiled as a CPP file. This file takes cares of it */
|
||||
#define VMA_IMPLEMENTATION
|
||||
#ifdef __unix__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
@@ -20,6 +21,9 @@
|
||||
#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#pragma GCC diagnostic ignored "-Wparentheses"
|
||||
#endif
|
||||
#include <cstdio>
|
||||
#include "vk_mem_alloc.h"
|
||||
#include "vma/vk_mem_alloc.h"
|
||||
#ifdef __unix__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
+19
-27
@@ -12,20 +12,8 @@
|
||||
#include "vulkan_base.h"
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
/* We are building with -Werror flag on, but there are some warning in VMA implementation. Thus diagnostic push */
|
||||
// #pragma GCC diagnostic push
|
||||
// #pragma GCC diagnostic ignored "-Wunused-function"
|
||||
// #pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
// #pragma GCC diagnostic ignored "-Wpedantic"
|
||||
// #pragma GCC diagnostic ignored "-Wignored-qualifiers"
|
||||
// #pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
// #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
|
||||
// #pragma GCC diagnostic ignored "-Wswitch"
|
||||
// #pragma GCC diagnostic ignored "-Wparentheses"
|
||||
#include "utilities/localization.h"
|
||||
#include "vk_mem_alloc.h"
|
||||
// #pragma GCC diagnostic pop
|
||||
#include <vma/vk_mem_alloc.h>
|
||||
|
||||
#include "utilities/commons.h"
|
||||
#include "utilities/errors_common.h"
|
||||
@@ -363,19 +351,21 @@ static rse_err_t pick_physical_device(VkInstance instance, VkPhysicalDevice* phy
|
||||
*/
|
||||
static rse_err_t create_device(struct graphics_context_t* context)
|
||||
{
|
||||
size_t device_queues_count = 0;
|
||||
uint32_t queue_families_property_count = 0U;
|
||||
ssize_t graphics_family_idx = -1;
|
||||
ssize_t presentation_familiy_idx = -1;
|
||||
VkQueueFamilyProperties* queue_family_properties = NULL;
|
||||
VkDeviceCreateInfo device_create_info = {0};
|
||||
VkDeviceQueueCreateInfo device_queue_createinfos[2] = {0};
|
||||
bool graphics_family_found = false;
|
||||
bool presentation_familiy_found = false;
|
||||
float* graphics_familiy_queue_priorities = NULL;
|
||||
float* presentation_familiy_queue_priorities = NULL;
|
||||
uint32_t device_queues_count = 0;
|
||||
uint32_t graphics_family_idx = 0;
|
||||
uint32_t presentation_familiy_idx = 0;
|
||||
uint32_t queue_families_property_count = 0U;
|
||||
uint32_t enabled_device_extensions_count = 2;
|
||||
VkBool32 bindless_supported = VK_FALSE;
|
||||
VkDeviceCreateInfo device_create_info = {0};
|
||||
VkQueueFamilyProperties* queue_family_properties = NULL;
|
||||
VkDeviceQueueCreateInfo device_queue_createinfos[2] = {0};
|
||||
VkPhysicalDeviceFeatures2 physical_features2 = {0};
|
||||
VkPhysicalDeviceDescriptorIndexingFeatures indexing_features = {0};
|
||||
VkBool32 bindless_supported = VK_FALSE;
|
||||
uint32_t enabled_device_extensions_count = 2;
|
||||
const char* enabled_device_extensions_names[] = {
|
||||
"VK_KHR_swapchain",
|
||||
"VK_EXT_descriptor_indexing",
|
||||
@@ -405,12 +395,13 @@ static rse_err_t create_device(struct graphics_context_t* context)
|
||||
* queues. */
|
||||
{
|
||||
size_t numberOfQueues = 0;
|
||||
for (size_t familyIdx = 0; familyIdx < queue_families_property_count; ++familyIdx) {
|
||||
for (uint32_t familyIdx = 0; familyIdx < queue_families_property_count; ++familyIdx) {
|
||||
LOGI("Checking queue: %ld", familyIdx);
|
||||
if (queue_family_properties[familyIdx].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
||||
if (queue_family_properties[familyIdx].queueCount > numberOfQueues) {
|
||||
graphics_family_idx = familyIdx;
|
||||
LOGI("Setting graphics family idx to %d", familyIdx);
|
||||
graphics_family_found = true;
|
||||
LOGI("Setting graphics family idx to %ld", familyIdx);
|
||||
numberOfQueues = queue_family_properties[familyIdx].queueCount;
|
||||
device_queues_count++;
|
||||
}
|
||||
@@ -421,13 +412,14 @@ static rse_err_t create_device(struct graphics_context_t* context)
|
||||
vkGetPhysicalDeviceSurfaceSupportKHR(context->physical_device, familyIdx, context->surface, &presentSupport);
|
||||
if (presentSupport) {
|
||||
presentation_familiy_idx = familyIdx;
|
||||
presentation_familiy_found = true;
|
||||
/* If this is the same queue family as in graphics family, don't increase queue count */
|
||||
if (presentation_familiy_idx != graphics_family_idx) {
|
||||
device_queues_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (graphics_family_idx > 0 && presentation_familiy_idx > 0) {
|
||||
if (graphics_family_found && presentation_familiy_found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -529,10 +521,10 @@ static rse_err_t create_memory_allocator(struct graphics_context_t* context)
|
||||
*/
|
||||
static rse_err_t create_sync_objects(struct graphics_context_t* context)
|
||||
{
|
||||
VkSemaphoreCreateInfo semaphore_info = {};
|
||||
VkSemaphoreCreateInfo semaphore_info = {0};
|
||||
semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||
|
||||
VkFenceCreateInfo fenceInfo = {};
|
||||
VkFenceCreateInfo fenceInfo = {0};
|
||||
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||
fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
static void copy_buffer(struct graphics_context_t* context, VkBuffer src, VkBuffer dst, VkDeviceSize size, VkDeviceSize dest_offset)
|
||||
{
|
||||
/* Vulkan buffers can only be copied using command buffers */
|
||||
VkBufferCopy copy_region = {};
|
||||
VkBufferCopy copy_region = {0};
|
||||
VkCommandBuffer command_buffer = {0};
|
||||
|
||||
command_buffer = begin_single_time_command(context);
|
||||
@@ -152,8 +152,8 @@ rse_err_t create_buffer(struct graphics_context_t* context, const VkDeviceSize s
|
||||
const VmaAllocationCreateFlags allocation_flags,
|
||||
struct vulkan_buffer_t* buffer)
|
||||
{
|
||||
VkBufferCreateInfo vertex_buffer_info = {};
|
||||
VmaAllocationCreateInfo create_info = {};
|
||||
VkBufferCreateInfo vertex_buffer_info = {0};
|
||||
VmaAllocationCreateInfo create_info = {0};
|
||||
|
||||
vertex_buffer_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
vertex_buffer_info.pNext = NULL;
|
||||
@@ -194,7 +194,7 @@ void destroy_buffer(struct graphics_context_t* context, struct vulkan_buffer_t*
|
||||
|
||||
void update_uniform_buffers(struct graphics_context_t* context)
|
||||
{
|
||||
struct uniform_buffer_object_t ubo = {};
|
||||
struct uniform_buffer_object_t ubo = {0};
|
||||
struct vec3_t eye = {0};
|
||||
struct vec3_t center = {0};
|
||||
struct vec3_t up = {0};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "utilities/commons.h"
|
||||
#include "graphics_context.h"
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
#include <vma/vk_mem_alloc.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
#ifndef VULKAN_COMMANDS_H
|
||||
#define VULKAN_COMMANDS_H
|
||||
|
||||
#include "vk_mem_alloc.h"
|
||||
#include <vma/vk_mem_alloc.h>
|
||||
|
||||
#include "utilities/commons.h"
|
||||
#include "graphics_context.h"
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#include "math.h"
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vk_mem_alloc.h>
|
||||
#include <vma/vk_mem_alloc.h>
|
||||
|
||||
#include <stdalign.h>
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ enum vulkan_error_t
|
||||
VULKAN_ERROR_DRAW_FAILED,
|
||||
VULKAN_ERROR_PIPELINE_ALREADY_INITIALIZED,
|
||||
VULKAN_ERROR_UNKNOWN_DESCRIPTOR_TYPE,
|
||||
VULKAN_ERROR_DESCRIPTOR_SET_LAYOUT_CREATION_FAILED,
|
||||
VULKAN_ERROR_DESCRIPTOR_SET_CREATION_FAILED,
|
||||
VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED,
|
||||
};
|
||||
|
||||
#endif
|
||||
+60
-119
@@ -28,7 +28,7 @@
|
||||
* @param[in/out] context Graphics context to create sampler in
|
||||
* @return RSE_ERROR_NO_ERROR on success, error code otherwise
|
||||
*/
|
||||
static rse_err_t create_sampler(struct graphics_context_t* context)
|
||||
rse_err_t create_sampler(struct graphics_context_t* context, VkSampler sampler)
|
||||
{
|
||||
VkSamplerCreateInfo create_info = {0};
|
||||
|
||||
@@ -51,8 +51,7 @@ static rse_err_t create_sampler(struct graphics_context_t* context)
|
||||
create_info.borderColor = VK_BORDER_COLOR_INT_OPAQUE_BLACK;
|
||||
create_info.unnormalizedCoordinates = VK_FALSE;
|
||||
|
||||
if (VK_SUCCESS != vkCreateSampler(context->device, &create_info, NULL,
|
||||
&context->sampler)) {
|
||||
if (VK_SUCCESS != vkCreateSampler(context->device, &create_info, NULL, &sampler)) {
|
||||
LOGF("Failed to create image view");
|
||||
return 1;
|
||||
}
|
||||
@@ -60,26 +59,20 @@ static rse_err_t create_sampler(struct graphics_context_t* context)
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
static rse_err_t find_supported_format(struct graphics_context_t* context,
|
||||
const VkFormat* candidates,
|
||||
size_t candidates_count,
|
||||
VkImageTiling tiling,
|
||||
VkFormatFeatureFlags features,
|
||||
static rse_err_t find_supported_format(struct graphics_context_t* context, const VkFormat* candidates,
|
||||
size_t candidates_count, VkImageTiling tiling, VkFormatFeatureFlags features,
|
||||
VkFormat* found_format)
|
||||
{
|
||||
size_t i = 0U;
|
||||
|
||||
for (i = 0U; i < candidates_count; ++i) {
|
||||
VkFormatProperties props;
|
||||
vkGetPhysicalDeviceFormatProperties(context->physical_device,
|
||||
candidates[i], &props);
|
||||
vkGetPhysicalDeviceFormatProperties(context->physical_device, candidates[i], &props);
|
||||
|
||||
if (tiling == VK_IMAGE_TILING_LINEAR &&
|
||||
(props.linearTilingFeatures & features) == features) {
|
||||
if (tiling == VK_IMAGE_TILING_LINEAR && (props.linearTilingFeatures & features) == features) {
|
||||
*found_format = candidates[i];
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
} else if (tiling == VK_IMAGE_TILING_OPTIMAL &&
|
||||
(props.optimalTilingFeatures & features) == features) {
|
||||
} else if (tiling == VK_IMAGE_TILING_OPTIMAL && (props.optimalTilingFeatures & features) == features) {
|
||||
*found_format = candidates[i];
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
@@ -89,12 +82,9 @@ static rse_err_t find_supported_format(struct graphics_context_t* context,
|
||||
return VULKAN_ERROR_FORMAT_NOT_FOUND;
|
||||
}
|
||||
|
||||
static rse_err_t create_image(struct graphics_context_t* context,
|
||||
struct vulkan_image_t* image, uint32_t width,
|
||||
uint32_t height, VkFormat format,
|
||||
VkSampleCountFlagBits maa_samples,
|
||||
VkImageUsageFlags usage,
|
||||
VmaAllocationCreateFlags allocationFlags)
|
||||
static rse_err_t create_image(struct graphics_context_t* context, struct vulkan_image_t* image, uint32_t width,
|
||||
uint32_t height, VkFormat format, VkSampleCountFlagBits maa_samples,
|
||||
VkImageUsageFlags usage, VmaAllocationCreateFlags allocationFlags)
|
||||
{
|
||||
VkExtent3D image_extent = {0};
|
||||
VkImageCreateInfo image_info = {0};
|
||||
@@ -115,9 +105,8 @@ static rse_err_t create_image(struct graphics_context_t* context,
|
||||
image_info.samples = maa_samples;
|
||||
image_info.tiling = VK_IMAGE_TILING_OPTIMAL;
|
||||
image_info.usage = usage;
|
||||
image_info.sharingMode =
|
||||
VK_SHARING_MODE_EXCLUSIVE; // TODO: Change if used by more than one
|
||||
// queue family
|
||||
image_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE; // TODO: Change if used by more than one
|
||||
// queue family
|
||||
image_info.queueFamilyIndexCount = 0U;
|
||||
image_info.pQueueFamilyIndices = NULL;
|
||||
image_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
@@ -131,10 +120,8 @@ static rse_err_t create_image(struct graphics_context_t* context,
|
||||
alloc_create_info.pUserData = NULL;
|
||||
alloc_create_info.priority = 1.0f;
|
||||
|
||||
if (VK_SUCCESS != vmaCreateImage(context->allocator, &image_info,
|
||||
&alloc_create_info, &image->image,
|
||||
&image->allocation,
|
||||
&image->allocation_info)) {
|
||||
if (VK_SUCCESS != vmaCreateImage(context->allocator, &image_info, &alloc_create_info, &image->image,
|
||||
&image->allocation, &image->allocation_info)) {
|
||||
LOGF(_("Failed to create image\n"));
|
||||
return VULKAN_ERROR_IMAGE_NOT_CREATED;
|
||||
}
|
||||
@@ -142,9 +129,7 @@ static rse_err_t create_image(struct graphics_context_t* context,
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
static rse_err_t create_image_view(struct graphics_context_t* context,
|
||||
struct vulkan_image_t* image,
|
||||
VkFormat format,
|
||||
static rse_err_t create_image_view(struct graphics_context_t* context, struct vulkan_image_t* image, VkFormat format,
|
||||
VkImageAspectFlags aspectFlags)
|
||||
{
|
||||
VkImageViewCreateInfo image_view_create_info = {0};
|
||||
@@ -165,9 +150,7 @@ static rse_err_t create_image_view(struct graphics_context_t* context,
|
||||
image_view_create_info.subresourceRange.baseArrayLayer = 0U;
|
||||
image_view_create_info.subresourceRange.layerCount = 1U;
|
||||
|
||||
if (VK_SUCCESS != vkCreateImageView(context->device,
|
||||
&image_view_create_info, NULL,
|
||||
&image->image_view)) {
|
||||
if (VK_SUCCESS != vkCreateImageView(context->device, &image_view_create_info, NULL, &image->image_view)) {
|
||||
LOGF(_("Failed to create swapchain image view\n"));
|
||||
return VULKAN_ERROR_SWAPCHAIN_IMVIEW_CREATION_FAILED;
|
||||
}
|
||||
@@ -180,20 +163,14 @@ rse_err_t create_color_resource(struct graphics_context_t* context)
|
||||
VkFormat color_format = IMAGE_FORMAT;
|
||||
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
||||
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||
context->physical_device, context->surface,
|
||||
&physical_device_surface_capabilities);
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->physical_device, context->surface,
|
||||
&physical_device_surface_capabilities);
|
||||
|
||||
STATUS_CHECK(
|
||||
create_image(context, &context->color_image,
|
||||
physical_device_surface_capabilities.currentExtent.width,
|
||||
physical_device_surface_capabilities.currentExtent.height,
|
||||
color_format, VK_SAMPLE_COUNT_8_BIT,
|
||||
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT |
|
||||
VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
|
||||
0U));
|
||||
STATUS_CHECK(create_image_view(context, &context->color_image, color_format,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
STATUS_CHECK(create_image(context, &context->color_image, physical_device_surface_capabilities.currentExtent.width,
|
||||
physical_device_surface_capabilities.currentExtent.height, color_format,
|
||||
VK_SAMPLE_COUNT_8_BIT,
|
||||
VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT, 0U));
|
||||
STATUS_CHECK(create_image_view(context, &context->color_image, color_format, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -205,18 +182,13 @@ rse_err_t create_depth_resources(struct graphics_context_t* context)
|
||||
VkSurfaceCapabilitiesKHR physical_device_surface_capabilities;
|
||||
|
||||
STATUS_CHECK(find_depth_format(context, &depth_format));
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(
|
||||
context->physical_device, context->surface,
|
||||
&physical_device_surface_capabilities);
|
||||
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(context->physical_device, context->surface,
|
||||
&physical_device_surface_capabilities);
|
||||
|
||||
STATUS_CHECK(
|
||||
create_image(context, &context->depth_image,
|
||||
physical_device_surface_capabilities.currentExtent.width,
|
||||
physical_device_surface_capabilities.currentExtent.height,
|
||||
depth_format, VK_SAMPLE_COUNT_8_BIT,
|
||||
VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0U));
|
||||
STATUS_CHECK(create_image_view(context, &context->depth_image, depth_format,
|
||||
VK_IMAGE_ASPECT_DEPTH_BIT));
|
||||
STATUS_CHECK(create_image(context, &context->depth_image, physical_device_surface_capabilities.currentExtent.width,
|
||||
physical_device_surface_capabilities.currentExtent.height, depth_format,
|
||||
VK_SAMPLE_COUNT_8_BIT, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT, 0U));
|
||||
STATUS_CHECK(create_image_view(context, &context->depth_image, depth_format, VK_IMAGE_ASPECT_DEPTH_BIT));
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -228,8 +200,7 @@ rse_err_t create_depth_resources(struct graphics_context_t* context)
|
||||
* @param[out] format_size Format size in bytes to return
|
||||
* @return RSE_ERROR_NO_ERROR on success, error code otherwise
|
||||
*/
|
||||
static rse_err_t format_to_pixel_size(VkFormat format,
|
||||
VkDeviceSize* format_size)
|
||||
static rse_err_t format_to_pixel_size(VkFormat format, VkDeviceSize* format_size)
|
||||
{
|
||||
switch (format) {
|
||||
case VK_FORMAT_R8_SRGB:
|
||||
@@ -252,10 +223,8 @@ static rse_err_t format_to_pixel_size(VkFormat format,
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
static rse_err_t transition_image_layout(struct graphics_context_t* context,
|
||||
struct vulkan_image_t* image,
|
||||
VkImageLayout old_layout,
|
||||
VkImageLayout new_layout)
|
||||
static rse_err_t transition_image_layout(struct graphics_context_t* context, struct vulkan_image_t* image,
|
||||
VkImageLayout old_layout, VkImageLayout new_layout)
|
||||
{
|
||||
VkImageSubresourceRange range = {0};
|
||||
VkImageMemoryBarrier image_barrier = {0};
|
||||
@@ -280,8 +249,7 @@ static rse_err_t transition_image_layout(struct graphics_context_t* context,
|
||||
image_barrier.image = image->image;
|
||||
image_barrier.subresourceRange = range;
|
||||
|
||||
if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED &&
|
||||
new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
|
||||
if (old_layout == VK_IMAGE_LAYOUT_UNDEFINED && new_layout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
|
||||
image_barrier.srcAccessMask = 0;
|
||||
image_barrier.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
@@ -299,18 +267,14 @@ static rse_err_t transition_image_layout(struct graphics_context_t* context,
|
||||
}
|
||||
|
||||
command_buffer = begin_single_time_command(context);
|
||||
vkCmdPipelineBarrier(command_buffer, source_stage, destination_stage, 0, 0,
|
||||
NULL, 0, NULL, 1, &image_barrier);
|
||||
vkCmdPipelineBarrier(command_buffer, source_stage, destination_stage, 0, 0, NULL, 0, NULL, 1, &image_barrier);
|
||||
end_single_time_comands(context, command_buffer);
|
||||
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
}
|
||||
|
||||
static rse_err_t create_textured_image(struct graphics_context_t* context,
|
||||
uint32_t width, uint32_t height,
|
||||
VkFormat format,
|
||||
const unsigned char* pixels,
|
||||
uint16_t* texture_id)
|
||||
static rse_err_t create_textured_image(struct graphics_context_t* context, uint32_t width, uint32_t height,
|
||||
VkFormat format, const unsigned char* pixels, uint16_t* texture_id)
|
||||
{
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
struct vulkan_buffer_t staging_buffer = {0};
|
||||
@@ -345,11 +309,9 @@ static rse_err_t create_textured_image(struct graphics_context_t* context,
|
||||
|
||||
staging_buffer_size = staging_buffer_size * width * height;
|
||||
|
||||
STATUS_CHECK(create_image(
|
||||
context, free_texture_image, width, height, format,
|
||||
VK_SAMPLE_COUNT_8_BIT,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT));
|
||||
STATUS_CHECK(create_image(context, free_texture_image, width, height, format, VK_SAMPLE_COUNT_8_BIT,
|
||||
VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
VMA_ALLOCATION_CREATE_DEDICATED_MEMORY_BIT));
|
||||
|
||||
// /* Put image into correct layout to copy pixels from buffer to image
|
||||
// memory */ range.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
@@ -382,19 +344,14 @@ static rse_err_t create_textured_image(struct graphics_context_t* context,
|
||||
// &image_barrier);
|
||||
// end_single_time_comands(command_buffer);
|
||||
|
||||
transition_image_layout(context, free_texture_image,
|
||||
VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
transition_image_layout(context, free_texture_image, VK_IMAGE_LAYOUT_UNDEFINED,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
/* Copy pixel data to GPU memory */
|
||||
STATUS_CHECK(create_buffer(
|
||||
context, staging_buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||
VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_MAPPED_BIT |
|
||||
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT,
|
||||
&staging_buffer));
|
||||
context, staging_buffer_size, VK_BUFFER_USAGE_TRANSFER_SRC_BIT, VMA_MEMORY_USAGE_AUTO_PREFER_HOST,
|
||||
VMA_ALLOCATION_CREATE_MAPPED_BIT | VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT, &staging_buffer));
|
||||
|
||||
memcpy(staging_buffer.allocation_info.pMappedData, pixels,
|
||||
staging_buffer_size);
|
||||
memcpy(staging_buffer.allocation_info.pMappedData, pixels, staging_buffer_size);
|
||||
|
||||
copy_region.bufferOffset = 0U;
|
||||
copy_region.bufferRowLength = 0U;
|
||||
@@ -409,14 +366,12 @@ static rse_err_t create_textured_image(struct graphics_context_t* context,
|
||||
copy_region.imageExtent = image_extent;
|
||||
|
||||
command_buffer = begin_single_time_command(context);
|
||||
vkCmdCopyBufferToImage(
|
||||
command_buffer, staging_buffer.buffer, free_texture_image->image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region);
|
||||
vkCmdCopyBufferToImage(command_buffer, staging_buffer.buffer, free_texture_image->image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ©_region);
|
||||
end_single_time_comands(context, command_buffer);
|
||||
destroy_buffer(context, &staging_buffer);
|
||||
|
||||
transition_image_layout(context, free_texture_image,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
transition_image_layout(context, free_texture_image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
|
||||
// /* Change image layout for shaders to be able to read it */
|
||||
@@ -438,8 +393,7 @@ static rse_err_t create_textured_image(struct graphics_context_t* context,
|
||||
// &image_barrier);
|
||||
// end_single_time_comands(command_buffer);
|
||||
|
||||
STATUS_CHECK(create_image_view(context, free_texture_image, format,
|
||||
VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
STATUS_CHECK(create_image_view(context, free_texture_image, format, VK_IMAGE_ASPECT_COLOR_BIT));
|
||||
|
||||
free_texture_image->id_taken = IMAGE_TAKEN;
|
||||
return RSE_ERROR_NO_ERROR;
|
||||
@@ -449,29 +403,24 @@ rse_err_t init_vulkan_images(struct graphics_context_t* context)
|
||||
{
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
|
||||
STATUS_CHECK(create_sampler(context));
|
||||
STATUS_CHECK(create_depth_resources(context));
|
||||
STATUS_CHECK(create_color_resource(context));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
rse_err_t load_texture_from_bitmat(struct graphics_context_t* context,
|
||||
const unsigned char* pixel_buffer, int width,
|
||||
int height, uint16_t* texture_id,
|
||||
VkFormat color_format)
|
||||
rse_err_t load_texture_from_bitmat(struct graphics_context_t* context, const unsigned char* pixel_buffer, int width,
|
||||
int height, uint16_t* texture_id, VkFormat color_format)
|
||||
{
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
|
||||
/* Create actual Vulkan Image */
|
||||
STATUS_CHECK(create_textured_image(context, width, height, color_format,
|
||||
pixel_buffer, texture_id));
|
||||
STATUS_CHECK(create_textured_image(context, width, height, color_format, pixel_buffer, texture_id));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
rse_err_t load_texture_from_file(struct graphics_context_t* context,
|
||||
const char* file_path, uint16_t* texture_id)
|
||||
rse_err_t load_texture_from_file(struct graphics_context_t* context, const char* file_path, uint16_t* texture_id)
|
||||
{
|
||||
rse_err_t status = RSE_ERROR_NO_ERROR;
|
||||
int width = 0;
|
||||
@@ -479,16 +428,14 @@ rse_err_t load_texture_from_file(struct graphics_context_t* context,
|
||||
int channels = 0;
|
||||
stbi_uc* pixel_buffer = NULL;
|
||||
|
||||
pixel_buffer =
|
||||
stbi_load(file_path, &width, &height, &channels, STBI_rgb_alpha);
|
||||
pixel_buffer = stbi_load(file_path, &width, &height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (pixel_buffer == NULL) {
|
||||
LOGE("Failed to load texture from file: %s", file_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
STATUS_CHECK(load_texture_from_bitmat(context, pixel_buffer, width, height,
|
||||
texture_id, VK_FORMAT_R8G8B8A8_SRGB));
|
||||
STATUS_CHECK(load_texture_from_bitmat(context, pixel_buffer, width, height, texture_id, VK_FORMAT_R8G8B8A8_SRGB));
|
||||
|
||||
stbi_image_free(pixel_buffer);
|
||||
|
||||
@@ -503,10 +450,8 @@ void destroy_textures(struct graphics_context_t* context)
|
||||
|
||||
for (i = 0U; i < RSE_MAX_IMAGE_COUNT; ++i) {
|
||||
if (context->texture_images[i].id_taken == IMAGE_TAKEN) {
|
||||
vkDestroyImageView(context->device,
|
||||
context->texture_images[i].image_view, NULL);
|
||||
vmaDestroyImage(context->allocator,
|
||||
context->texture_images[i].image,
|
||||
vkDestroyImageView(context->device, context->texture_images[i].image_view, NULL);
|
||||
vmaDestroyImage(context->allocator, context->texture_images[i].image,
|
||||
context->texture_images[i].allocation);
|
||||
}
|
||||
}
|
||||
@@ -515,15 +460,13 @@ void destroy_textures(struct graphics_context_t* context)
|
||||
void destroy_depth_resource(struct graphics_context_t* context)
|
||||
{
|
||||
vkDestroyImageView(context->device, context->depth_image.image_view, NULL);
|
||||
vmaDestroyImage(context->allocator, context->depth_image.image,
|
||||
context->depth_image.allocation);
|
||||
vmaDestroyImage(context->allocator, context->depth_image.image, context->depth_image.allocation);
|
||||
}
|
||||
|
||||
void destroy_color_resource(struct graphics_context_t* context)
|
||||
{
|
||||
vkDestroyImageView(context->device, context->color_image.image_view, NULL);
|
||||
vmaDestroyImage(context->allocator, context->color_image.image,
|
||||
context->color_image.allocation);
|
||||
vmaDestroyImage(context->allocator, context->color_image.image, context->color_image.allocation);
|
||||
}
|
||||
|
||||
uint8_t image_exists(struct graphics_context_t* context, uint8_t image_id)
|
||||
@@ -545,16 +488,14 @@ size_t get_textures_count(struct graphics_context_t* context)
|
||||
return count;
|
||||
}
|
||||
|
||||
rse_err_t find_depth_format(struct graphics_context_t* context,
|
||||
VkFormat* found_format)
|
||||
rse_err_t find_depth_format(struct graphics_context_t* context, VkFormat* found_format)
|
||||
{
|
||||
#define formats_count 3
|
||||
rse_err_t status;
|
||||
VkFormat formats[formats_count] = {VK_FORMAT_D32_SFLOAT};
|
||||
|
||||
STATUS_CHECK(find_supported_format(
|
||||
context, formats, formats_count, VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, found_format));
|
||||
STATUS_CHECK(find_supported_format(context, formats, formats_count, VK_IMAGE_TILING_OPTIMAL,
|
||||
VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT, found_format));
|
||||
|
||||
return status;
|
||||
#undef formats_count
|
||||
|
||||
@@ -9,18 +9,15 @@
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef TEXTURE_H
|
||||
#define TEXTURE_H
|
||||
|
||||
#include "utilities/file_utils.h"
|
||||
#include "utilities/commons.h"
|
||||
#include "graphics_context.h"
|
||||
|
||||
#include "vulkan/vulkan_core.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "graphics_context.h"
|
||||
#include "utilities/commons.h"
|
||||
#include "utilities/file_utils.h"
|
||||
#include "vulkan/vulkan_core.h"
|
||||
|
||||
#define IMAGE_FORMAT VK_FORMAT_B8G8R8A8_SRGB;
|
||||
|
||||
@@ -40,7 +37,8 @@ rse_err_t init_vulkan_images(struct graphics_context_t* context);
|
||||
* @param texture_id Texture ID will be set up here
|
||||
* @return rse_err_t RSE_ERROR_NO_ERROR on success
|
||||
*/
|
||||
rse_err_t load_texture_from_bitmat(struct graphics_context_t* context, const unsigned char* pixel_buffer, int width, int height, uint16_t* texture_id, VkFormat color_format);
|
||||
rse_err_t load_texture_from_bitmat(struct graphics_context_t* context, const unsigned char* pixel_buffer, int width,
|
||||
int height, uint16_t* texture_id, VkFormat color_format);
|
||||
|
||||
/**
|
||||
* @brief Loads image from file, for later to be used as a texture
|
||||
@@ -85,4 +83,6 @@ void destroy_color_resource(struct graphics_context_t* context);
|
||||
rse_err_t create_depth_resources(struct graphics_context_t* context);
|
||||
void destroy_depth_resource(struct graphics_context_t* context);
|
||||
|
||||
rse_err_t create_sampler(struct graphics_context_t* context, VkSampler sampler);
|
||||
|
||||
#endif /* TEXTURE_H */
|
||||
Reference in new issue
Block a user