4#include <vulkan/vulkan_core.h>
5#include <unordered_map>
14 class ApplicationContext;
38 PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT =
40 PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT =
nullptr;
41 PFN_vkResetQueryPool vkResetQueryPool =
nullptr;
63 VkDeviceSize
size = VK_WHOLE_SIZE;
79enum DynamicFunctionInitState : uint32_t
82 DEBUG_FUNCTIONS_INITIALIZED = 1,
126 template <
typename T>
127 static void loadVkFunction( VkInstance instance,
const std::string & name, T & functionPointer )
129 functionPointer =
reinterpret_cast<T
>( vkGetInstanceProcAddr( instance, name.c_str() ) );
131 if ( !functionPointer )
133 std::stringstream error;
134 error <<
"Vulkan INSTANCE extension function " << name <<
" is not supported!";
135 PLOGE << error.str();
136 throw std::runtime_error( error.str() );
148 template <
typename T>
151 functionPointer =
reinterpret_cast<T
>( vkGetDeviceProcAddr( device, name.c_str() ) );
152 if ( !functionPointer )
154 std::stringstream error;
155 error <<
"Vulkan DEVICE extension function " << name <<
" is not supported!";
156 PLOGE << error.str();
157 throw std::runtime_error( error.str() );
174 VkPhysicalDevice physicalDevice,
176 VkBufferUsageFlags usage,
177 VkMemoryPropertyFlags properties,
179 VkDeviceMemory & bufferMemory
195 VkPhysicalDevice physicalDevice,
196 VkCommandPool commandPool,
199 const void * dataPtr,
200 VkBuffer targetBuffer
226 VkPhysicalDevice physicalDevice,
228 VkMemoryPropertyFlags properties
240 VkPhysicalDevice physicalDevice,
241 VkMemoryRequirements2 requirements,
242 VkMemoryPropertyFlags properties,
243 uint32_t & out_typeIndex
252 static VkDeviceSize
align( VkDeviceSize value, VkDeviceSize alignment );
265 VkCommandPool commandPool,
266 VkQueue graphicsQueue,
267 VkBuffer sourceBuffer,
268 VkBuffer destinationBuffer,
282 VkCommandPool commandPool,
283 VkQueue graphicsQueue,
284 const std::vector<BufferCopyObject> & bufferCopyObjects
296 VkCommandBuffer commandBuffer,
297 const std::vector<BufferCopyObject> & bufferCopyObjects
317 VkQueue graphicsQueue,
318 VkCommandPool commandPool,
319 VkCommandBuffer commandBuffer
327 static void cleanupBuffer( VkDevice device, VkBuffer buffer, VkDeviceMemory bufferMemory );
345 VkPhysicalDevice physicalDevice,
349 VkImageTiling tiling,
350 VkImageUsageFlags usage,
351 VkMemoryPropertyFlags properties,
353 VkDeviceMemory & imageMemory
370 VkCommandBuffer commandBuffer,
372 VkQueue graphicsQueue,
373 VkCommandPool commandPool,
376 VkImageLayout oldLayout,
377 VkImageLayout newLayout,
378 uint32_t layerCount = 1
400 VkCommandPool commandPool,
401 VkQueue graphicsQueue,
418 createImageView( VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags );
437 const VkDescriptorSetAllocateInfo * pAllocateInfo,
438 VkDescriptorSet * pDescriptorSets,
439 const std::string & name
454 const VkSemaphoreCreateInfo * pCreateInfo,
455 const VkAllocationCallbacks * pAllocator,
456 VkSemaphore * pSemaphore,
457 const std::string & name
471 const VkCommandBufferAllocateInfo * pAllocateInfo,
472 VkCommandBuffer * pCommandBuffers,
473 const std::string & name
488 const VkDescriptorSetLayoutCreateInfo * pCreateInfo,
489 const VkAllocationCallbacks * pAllocator,
490 VkDescriptorSetLayout * pSetLayout,
491 const std::string & name
506 const VkPipelineLayoutCreateInfo * pCreateInfo,
507 const VkAllocationCallbacks * pAllocator,
508 VkPipelineLayout * pPipelineLayout,
509 const std::string & name
523 const VkFenceCreateInfo * pCreateInfo,
524 const VkAllocationCallbacks * pAllocator,
526 const std::string & name
540 const VkDescriptorPoolCreateInfo * pCreateInfo,
541 const VkAllocationCallbacks * pAllocator,
542 VkDescriptorPool * pDescriptorPool,
543 const std::string & name
553 static std::string
getName(
const std::string & name,
const std::string & suffix );
566 beginLabel( VkCommandBuffer commandBuffer,
const char * pLabelName,
const float color[4] =
nullptr );
573 static void endLabel( VkCommandBuffer commandBuffer );
576 static std::unordered_map<uint64_t, std::string> objectNames;
582 static void beginLabel( VkCommandBuffer,
const char *,
const float * ) {}
593# define VK_OBJECT_TYPE_CASE( VkType, VkEnum ) \
594 if constexpr ( std::is_same_v<VulkanObjectType, VkType> ) \
602 template <
typename VulkanObjectType>
603 static constexpr VkObjectType getVulkanObjectType()
605 VK_OBJECT_TYPE_CASE( VkBuffer, VK_OBJECT_TYPE_BUFFER );
606 VK_OBJECT_TYPE_CASE( VkQueue, VK_OBJECT_TYPE_QUEUE );
607 VK_OBJECT_TYPE_CASE( VkDescriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL );
608 VK_OBJECT_TYPE_CASE( VkDescriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT );
609 VK_OBJECT_TYPE_CASE( VkDescriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET );
610 VK_OBJECT_TYPE_CASE( VkPipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT );
611 VK_OBJECT_TYPE_CASE( VkPipeline, VK_OBJECT_TYPE_PIPELINE );
612 VK_OBJECT_TYPE_CASE( VkCommandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER );
613 VK_OBJECT_TYPE_CASE( VkSemaphore, VK_OBJECT_TYPE_SEMAPHORE );
614 VK_OBJECT_TYPE_CASE( VkFence, VK_OBJECT_TYPE_FENCE );
615 VK_OBJECT_TYPE_CASE( VkImage, VK_OBJECT_TYPE_IMAGE );
616 VK_OBJECT_TYPE_CASE( VkDeviceMemory, VK_OBJECT_TYPE_DEVICE_MEMORY );
617 VK_OBJECT_TYPE_CASE( VkImageView, VK_OBJECT_TYPE_IMAGE_VIEW );
618 VK_OBJECT_TYPE_CASE( VkSampler, VK_OBJECT_TYPE_SAMPLER );
619 VK_OBJECT_TYPE_CASE( VkRenderPass, VK_OBJECT_TYPE_RENDER_PASS );
620 VK_OBJECT_TYPE_CASE( VkShaderModule, VK_OBJECT_TYPE_SHADER_MODULE );
621 VK_OBJECT_TYPE_CASE( VkCommandPool, VK_OBJECT_TYPE_COMMAND_POOL );
623 PLOGF <<
"Failed to find the type of " <<
typeid( VulkanObjectType ).name();
624 return VK_OBJECT_TYPE_UNKNOWN;
633 template <
typename VulkanObjectType>
634 static void setObjectName( VkDevice device, VulkanObjectType objectHandle,
const std::string & name );
641 template <
typename VulkanObjectType>
642 static std::string
getDebugName ( VulkanObjectType objectHandle );
650 template <
typename VulkanObjectType>
651 static void setObjectName( VkDevice device, VulkanObjectType objectHandle,
const std::string & name )
660 template <
typename VulkanObjectType>
674template <
typename VulkanObjectType>
684 VkDebugUtilsObjectNameInfoEXT nameInfo = {};
685 nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
686 nameInfo.objectHandle =
reinterpret_cast<uint64_t
>( objectHandle );
687 nameInfo.objectType = VulkanHelper::getVulkanObjectType<VulkanObjectType>();
688 nameInfo.pObjectName = name.c_str();
691 s_functions.vkSetDebugUtilsObjectNameEXT( device, &nameInfo );
693 objectNames.insert( {
reinterpret_cast<uint64_t
>(objectHandle), name} );
696template <
typename VulkanObjectType>
699 const auto objectHandle64 =
reinterpret_cast<uint64_t
>( objectHandle );
700 if (!objectNames.contains( objectHandle64 ) )
702 return "Unnamed Object";
704 return objectNames.find( objectHandle64 )->second;
733 DebugLabel( VkCommandBuffer commandBuffer,
const char * pLabelName,
const float color[4] =
nullptr )
734 : m_commandBuffer( commandBuffer )
750 DebugLabel( VkCommandBuffer,
const char *,
const float * =
nullptr ) {}
780 VkCommandBuffer m_commandBuffer;
~DebugLabel()
Release-build no-op destructor.
DebugLabel(const DebugLabel &)=delete
Debug label scopes cannot be copied.
DebugLabel & operator=(const DebugLabel &)=delete
Debug label scopes cannot be copy-assigned.
DebugLabel(VkCommandBuffer, const char *, const float *=nullptr)
Release-build no-op constructor.
DebugLabel(DebugLabel &&)=delete
Debug label scopes cannot be moved.
DebugLabel & operator=(DebugLabel &&)=delete
Debug label scopes cannot be move-assigned.
The application context is the core class which stores the basic openxr and vulkan objects.
Static helpers for common Vulkan allocation, copy, descriptor, and debug operations.
static VkDescriptorBufferInfo fullBufferInfo(VkBuffer buffer)
Creates descriptor buffer info for a whole buffer binding.
static std::string getName(const std::string &name, const std::string &suffix)
Appends an object-type suffix to a debug name.
static VkResult createPipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout, const std::string &name)
Creates a pipeline layout and assigns a debug name.
static bool hasStencilComponent(VkFormat format)
Checks whether a Vulkan format contains a stencil component.
static void initializeFunctions(VkInstance instance, VkDevice device)
Loads all Vulkan extension functions used by the engine.
static void loadVkDeviceFunction(VkDevice device, const std::string &name, T &functionPointer)
Loads one Vulkan device-level function pointer.
static std::string getDebugName(VulkanObjectType objectHandle)
Release-build no-op for retrieving a Vulkan object debug name.
static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, VkBuffer sourceBuffer, VkBuffer destinationBuffer, VkDeviceSize size)
Copies bytes from one buffer to another and waits for the queue to become idle.
static VkResult createSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore, const std::string &name)
Creates a semaphore and assigns a debug name.
static std::string strIsValid(void *object)
Returns a checkmark or cross string for a Vulkan dispatchable handle value.
static DynamicFunctionInitState s_functionInitializationState
static VulkanFunctions s_functions
static const VulkanFunctions & getFunctions()
Returns the loaded Vulkan extension function table.
static void endLabel(VkCommandBuffer)
Release-build no-op for ending a Vulkan debug label region.
static VkImageView createImageView(VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
Creates a 2D image view over one mip level and one array layer.
static void createImage(VkDevice device, VkPhysicalDevice physicalDevice, uint32_t width, uint32_t height, VkFormat format, VkImageTiling tiling, VkImageUsageFlags usage, VkMemoryPropertyFlags properties, VkImage &image, VkDeviceMemory &imageMemory)
Creates a 2D image, allocates memory for it, and binds the memory at offset 0.
static bool isValid(void *object)
Checks whether a Vulkan dispatchable handle value is non-null.
static void copyBufferMultiple(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, const std::vector< BufferCopyObject > &bufferCopyObjects)
Copies several buffer regions in one command buffer and waits for the queue to become idle.
static VkDeviceSize align(VkDeviceSize value, VkDeviceSize alignment)
Rounds a size up to the next multiple of an alignment.
static VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool)
Allocates and begins a primary command buffer for one-time submission.
static void setObjectName(VkDevice device, VulkanObjectType objectHandle, const std::string &name)
Release-build no-op for assigning a Vulkan object debug name.
static void loadVkFunction(VkInstance instance, const std::string &name, T &functionPointer)
Loads one Vulkan instance-level function pointer.
static VkResult allocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets, const std::string &name)
Allocates descriptor sets and assigns a debug name to the first returned set.
static void recordBufferCopyMultiple(Engine::Core::ApplicationContext *context, VkCommandBuffer commandBuffer, const std::vector< BufferCopyObject > &bufferCopyObjects)
Records several buffer copy commands into an existing command buffer.
static void initializeDebugFunctions(VkInstance instance)
Loads debug utils extension functions from an instance.
static void endSingleTimeCommands(VkDevice device, VkQueue graphicsQueue, VkCommandPool commandPool, VkCommandBuffer commandBuffer)
Ends, submits, waits for, and frees a one-time command buffer.
static void copyBufferToImage(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, VkBuffer buffer, VkImage image, uint32_t width, uint32_t height)
Copies a buffer into the first layer and mip level of a 2D image.
static uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties)
Finds a memory type index that satisfies a bitmask and required properties.
static void createBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
Creates a Vulkan buffer, allocates memory for it, and binds the memory at offset 0.
static VkResult createDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool, const std::string &name)
Creates a descriptor pool and assigns a debug name.
static void createFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence, const std::string &name)
Creates a fence and assigns a debug name.
static VkResult createDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout, const std::string &name)
Creates a descriptor set layout and assigns a debug name.
static void transitionImageLayout(VkCommandBuffer commandBuffer, VkDevice device, VkQueue graphicsQueue, VkCommandPool commandPool, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t layerCount=1)
Records an image layout transition barrier into an existing command buffer.
static void cleanupBuffer(VkDevice device, VkBuffer buffer, VkDeviceMemory bufferMemory)
Destroys a buffer and frees its memory when the handles are non-null.
static void beginLabel(VkCommandBuffer, const char *, const float *)
Release-build no-op for beginning a Vulkan debug label region.
static void uploadDataToExistingBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, VkDeviceSize size, const void *dataPtr, VkBuffer targetBuffer)
Uploads CPU memory into an existing buffer through a temporary staging buffer.
static std::mutex s_mutex
static bool findSuitableMemoryType(VkPhysicalDevice physicalDevice, VkMemoryRequirements2 requirements, VkMemoryPropertyFlags properties, uint32_t &out_typeIndex)
Finds a memory type index without throwing on failure.
static VkResult allocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers, const std::string &name)
Allocates command buffers and assigns a debug name to the first returned command buffer.
Description of one buffer-to-buffer copy operation.
VkBuffer sourceBuffer
Source buffer for the copy.
VkDeviceSize srcOffset
Byte offset in the source buffer.
VkDeviceSize size
Number of bytes to copy.
VkDeviceSize dstOffset
Offset in source buffer (usually 0 for staging)
VkBuffer destinationBuffer
Destination buffer for the copy.
Function pointers for Vulkan extension entry points used by the engine.
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT
Ends command-buffer debug labels.
PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT
Ends conditional rendering.
PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT
Draws mesh tasks indirectly.
PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2
Binds descriptor sets with the Vulkan 1.4 entry point.
PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT
Begins conditional rendering.
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT
Creates debug messengers.
PFN_vkCmdPushConstants2 vkCmdPushConstants2
Pushes constants with the Vulkan 1.4 entry point.
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT
Destroys debug messengers.
PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT
Draws mesh tasks with an indirect count.
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT
Begins command-buffer debug labels.
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT
Assigns debug names to Vulkan objects.