Vulkan Schnee 0.0.1
High-performance rendering engine
Loading...
Searching...
No Matches
VulkanHelper.h
Go to the documentation of this file.
1#pragma once
2#include "plog/Log.h"
3#include <mutex>
4#include <vulkan/vulkan_core.h>
5#include <unordered_map>
6
7namespace Engine::Core
8{
10} // namespace Engine::Core
11
12namespace EngineCore
13{
14 class ApplicationContext;
15} // namespace EngineCore
16
18{
19 PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr;
20 PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
21 PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr;
22 PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = nullptr;
23 PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT = nullptr;
24 PFN_vkCmdPushConstants2 vkCmdPushConstants2 = nullptr;
25 PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2 = nullptr;
26 PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr;
27 PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT = nullptr;
28 PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT = nullptr;
29 PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT = nullptr;
30#ifdef ENABLE_TRACY
31 // Tracy calibrated timestamps extension functions
32 PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT =
33 nullptr;
34 PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT = nullptr;
35 PFN_vkResetQueryPool vkResetQueryPool = nullptr;
36#endif
37};
38
40{
41 VkBuffer sourceBuffer = VK_NULL_HANDLE;
42 VkBuffer destinationBuffer = VK_NULL_HANDLE;
43 VkDeviceSize size = VK_WHOLE_SIZE;
44 VkDeviceSize srcOffset = 0;
45 VkDeviceSize dstOffset = 0;
46};
47
54
60{
61public:
62 static void initializeDebugFunctions(VkInstance instance);
63 static void initializeFunctions( VkInstance instance, VkDevice device );
64 static const VulkanFunctions & getFunctions();
65
66 template <typename T>
67 static void loadVkFunction( VkInstance instance, const std::string & name, T & functionPointer )
68 {
69 functionPointer = reinterpret_cast<T>( vkGetInstanceProcAddr( instance, name.c_str() ) );
70
71 if ( !functionPointer )
72 {
73 std::stringstream error;
74 error << "Vulkan INSTANCE extension function " << name << " is not supported!";
75 PLOGE << error.str();
76 throw std::runtime_error( error.str() );
77 }
78 }
79
80 template <typename T>
81 static void loadVkDeviceFunction( VkDevice device, const std::string & name, T & functionPointer )
82 {
83 functionPointer = reinterpret_cast<T>( vkGetDeviceProcAddr( device, name.c_str() ) );
84 if ( !functionPointer )
85 {
86 std::stringstream error;
87 error << "Vulkan DEVICE extension function " << name << " is not supported!";
88 PLOGE << error.str();
89 throw std::runtime_error( error.str() );
90 }
91 }
92
93 static void createBuffer(
94 VkDevice device,
95 VkPhysicalDevice physicalDevice,
96 VkDeviceSize size,
97 VkBufferUsageFlags usage,
98 VkMemoryPropertyFlags properties,
99 VkBuffer & buffer,
100 VkDeviceMemory & bufferMemory
101 );
102
104 VkDevice device,
105 VkPhysicalDevice physicalDevice,
106 VkCommandPool commandPool,
107 VkQueue queue,
108 VkDeviceSize size,
109 const void * dataPtr,
110 VkBuffer targetBuffer
111 );
112
113 static bool isValid( void * object );
114
115 static std::string strIsValid( void * object );
116
117 static uint32_t findMemoryType(
118 VkPhysicalDevice physicalDevice,
119 uint32_t typeFilter,
120 VkMemoryPropertyFlags properties
121 );
122
124 VkPhysicalDevice physicalDevice,
125 VkMemoryRequirements2 requirements,
126 VkMemoryPropertyFlags properties,
127 uint32_t & out_typeIndex
128 );
129
130 static VkDeviceSize align( VkDeviceSize value, VkDeviceSize alignment );
131
132 static void copyBuffer(
133 VkDevice device,
134 VkCommandPool commandPool,
135 VkQueue graphicsQueue,
136 VkBuffer sourceBuffer,
137 VkBuffer destinationBuffer,
138 VkDeviceSize size
139 );
140
142 VkDevice device,
143 VkCommandPool commandPool,
144 VkQueue graphicsQueue,
145 const std::vector<BufferCopyObject> & bufferCopyObjects
146 );
147
150 VkCommandBuffer commandBuffer,
151 const std::vector<BufferCopyObject> & bufferCopyObjects
152 );
153
154 static VkCommandBuffer beginSingleTimeCommands( VkDevice device, VkCommandPool commandPool );
156 VkDevice device,
157 VkQueue graphicsQueue,
158 VkCommandPool commandPool,
159 VkCommandBuffer commandBuffer
160 );
161 static void cleanupBuffer( VkDevice device, VkBuffer buffer, VkDeviceMemory bufferMemory );
162 static void createImage(
163 VkDevice device,
164 VkPhysicalDevice physicalDevice,
165 uint32_t width,
166 uint32_t height,
167 VkFormat format,
168 VkImageTiling tiling,
169 VkImageUsageFlags usage,
170 VkMemoryPropertyFlags properties,
171 VkImage & image,
172 VkDeviceMemory & imageMemory
173 );
174
176 VkCommandBuffer commandBuffer,
177 VkDevice device,
178 VkQueue graphicsQueue,
179 VkCommandPool commandPool,
180 VkImage image,
181 VkFormat format,
182 VkImageLayout oldLayout,
183 VkImageLayout newLayout,
184 uint32_t layerCount = 1
185 );
186
187 static bool hasStencilComponent( VkFormat format );
188
189 static void copyBufferToImage(
190 VkDevice device,
191 VkCommandPool commandPool,
192 VkQueue graphicsQueue,
193 VkBuffer buffer,
194 VkImage image,
195 uint32_t width,
196 uint32_t height
197 );
198
199 static VkImageView
200 createImageView( VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags );
201
202 static VkDescriptorBufferInfo fullBufferInfo( VkBuffer buffer );
203
204 static VkResult allocateDescriptorSets(
205 VkDevice device,
206 const VkDescriptorSetAllocateInfo * pAllocateInfo,
207 VkDescriptorSet * pDescriptorSets,
208 const std::string & name
209 );
210
211 static VkResult createSemaphore(
212 VkDevice device,
213 const VkSemaphoreCreateInfo * pCreateInfo,
214 const VkAllocationCallbacks * pAllocator,
215 VkSemaphore * pSemaphore,
216 const std::string & name
217 );
218
219 static VkResult allocateCommandBuffers(
220 VkDevice device,
221 const VkCommandBufferAllocateInfo * pAllocateInfo,
222 VkCommandBuffer * pCommandBuffers,
223 const std::string & name
224 );
225
227 VkDevice device,
228 const VkDescriptorSetLayoutCreateInfo * pCreateInfo,
229 const VkAllocationCallbacks * pAllocator,
230 VkDescriptorSetLayout * pSetLayout,
231 const std::string & name
232 );
233
234 static VkResult createPipelineLayout(
235 VkDevice device,
236 const VkPipelineLayoutCreateInfo * pCreateInfo,
237 const VkAllocationCallbacks * pAllocator,
238 VkPipelineLayout * pPipelineLayout,
239 const std::string & name
240 );
241
242 static void createFence(
243 VkDevice device,
244 const VkFenceCreateInfo * pCreateInfo,
245 const VkAllocationCallbacks * pAllocator,
246 VkFence * pFence,
247 const std::string & name
248 );
249
250 static VkResult createDescriptorPool(
251 VkDevice device,
252 const VkDescriptorPoolCreateInfo * pCreateInfo,
253 const VkAllocationCallbacks * pAllocator,
254 VkDescriptorPool * pDescriptorPool,
255 const std::string & name
256 );
257
258private:
259 static std::string getName( const std::string & name, const std::string & suffix );
260
261public:
262 /*static VkSampler createTextureSampler(const EngineCore::VulkanContext context);*/
263#ifdef IS_IN_DEBUG
271 static void
272 beginLabel( VkCommandBuffer commandBuffer, const char * pLabelName, const float color[4] = nullptr );
273
279 static void endLabel( VkCommandBuffer commandBuffer );
280
281private:
282 static std::unordered_map<uint64_t, std::string> objectNames;
283public:
284#else
285 // In release builds, these functions are empty and will be optimized away.
286 static void beginLabel( VkCommandBuffer, const char *, const float * ) {}
287
288 static void endLabel( VkCommandBuffer ) {}
289#endif
290
291public:
292#ifdef IS_IN_DEBUG
293
294# define VK_OBJECT_TYPE_CASE( VkType, VkEnum ) \
295 if constexpr ( std::is_same_v<VulkanObjectType, VkType> ) \
296 return VkEnum;
297
298 template <typename VulkanObjectType>
299 static constexpr VkObjectType getVulkanObjectType()
300 {
301 VK_OBJECT_TYPE_CASE( VkBuffer, VK_OBJECT_TYPE_BUFFER );
302 VK_OBJECT_TYPE_CASE( VkQueue, VK_OBJECT_TYPE_QUEUE );
303 VK_OBJECT_TYPE_CASE( VkDescriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL );
304 VK_OBJECT_TYPE_CASE( VkDescriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT );
305 VK_OBJECT_TYPE_CASE( VkDescriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET );
306 VK_OBJECT_TYPE_CASE( VkPipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT );
307 VK_OBJECT_TYPE_CASE( VkPipeline, VK_OBJECT_TYPE_PIPELINE );
308 VK_OBJECT_TYPE_CASE( VkCommandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER );
309 VK_OBJECT_TYPE_CASE( VkSemaphore, VK_OBJECT_TYPE_SEMAPHORE );
310 VK_OBJECT_TYPE_CASE( VkFence, VK_OBJECT_TYPE_FENCE );
311 VK_OBJECT_TYPE_CASE( VkImage, VK_OBJECT_TYPE_IMAGE );
312 VK_OBJECT_TYPE_CASE( VkDeviceMemory, VK_OBJECT_TYPE_DEVICE_MEMORY );
313 VK_OBJECT_TYPE_CASE( VkImageView, VK_OBJECT_TYPE_IMAGE_VIEW );
314 VK_OBJECT_TYPE_CASE( VkSampler, VK_OBJECT_TYPE_SAMPLER );
315 VK_OBJECT_TYPE_CASE( VkRenderPass, VK_OBJECT_TYPE_RENDER_PASS );
316 VK_OBJECT_TYPE_CASE( VkShaderModule, VK_OBJECT_TYPE_SHADER_MODULE );
317 VK_OBJECT_TYPE_CASE( VkCommandPool, VK_OBJECT_TYPE_COMMAND_POOL );
318
319 PLOGF << "Failed to find the type of " << typeid( VulkanObjectType ).name();
320 return VK_OBJECT_TYPE_UNKNOWN;
321 }
322
333 template <typename VulkanObjectType>
334 static void setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name );
335
336 template <typename VulkanObjectType>
337 static std::string getDebugName ( VulkanObjectType objectHandle );
338#else
339 template <typename VulkanObjectType>
340 static void setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name )
341 {
342 }
343
344 template <typename VulkanObjectType>
345 static std::string getDebugName ( VulkanObjectType objectHandle )
346 {
347 return "";
348 }
349#endif
350
351private:
354 static std::mutex s_mutex;
355};
356
357#ifdef IS_IN_DEBUG
358template <typename VulkanObjectType>
359void VulkanHelper::setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name )
360{
361 // Only proceed if the function pointer was successfully loaded
364 {
365 return;
366 }
367
368 VkDebugUtilsObjectNameInfoEXT nameInfo = {};
369 nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
370 nameInfo.objectHandle = reinterpret_cast<uint64_t>( objectHandle );
371 nameInfo.objectType = VulkanHelper::getVulkanObjectType<VulkanObjectType>();
372 nameInfo.pObjectName = name.c_str();
373
374 // Call the function
375 s_functions.vkSetDebugUtilsObjectNameEXT( device, &nameInfo );
376
377 objectNames.insert( {reinterpret_cast<uint64_t>(objectHandle), name} );
378}
379
380template <typename VulkanObjectType>
381std::string VulkanHelper::getDebugName( VulkanObjectType objectHandle )
382{
383 const auto objectHandle64 = reinterpret_cast<uint64_t>( objectHandle );
384 if (!objectNames.contains( objectHandle64 ) )
385 {
386 return "Unnamed Object";
387 }
388 return objectNames.find( objectHandle64 )->second;
389}
390#endif
391
406{
407public:
408#ifdef IS_IN_DEBUG
409 DebugLabel( VkCommandBuffer commandBuffer, const char * pLabelName, const float color[4] = nullptr )
410 : m_commandBuffer( commandBuffer )
411 {
412 VulkanHelper::beginLabel( m_commandBuffer, pLabelName, color );
413 }
414
416 {
417 VulkanHelper::endLabel( m_commandBuffer );
418 }
419#else
420 // In release builds, the constructor and destructor do nothing.
421 DebugLabel( VkCommandBuffer, const char *, const float * = nullptr ) {}
422
424#endif
425
426 // Make the class non-copyable and non-movable to prevent misuse.
427 DebugLabel( const DebugLabel & ) = delete;
428 DebugLabel & operator=( const DebugLabel & ) = delete;
429 DebugLabel( DebugLabel && ) = delete;
431
432private:
433#ifdef IS_IN_DEBUG
434 VkCommandBuffer m_commandBuffer;
435#endif
436};
DynamicFunctionInitState
@ NOT_INITIALIZED
@ DEBUG_FUNCTIONS_INITIALIZED
@ FINISHED
DebugLabel(const DebugLabel &)=delete
DebugLabel & operator=(const DebugLabel &)=delete
DebugLabel(VkCommandBuffer, const char *, const float *=nullptr)
DebugLabel(DebugLabel &&)=delete
DebugLabel & operator=(DebugLabel &&)=delete
The application context is the core class which stores the basic openxr and vulkan objects.
Stores lots of different functions which shorten the amount of code which needs to be written for def...
static VkDescriptorBufferInfo fullBufferInfo(VkBuffer buffer)
static std::string getName(const std::string &name, const std::string &suffix)
static VkResult createPipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout, const std::string &name)
static bool hasStencilComponent(VkFormat format)
static void initializeFunctions(VkInstance instance, VkDevice device)
static void loadVkDeviceFunction(VkDevice device, const std::string &name, T &functionPointer)
static std::string getDebugName(VulkanObjectType objectHandle)
static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, VkBuffer sourceBuffer, VkBuffer destinationBuffer, VkDeviceSize size)
static VkResult createSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore, const std::string &name)
static std::string strIsValid(void *object)
static DynamicFunctionInitState s_functionInitializationState
static VulkanFunctions s_functions
static const VulkanFunctions & getFunctions()
static void endLabel(VkCommandBuffer)
static VkImageView createImageView(VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
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)
static bool isValid(void *object)
static void copyBufferMultiple(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, const std::vector< BufferCopyObject > &bufferCopyObjects)
static VkDeviceSize align(VkDeviceSize value, VkDeviceSize alignment)
static VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool)
static void setObjectName(VkDevice device, VulkanObjectType objectHandle, const std::string &name)
static void loadVkFunction(VkInstance instance, const std::string &name, T &functionPointer)
static VkResult allocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets, const std::string &name)
static void recordBufferCopyMultiple(Engine::Core::ApplicationContext *context, VkCommandBuffer commandBuffer, const std::vector< BufferCopyObject > &bufferCopyObjects)
static void initializeDebugFunctions(VkInstance instance)
static void endSingleTimeCommands(VkDevice device, VkQueue graphicsQueue, VkCommandPool commandPool, VkCommandBuffer commandBuffer)
static void copyBufferToImage(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, VkBuffer buffer, VkImage image, uint32_t width, uint32_t height)
static uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties)
static void createBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
static VkResult createDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool, const std::string &name)
static void createFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence, const std::string &name)
static VkResult createDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout, const std::string &name)
static void transitionImageLayout(VkCommandBuffer commandBuffer, VkDevice device, VkQueue graphicsQueue, VkCommandPool commandPool, VkImage image, VkFormat format, VkImageLayout oldLayout, VkImageLayout newLayout, uint32_t layerCount=1)
static void cleanupBuffer(VkDevice device, VkBuffer buffer, VkDeviceMemory bufferMemory)
static void beginLabel(VkCommandBuffer, const char *, const float *)
static void uploadDataToExistingBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, VkDeviceSize size, const void *dataPtr, VkBuffer targetBuffer)
static std::mutex s_mutex
static bool findSuitableMemoryType(VkPhysicalDevice physicalDevice, VkMemoryRequirements2 requirements, VkMemoryPropertyFlags properties, uint32_t &out_typeIndex)
static VkResult allocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers, const std::string &name)
Core audio subsystem owning the miniaudio engine and managing playback.
Definition AudioConfig.h:9
VkBuffer sourceBuffer
VkDeviceSize srcOffset
VkDeviceSize size
VkDeviceSize dstOffset
Offset in source buffer (usually 0 for staging)
VkBuffer destinationBuffer
PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT
PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT
PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT
PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2
PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT
PFN_vkCmdPushConstants2 vkCmdPushConstants2
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT
PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT
PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT