From e8b0ab3b35ecb1f8728ffeb0a4ed8be8964dc505 Mon Sep 17 00:00:00 2001 From: Jakob Bornecrantz Date: Wed, 10 Nov 2021 13:09:07 +0000 Subject: [PATCH] aux/vk: Add many more helper functions --- src/xrt/auxiliary/CMakeLists.txt | 2 + src/xrt/auxiliary/meson.build | 2 + src/xrt/auxiliary/vk/vk_command_buffer.c | 96 ++++++++++ src/xrt/auxiliary/vk/vk_helpers.h | 115 ++++++++++++ src/xrt/auxiliary/vk/vk_state_creators.c | 212 +++++++++++++++++++++++ 5 files changed, 427 insertions(+) create mode 100644 src/xrt/auxiliary/vk/vk_command_buffer.c create mode 100644 src/xrt/auxiliary/vk/vk_state_creators.c diff --git a/src/xrt/auxiliary/CMakeLists.txt b/src/xrt/auxiliary/CMakeLists.txt index d9ca77dd1..3cca611ba 100644 --- a/src/xrt/auxiliary/CMakeLists.txt +++ b/src/xrt/auxiliary/CMakeLists.txt @@ -184,11 +184,13 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/util/u_git_tag.c.in" "${CMAKE_CURREN list(APPEND UTIL_SOURCE_FILES "${CMAKE_CURRENT_BINARY_DIR}/u_git_tag.c") set(VK_SOURCE_FILES + vk/vk_command_buffer.c vk/vk_documentation.h vk/vk_helpers.c vk/vk_helpers.h vk/vk_image_allocator.c vk/vk_image_allocator.h + vk/vk_state_creators.c ) # Common includes diff --git a/src/xrt/auxiliary/meson.build b/src/xrt/auxiliary/meson.build index 6e3f7ed7b..610b1586e 100644 --- a/src/xrt/auxiliary/meson.build +++ b/src/xrt/auxiliary/meson.build @@ -271,11 +271,13 @@ aux_vive = declare_dependency( lib_aux_vk = static_library( 'aux_vk', files( + 'vk/vk_command_buffer.c', 'vk/vk_documentation.h', 'vk/vk_helpers.h', 'vk/vk_helpers.c', 'vk/vk_image_allocator.h', 'vk/vk_image_allocator.c', + 'vk/vk_state_creators.c', ), include_directories: [ xrt_include, diff --git a/src/xrt/auxiliary/vk/vk_command_buffer.c b/src/xrt/auxiliary/vk/vk_command_buffer.c new file mode 100644 index 000000000..16f2f2981 --- /dev/null +++ b/src/xrt/auxiliary/vk/vk_command_buffer.c @@ -0,0 +1,96 @@ +// Copyright 2019-2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Vulkan command buffer helpers. + * + * @author Jakob Bornecrantz + * @author Lubosz Sarnecki + * @ingroup aux_vk + */ + +#include "vk/vk_helpers.h" + + +VkResult +vk_create_command_buffer(struct vk_bundle *vk, VkCommandBuffer *out_command_buffer) +{ + VkResult ret; + + VkCommandBufferAllocateInfo cmd_buffer_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO, + .commandPool = vk->cmd_pool, + .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY, + .commandBufferCount = 1, + }; + + VkCommandBuffer cmd = VK_NULL_HANDLE; + + os_mutex_lock(&vk->cmd_pool_mutex); + + ret = vk->vkAllocateCommandBuffers( // + vk->device, // device + &cmd_buffer_info, // pAllocateInfo + &cmd); // pCommandBuffers + + os_mutex_unlock(&vk->cmd_pool_mutex); + + if (ret != VK_SUCCESS) { + VK_ERROR(vk, "vkCreateFramebuffer failed: %s", vk_result_string(ret)); + return ret; + } + + *out_command_buffer = cmd; + + return VK_SUCCESS; +} + +void +vk_destroy_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer) +{ + os_mutex_lock(&vk->cmd_pool_mutex); + + vk->vkFreeCommandBuffers( // + vk->device, // device + vk->cmd_pool, // commandPool + 1, // commandBufferCount + &command_buffer); // pCommandBuffers + + os_mutex_unlock(&vk->cmd_pool_mutex); +} + +VkResult +vk_begin_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer) +{ + VkResult ret; + + VkCommandBufferBeginInfo command_buffer_info = { + .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, + }; + + ret = vk->vkBeginCommandBuffer( // + command_buffer, // commandBuffer + &command_buffer_info); // pBeginInfo + if (ret != VK_SUCCESS) { + VK_ERROR(vk, "vkBeginCommandBuffer failed: %s", vk_result_string(ret)); + return ret; + } + + return VK_SUCCESS; +} + +VkResult +vk_end_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer) +{ + VkResult ret; + + // End the command buffer. + ret = vk->vkEndCommandBuffer( // + command_buffer); // commandBuffer + if (ret != VK_SUCCESS) { + VK_ERROR(vk, "vkEndCommandBuffer failed: %s", vk_result_string(ret)); + return ret; + } + + return VK_SUCCESS; +} diff --git a/src/xrt/auxiliary/vk/vk_helpers.h b/src/xrt/auxiliary/vk/vk_helpers.h index 750a46dbc..92f66c957 100644 --- a/src/xrt/auxiliary/vk/vk_helpers.h +++ b/src/xrt/auxiliary/vk/vk_helpers.h @@ -669,6 +669,121 @@ vk_update_buffer(struct vk_bundle *vk, float *buffer, size_t buffer_size, VkDevi VkResult vk_locked_submit(struct vk_bundle *vk, VkQueue queue, uint32_t count, const VkSubmitInfo *infos, VkFence fence); + +/* + * + * State creation helpers, in the vk_state_creators.c file. + * + */ + +/*! + * Arguments to @ref vk_create_descriptor_pool function. + */ +struct vk_descriptor_pool_info +{ + uint32_t uniform_per_descriptor_count; //!< VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER + uint32_t sampler_per_descriptor_count; //!< VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER + uint32_t storage_image_per_descriptor_count; //!< VK_DESCRIPTOR_TYPE_STORAGE_IMAGE + uint32_t storage_buffer_per_descriptor_count; //!< VK_DESCRIPTOR_TYPE_STORAGE_BUFFER + + //! The max count of created descriptors. + uint32_t descriptor_count; + + //! Are descriptors freeable, or must vkResetDescriptorPool be used. + bool freeable; +}; + +/*! + * Creates a descriptor pool, made for a single layout. + * + * Does error logging. + */ +VkResult +vk_create_descriptor_pool(struct vk_bundle *vk, + const struct vk_descriptor_pool_info *info, + VkDescriptorPool *out_descriptor_pool); + +/*! + * Creates a descriptor set. + * + * Does error logging. + */ +VkResult +vk_create_descriptor_set(struct vk_bundle *vk, + VkDescriptorPool descriptor_pool, + VkDescriptorSetLayout descriptor_layout, + VkDescriptorSet *out_descriptor_set); + +/*! + * Creates a pipeline layout from a single descriptor set layout. + * + * Does error logging. + */ +VkResult +vk_create_pipeline_layout(struct vk_bundle *vk, + VkDescriptorSetLayout descriptor_set_layout, + VkPipelineLayout *out_pipeline_layout); + +/*! + * Creates a pipeline cache. + * + * Does error logging. + */ +VkResult +vk_create_pipeline_cache(struct vk_bundle *vk, VkPipelineCache *out_pipeline_cache); + +/*! + * Creates a compute pipeline, assumes entry function is called 'main'. + * + * Does error logging. + */ +VkResult +vk_create_compute_pipeline(struct vk_bundle *vk, + VkPipelineCache pipeline_cache, + VkShaderModule shader, + VkPipelineLayout pipeline_layout, + VkPipeline *out_compute_pipeline); + + +/* + * + * Command buffer helpers, in the vk_command_buffer.c file. + * + */ + +/*! + * Creates a new command buffer using the bundle's pool, takes the cmd_pool_mutex. + * + * Does error logging. + */ +VkResult +vk_create_command_buffer(struct vk_bundle *vk, VkCommandBuffer *out_cmd); + +/*! + * Destroys a command buffer, takes the cmd_pool_mutex. + * + * Does error logging. + */ +void +vk_destroy_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer); + +/*! + * Issues the vkBeginCommandBuffer function on the command buffer. + * + * Does error logging. + */ +VkResult +vk_begin_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer); + +/*! + * Issues the vkEndCommandBuffer function on the command buffer. + * + * Does error logging. + */ +VkResult +vk_end_command_buffer(struct vk_bundle *vk, VkCommandBuffer command_buffer); + + #ifdef __cplusplus } #endif diff --git a/src/xrt/auxiliary/vk/vk_state_creators.c b/src/xrt/auxiliary/vk/vk_state_creators.c new file mode 100644 index 000000000..3e5164f31 --- /dev/null +++ b/src/xrt/auxiliary/vk/vk_state_creators.c @@ -0,0 +1,212 @@ +// Copyright 2019-2021, Collabora, Ltd. +// SPDX-License-Identifier: BSL-1.0 +/*! + * @file + * @brief Vulkan state creators helpers. + * + * @author Jakob Bornecrantz + * @author Lubosz Sarnecki + * @ingroup aux_vk + */ + +#include "vk/vk_helpers.h" + + +VkResult +vk_create_descriptor_pool(struct vk_bundle *vk, + const struct vk_descriptor_pool_info *info, + VkDescriptorPool *out_descriptor_pool) +{ + VkResult ret; + + uint32_t pool_count = 0; + VkDescriptorPoolSize pool_sizes[4] = {0}; + + const uint32_t descriptor_count = info->descriptor_count; + const uint32_t uniform_count = info->uniform_per_descriptor_count * descriptor_count; + const uint32_t sampler_count = info->sampler_per_descriptor_count * descriptor_count; + const uint32_t storage_image_count = info->storage_image_per_descriptor_count * descriptor_count; + const uint32_t storage_buffer_count = info->storage_buffer_per_descriptor_count * descriptor_count; + + if (uniform_count > 0) { + pool_sizes[pool_count].type = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; + pool_sizes[pool_count].descriptorCount = uniform_count; + pool_count++; + } + + if (sampler_count > 0) { + pool_sizes[pool_count].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + pool_sizes[pool_count].descriptorCount = sampler_count; + pool_count++; + } + + if (storage_image_count > 0) { + pool_sizes[pool_count].type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; + pool_sizes[pool_count].descriptorCount = storage_image_count; + pool_count++; + } + + if (storage_buffer_count > 0) { + pool_sizes[pool_count].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER; + pool_sizes[pool_count].descriptorCount = storage_buffer_count; + pool_count++; + } + + assert(pool_count > 0 && pool_count <= ARRAY_SIZE(pool_sizes)); + + VkDescriptorPoolCreateFlags flags = 0; + + if (info->freeable) { + flags |= VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT; + } + + VkDescriptorPoolCreateInfo descriptor_pool_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO, + .flags = flags, + .maxSets = descriptor_count, + .poolSizeCount = pool_count, + .pPoolSizes = pool_sizes, + }; + + VkDescriptorPool descriptor_pool = VK_NULL_HANDLE; + ret = vk->vkCreateDescriptorPool( // + vk->device, // device + &descriptor_pool_info, // pCreateInfo + NULL, // pAllocator + &descriptor_pool); // pDescriptorPool + if (ret != VK_SUCCESS) { + VK_ERROR(vk, "vkCreateRenderPass failed: %s", vk_result_string(ret)); + return ret; + } + + *out_descriptor_pool = descriptor_pool; + + return VK_SUCCESS; +} + +VkResult +vk_create_descriptor_set(struct vk_bundle *vk, + VkDescriptorPool descriptor_pool, + VkDescriptorSetLayout descriptor_layout, + VkDescriptorSet *out_descriptor_set) +{ + VkResult ret; + + VkDescriptorSetAllocateInfo alloc_info = { + .sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO, + .descriptorPool = descriptor_pool, + .descriptorSetCount = 1, + .pSetLayouts = &descriptor_layout, + }; + + VkDescriptorSet descriptor_set = VK_NULL_HANDLE; + ret = vk->vkAllocateDescriptorSets( // + vk->device, // device + &alloc_info, // pAllocateInfo + &descriptor_set); // pDescriptorSets + if (ret != VK_SUCCESS) { + VK_DEBUG(vk, "vkAllocateDescriptorSets failed: %s", vk_result_string(ret)); + return ret; + } + + *out_descriptor_set = descriptor_set; + + return VK_SUCCESS; +} + +VkResult +vk_create_pipeline_layout(struct vk_bundle *vk, + VkDescriptorSetLayout descriptor_set_layout, + VkPipelineLayout *out_pipeline_layout) +{ + VkResult ret; + + VkPipelineLayoutCreateInfo pipeline_layout_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, + .setLayoutCount = 1, + .pSetLayouts = &descriptor_set_layout, + }; + + VkPipelineLayout pipeline_layout = VK_NULL_HANDLE; + ret = vk->vkCreatePipelineLayout( // + vk->device, // device + &pipeline_layout_info, // pCreateInfo + NULL, // pAllocator + &pipeline_layout); // pPipelineLayout + if (ret != VK_SUCCESS) { + VK_ERROR(vk, "vkCreatePipelineLayout failed: %s", vk_result_string(ret)); + return ret; + } + + *out_pipeline_layout = pipeline_layout; + + return VK_SUCCESS; +} + +VkResult +vk_create_pipeline_cache(struct vk_bundle *vk, VkPipelineCache *out_pipeline_cache) +{ + VkResult ret; + + VkPipelineCacheCreateInfo pipeline_cache_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO, + }; + + VkPipelineCache pipeline_cache; + ret = vk->vkCreatePipelineCache( // + vk->device, // device + &pipeline_cache_info, // pCreateInfo + NULL, // pAllocator + &pipeline_cache); // pPipelineCache + if (ret != VK_SUCCESS) { + VK_ERROR(vk, "vkCreatePipelineCache failed: %s", vk_result_string(ret)); + return ret; + } + + *out_pipeline_cache = pipeline_cache; + + return VK_SUCCESS; +} + +VkResult +vk_create_compute_pipeline(struct vk_bundle *vk, + VkPipelineCache pipeline_cache, + VkShaderModule shader, + VkPipelineLayout pipeline_layout, + VkPipeline *out_compute_pipeline) +{ + VkResult ret; + + VkPipelineShaderStageCreateInfo shader_stage_info = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, + .pNext = NULL, + .stage = VK_SHADER_STAGE_COMPUTE_BIT, + .module = shader, + .pName = "main", + }; + + VkComputePipelineCreateInfo pipeline_info = { + .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, + .pNext = NULL, + .flags = 0, + .stage = shader_stage_info, + .layout = pipeline_layout, + }; + + VkPipeline pipeline = VK_NULL_HANDLE; + ret = vk->vkCreateComputePipelines( // + vk->device, // device + pipeline_cache, // pipelineCache + 1, // createInfoCount + &pipeline_info, // pCreateInfos + NULL, // pAllocator + &pipeline); // pPipelines + if (ret != VK_SUCCESS) { + VK_DEBUG(vk, "vkCreateComputePipelines failed: %s", vk_result_string(ret)); + return ret; + } + + *out_compute_pipeline = pipeline; + + return VK_SUCCESS; +}