Add bindless textures

Created bindless descriptors for holding texture data.
This commit is contained in:
Piotr Krygier committed 2023-10-04 13:29:23 +02:00
1 parent d328e38761
commit bd4dd74881
13 files changed
+136 -43

No files matched your search

+11 -21
View File
@@ -12,37 +12,24 @@ extern struct rse_vulkan_state_t g_vulkan_state;
void rse_graphics_init(void)
{
// g_vulkan_state = malloc(sizeof(struct rse_vulkan_state_t));
g_vulkan_state.graphics_queue = VK_NULL_HANDLE;
g_vulkan_state.physical_device = VK_NULL_HANDLE;
g_vulkan_state.current_frame = 0U;
// vulkan_state->queueFamilyIndices = {0U}; /* TODO: Change when more families are needed */
// g_vulkan_state->uniformBuffers = {};
// g_vulkan_state->pCommandBuffers = {};
// g_vulkan_state->descriptorSets = {};
// g_vulkan_state->swapChainImageViews = {}; TODO: Allocate later
// g_vulkan_state->swapchainExtent = {}; TODO: Allocate later
g_vulkan_state.render_pass = VK_NULL_HANDLE;
g_vulkan_state.descriptor_set_layout = VK_NULL_HANDLE;
// g_vulkan_state->swapchainFramebuffers = {}; TODO: Allocate later
g_vulkan_state.graphics_pipeline = VK_NULL_HANDLE;
g_vulkan_state.pipeline_layout = VK_NULL_HANDLE;
g_vulkan_state.swapchain = VK_NULL_HANDLE;
}
void rse_graphics_deinit()
{
// free(g_vulkan_state);
}
uint8_t rse_graphics_run(void)
{
int8_t tex_id_2 = 0;
window_init();
if (0 != preinit_vulkan())
return -1;
return;
}
void rse_graphics_test_function(void)
{
int8_t tex_id_2 = 0;
tex_id_2 = rse_load_texture("../../test_image.png");
@@ -82,10 +69,13 @@ uint8_t rse_graphics_run(void)
1.0f,
tex_id_2
});
}
if (0 != init_vulkan())
uint8_t rse_graphics_run(void)
{
if (0 != init_vulkan()) {
return -1;
}
window_loop();
-3
View File
@@ -366,7 +366,6 @@ static int8_t create_vulkan_image(uint32_t width, uint32_t height, VkFormat form
image_view_create_info.image = free_texture_image->image;
image_view_create_info.viewType = VK_IMAGE_VIEW_TYPE_2D;
image_view_create_info.format = format;
// image_view_create_info.components = 0;
image_view_create_info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
image_view_create_info.subresourceRange.baseMipLevel = 0;
image_view_create_info.subresourceRange.levelCount = 1;
@@ -389,8 +388,6 @@ uint8_t init_vulkan_images()
{
uint8_t status = VULKAN_ERROR_NO_ERROR;
// memset(g_texture_images, 0, sizeof(struct rse_vulkan_image_t) * RSE_MAX_IMAGE_COUNT);
STATUS_CHECK(create_sampler());
STATUS_CHECK(create_depth_resources());
+14
View File
@@ -0,0 +1,14 @@
#version 450
/* Each time texture count is changed this value also need to change. I have to fix it somehow. */
layout(binding = 1) uniform sampler2D texSampler[1];
layout(location = 0) in vec3 fragColor;
layout(location = 1) in vec2 fragTexCoord;
layout(location = 2) in flat uint instanceTextureId;
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(fragColor * texture(texSampler[instanceTextureId], fragTexCoord).rgb, 1.0);
}
+20 -3
View File
@@ -342,6 +342,8 @@ uint8_t pick_physical_device()
{
uint32_t physical_device_count = 0U;
VkPhysicalDevice* physical_devices = NULL;
VkPhysicalDeviceProperties device_properties = {0};;
VkPhysicalDeviceFeatures device_features = {0};
/* Get number of existing physical devices */
vkEnumeratePhysicalDevices(g_vulkan_instance, &physical_device_count, NULL);
@@ -356,8 +358,6 @@ uint8_t pick_physical_device()
/* Check for suitability */
for (size_t physicalDeviceIdx = 0U; physicalDeviceIdx < physical_device_count; ++physicalDeviceIdx) {
VkPhysicalDeviceProperties device_properties;
VkPhysicalDeviceFeatures device_features;
vkGetPhysicalDeviceProperties(physical_devices[physicalDeviceIdx], &device_properties);
vkGetPhysicalDeviceFeatures(physical_devices[physicalDeviceIdx], &device_features);
@@ -398,6 +398,22 @@ uint8_t create_device()
VkDeviceQueueCreateInfo device_queue_createinfos[2] = {}; /* TODO: Change when we want more queues */
float* graphics_familiy_queue_priorities = NULL;
float* presentation_familiy_queue_priorities = NULL;
VkPhysicalDeviceFeatures2 physical_features2 = {0};
VkPhysicalDeviceDescriptorIndexingFeatures indexing_features = {0};
VkBool32 bindless_supported = VK_FALSE;
indexing_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES_EXT;
physical_features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
physical_features2.pNext = &indexing_features;
vkGetPhysicalDeviceFeatures2(g_vulkan_state.physical_device, &physical_features2);
bindless_supported = indexing_features.descriptorBindingPartiallyBound && indexing_features.runtimeDescriptorArray;
if (bindless_supported == VK_FALSE) {
LOGE("This engine requires bindless support");
return 1;
}
/* Get information about supported queue families */
vkGetPhysicalDeviceQueueFamilyProperties(g_vulkan_state.physical_device, &queue_families_property_count, NULL);
@@ -473,7 +489,7 @@ uint8_t create_device()
device_queue_createinfos[1].pQueuePriorities = presentation_familiy_queue_priorities;
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.pNext = NULL;
device_create_info.pNext = &physical_features2;
device_create_info.flags = 0U;
device_create_info.queueCreateInfoCount = device_queues_count;
device_create_info.pQueueCreateInfos = device_queue_createinfos;
@@ -483,6 +499,7 @@ uint8_t create_device()
device_create_info.ppEnabledExtensionNames = g_enabled_device_extensions_names;
device_create_info.pEnabledFeatures = NULL; /* TODO: Enable features, when needed */
if (VK_SUCCESS != vkCreateDevice(g_vulkan_state.physical_device, &device_create_info, NULL, &g_vulkan_state.device)) {
LOGF(vulkan_error_messages[VULKAN_FAILED_TO_CREATE_DEVICE]);
return VULKAN_ERROR_DEVICE_CREATION_FAILED;
+4 -2
View File
@@ -330,6 +330,8 @@ uint8_t update_mesh_instances(uint16_t mesh_id, struct rse_instance_data_t* inst
uint8_t record_command_buffer(uint32_t image_index)
{
VkCommandBuffer command_buffer = g_vulkan_state.command_buffers[g_vulkan_state.current_frame];
VkDescriptorSet descriptor_sets[] = {g_vulkan_state.descriptor_sets[g_vulkan_state.current_frame],
g_vulkan_state.descriptor_sets_bindless};
VkCommandBufferBeginInfo begin_info = {};
VkRenderPassBeginInfo render_pass_info = {};
VkViewport viewport = {};
@@ -381,8 +383,8 @@ uint8_t record_command_buffer(uint32_t image_index)
vkCmdBindVertexBuffers(command_buffer, 0, 1, &g_vertex_buffer.buffer, offsets);
vkCmdBindIndexBuffer(command_buffer, g_index_buffer.buffer, 0, VK_INDEX_TYPE_UINT16);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_vulkan_state.pipeline_layout, 0, 1,
&g_vulkan_state.descriptor_sets[g_vulkan_state.current_frame], 0, NULL);
vkCmdBindDescriptorSets(command_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS, g_vulkan_state.pipeline_layout, 0, 2,
descriptor_sets, 0, NULL);
for (i = 0; i < 2; ++i) {
VkBuffer instance_buffer = {g_instance_buffers[i].buffer};
+2
View File
@@ -64,10 +64,12 @@ struct rse_vulkan_state_t
struct rse_vulkan_buffer_t uniform_buffers[SWAP_BUFFER_COUNT];
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;
VkDescriptorSetLayout descriptor_set_layout;
VkDescriptorSetLayout descriptor_set_layout_bindless;
VkFramebuffer* swapchain_framebuffers;
VkPipeline graphics_pipeline;
VkPipelineLayout pipeline_layout;
+40 -5
View File
@@ -8,7 +8,9 @@
#include "vulkan/vulkan.h"
VkDescriptorPool gDescriptorPool;
VkDescriptorPool gDescriptorPool_bindless;
static uint8_t create_descriptor_pool();
static uint8_t create_descriptor_sets();
@@ -27,12 +29,12 @@ uint8_t create_descriptor_pool()
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_SAMPLER;
pool_sizes[1].descriptorCount = (uint32_t)(SWAP_BUFFER_COUNT*get_textures_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 = 2;
pool_info.pPoolSizes = pool_sizes;
pool_info.poolSizeCount = 1;
pool_info.pPoolSizes = &pool_sizes[0];
pool_info.maxSets = (uint32_t)(SWAP_BUFFER_COUNT);
if (vkCreateDescriptorPool(g_vulkan_state.device, &pool_info, NULL, &gDescriptorPool) != VK_SUCCESS) {
@@ -40,6 +42,15 @@ uint8_t create_descriptor_pool()
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(g_vulkan_state.device, &pool_info, NULL, &gDescriptorPool_bindless) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTOR_POOL_CREATION_FAILED]);
return VULKAN_ERROR_DESCRIPTOR_POOL_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
@@ -50,22 +61,44 @@ uint8_t create_descriptor_pool()
* VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED */
uint8_t create_descriptor_sets()
{
uint32_t max_binding = MAX_BINDLESS_RESOURCES - 1;
VkDescriptorSetLayout layouts[SWAP_BUFFER_COUNT] = {
g_vulkan_state.descriptor_set_layout,
g_vulkan_state.descriptor_set_layout
};
VkDescriptorSetLayout layouts_bindless[SWAP_BUFFER_COUNT] = {
g_vulkan_state.descriptor_set_layout_bindless,
g_vulkan_state.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 = gDescriptorPool;
allocInfo.descriptorSetCount = (uint32_t)(SWAP_BUFFER_COUNT);
allocInfo.pSetLayouts = layouts;
allocInfo_bindless = allocInfo;
allocInfo_bindless.descriptorPool = gDescriptorPool_bindless;
allocInfo_bindless.pSetLayouts = layouts_bindless;
allocInfo_bindless.pNext = &count_info;
allocInfo_bindless.descriptorSetCount = 1;
if (vkAllocateDescriptorSets(g_vulkan_state.device, &allocInfo, g_vulkan_state.descriptor_sets) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED]);
return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED;
}
if (vkAllocateDescriptorSets(g_vulkan_state.device, &allocInfo_bindless, &g_vulkan_state.descriptor_sets_bindless) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTOR_SETS_ALLOCATION_FAILED]);
return VULKAN_ERROR_DESCRIPTOR_SETS_ALLOCATION_FAILED;
}
for (size_t i = 0; i < SWAP_BUFFER_COUNT; i++) {
VkDescriptorBufferInfo buffer_info = {};
VkWriteDescriptorSet descriptor_writes[2] = {};
@@ -95,7 +128,7 @@ uint8_t create_descriptor_sets()
descriptor_writes[0].pBufferInfo = &buffer_info;
descriptor_writes[1].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
descriptor_writes[1].dstSet = g_vulkan_state.descriptor_sets[i];
descriptor_writes[1].dstSet = g_vulkan_state.descriptor_sets_bindless;
descriptor_writes[1].dstBinding = 1;
descriptor_writes[1].dstArrayElement = 0;
descriptor_writes[1].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
@@ -121,5 +154,7 @@ uint8_t create_descriptors()
void destroy_descriptors()
{
vkDestroyDescriptorPool(g_vulkan_state.device, gDescriptorPool, NULL);
vkDestroyDescriptorPool(g_vulkan_state.device, gDescriptorPool_bindless, NULL);
vkDestroyDescriptorSetLayout(g_vulkan_state.device, g_vulkan_state.descriptor_set_layout, NULL);
vkDestroyDescriptorSetLayout(g_vulkan_state.device, g_vulkan_state.descriptor_set_layout_bindless, NULL);
}
+3
View File
@@ -2,6 +2,9 @@
#define RSE_VULKAN_DESCRIPTORS_H
#include <stdint.h>
#define MAX_BINDLESS_RESOURCES 16536
/**
* @brief Create descriptors
*
+26 -8
View File
@@ -6,6 +6,7 @@
#include "vulkan_errors.h"
#include "mesh_controller.h"
#include "rse_vulkan_image.h"
#include "vulkan_descriptors.h"
#include "vulkan/vulkan.h"
@@ -294,10 +295,18 @@ uint8_t create_render_pass()
uint8_t create_descriptor_set_layout()
{
VkDescriptorSetLayoutCreateInfo layout_info = {};
VkDescriptorSetLayoutCreateInfo layout_info_bindless = {};
VkDescriptorSetLayoutBinding bindings[2];
VkDescriptorSetLayoutBinding ubo_layout_binding = {};
VkDescriptorSetLayoutBinding sampler_layout_binding = {};
// VkDescriptorSetLayoutBinding textures_layout_binding = {};
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;
extended_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT;
extended_info.bindingCount = 1;
extended_info.pBindingFlags = &bindless_flags;
ubo_layout_binding.binding = 0;
ubo_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
@@ -307,7 +316,7 @@ uint8_t create_descriptor_set_layout()
sampler_layout_binding.binding = 1;
sampler_layout_binding.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
sampler_layout_binding.descriptorCount = get_textures_count();
sampler_layout_binding.descriptorCount = MAX_BINDLESS_RESOURCES;
sampler_layout_binding.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT;
sampler_layout_binding.pImmutableSamplers = NULL;
@@ -315,16 +324,24 @@ uint8_t create_descriptor_set_layout()
bindings[1] = sampler_layout_binding;
layout_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
layout_info.pNext = NULL;
layout_info.flags = 0U;
layout_info.bindingCount = 2U;
layout_info.pBindings = bindings;
layout_info.bindingCount = 1U;
layout_info.pBindings = &bindings[0];
if (vkCreateDescriptorSetLayout(g_vulkan_state.device, &layout_info, NULL, &g_vulkan_state.descriptor_set_layout) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]);
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
}
layout_info_bindless = layout_info;
layout_info_bindless.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT;
layout_info_bindless.pNext = &extended_info;
layout_info_bindless.pBindings = &bindings[1];
if (vkCreateDescriptorSetLayout(g_vulkan_state.device, &layout_info_bindless, NULL, &g_vulkan_state.descriptor_set_layout_bindless) != VK_SUCCESS) {
LOGF(vulkan_error_messages[VULKAN_DESCRIPTORSETLAYOUT_CREATION_FAILED]);
return VULKAN_ERROR_DESCRIPTORSETLAYOUT_CREATION_FAILED;
}
return VULKAN_ERROR_NO_ERROR;
}
/**
@@ -335,12 +352,13 @@ uint8_t create_descriptor_set_layout()
*/
uint8_t create_pipeline_layout()
{
VkDescriptorSetLayout set_layouts[2] = {g_vulkan_state.descriptor_set_layout, g_vulkan_state.descriptor_set_layout_bindless};
VkPipelineLayoutCreateInfo create_info = {};
create_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
create_info.pNext = NULL;
create_info.flags = 0U;
create_info.setLayoutCount = 1U;
create_info.pSetLayouts = &g_vulkan_state.descriptor_set_layout;
create_info.setLayoutCount = 2U;
create_info.pSetLayouts = set_layouts;
create_info.pushConstantRangeCount = 0U;
create_info.pPushConstantRanges = NULL;