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
7
8namespace EngineCore
9{
11} // namespace EngineCore
12
14{
15 PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr;
16 PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
17 PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT = nullptr;
18 PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT = nullptr;
19 PFN_vkCmdDrawMeshTasksIndirectCountEXT vkCmdDrawMeshTasksIndirectCountEXT = nullptr;
20 PFN_vkCmdPushConstants2 vkCmdPushConstants2 = nullptr;
21 PFN_vkCmdBindDescriptorSets2 vkCmdBindDescriptorSets2 = nullptr;
22 PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT = nullptr;
23 PFN_vkCmdDrawMeshTasksIndirectEXT vkCmdDrawMeshTasksIndirectEXT = nullptr;
24 PFN_vkCmdBeginConditionalRenderingEXT vkCmdBeginConditionalRenderingEXT = nullptr;
25 PFN_vkCmdEndConditionalRenderingEXT vkCmdEndConditionalRenderingEXT = nullptr;
26#ifdef ENABLE_TRACY
27 // Tracy calibrated timestamps extension functions
28 PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT vkGetPhysicalDeviceCalibrateableTimeDomainsEXT =
29 nullptr;
30 PFN_vkGetCalibratedTimestampsEXT vkGetCalibratedTimestampsEXT = nullptr;
31 PFN_vkResetQueryPool vkResetQueryPool = nullptr;
32#endif
33};
34
36{
37 VkBuffer sourceBuffer;
39 VkDeviceSize size;
40 VkDeviceSize srcOffset = 0;
41 VkDeviceSize dstOffset = 0;
42};
43
50
56{
57public:
58 static void initializeDebugFunctions(VkInstance instance);
59 static void initializeFunctions( VkInstance instance, VkDevice device );
60 static const VulkanFunctions & getFunctions();
61
62 template <typename T>
63 static void loadVkFunction( VkInstance instance, const std::string & name, T & functionPointer )
64 {
65 functionPointer = reinterpret_cast<T>( vkGetInstanceProcAddr( instance, name.c_str() ) );
66
67 if ( !functionPointer )
68 {
69 std::stringstream error;
70 error << "Vulkan INSTANCE extension function " << name << " is not supported!";
71 PLOGE << error.str();
72 throw std::runtime_error( error.str() );
73 }
74 }
75
76 template <typename T>
77 static void loadVkDeviceFunction( VkDevice device, const std::string & name, T & functionPointer )
78 {
79 functionPointer = reinterpret_cast<T>( vkGetDeviceProcAddr( device, name.c_str() ) );
80 if ( !functionPointer )
81 {
82 std::stringstream error;
83 error << "Vulkan DEVICE extension function " << name << " is not supported!";
84 PLOGE << error.str();
85 throw std::runtime_error( error.str() );
86 }
87 }
88
92 [[deprecated("Use VulkanBuffer with VMA instead")]]
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
103 static void uploadDataToExistingBuffer(
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 void createBufferWithStaging(
118 VkDevice device,
119 VkPhysicalDevice physicalDevice,
120 VkCommandPool commandPool,
121 VkQueue queue,
122 VkDeviceSize size,
123 VkBufferUsageFlags usage,
124 const void * dataPtr,
125 VkBuffer & buffer,
126 VkDeviceMemory & bufferMemory
127 );
128
129 static void copyDataToBufferViaStaging(
130 VkDevice device,
131 VkPhysicalDevice physicalDevice,
132 VkCommandPool commandPool,
133 VkQueue queue,
134 VkDeviceSize size,
135 const void * dataPtr,
136 VkBuffer buffer,
137 VkDeviceMemory bufferMemory
138 );
139
140 static uint32_t findMemoryType(
141 VkPhysicalDevice physicalDevice,
142 uint32_t typeFilter,
143 VkMemoryPropertyFlags properties
144 );
145
146 static bool findSuitableMemoryType(
147 VkPhysicalDevice physicalDevice,
148 VkMemoryRequirements2 requirements,
149 VkMemoryPropertyFlags properties,
150 uint32_t & out_typeIndex
151 );
152
153 static VkDeviceSize align( VkDeviceSize value, VkDeviceSize alignment );
154
155 static void copyBuffer(
156 VkDevice device,
157 VkCommandPool commandPool,
158 VkQueue graphicsQueue,
159 VkBuffer sourceBuffer,
160 VkBuffer destinationBuffer,
161 VkDeviceSize size
162 );
163
164 static void copyBufferMultiple(
165 VkDevice device,
166 VkCommandPool commandPool,
167 VkQueue graphicsQueue,
168 const std::vector<BufferCopyObject> & bufferCopyObjects
169 );
170
171 static void recordBufferCopyMultiple(
173 VkCommandBuffer commandBuffer,
174 const std::vector<BufferCopyObject> & bufferCopyObjects
175 );
176
177 static VkCommandBuffer beginSingleTimeCommands( VkDevice device, VkCommandPool commandPool );
178 static void endSingleTimeCommands(
179 VkDevice device,
180 VkQueue graphicsQueue,
181 VkCommandPool commandPool,
182 VkCommandBuffer commandBuffer
183 );
184 static void cleanupBuffer( VkDevice device, VkBuffer buffer, VkDeviceMemory bufferMemory );
188 [[deprecated("Use Texture class with VMA instead")]]
189 static void createImage(
190 VkDevice device,
191 VkPhysicalDevice physicalDevice,
192 uint32_t width,
193 uint32_t height,
194 VkFormat format,
195 VkImageTiling tiling,
196 VkImageUsageFlags usage,
197 VkMemoryPropertyFlags properties,
198 VkImage & image,
199 VkDeviceMemory & imageMemory
200 );
201
202 static void transitionImageLayout(
203 VkCommandBuffer commandBuffer,
204 VkDevice device,
205 VkQueue graphicsQueue,
206 VkCommandPool commandPool,
207 VkImage image,
208 VkFormat format,
209 VkImageLayout oldLayout,
210 VkImageLayout newLayout,
211 uint32_t layerCount = 1
212 );
213
214 static bool hasStencilComponent( VkFormat format );
215
216 static void copyBufferToImage(
217 VkDevice device,
218 VkCommandPool commandPool,
219 VkQueue graphicsQueue,
220 VkBuffer buffer,
221 VkImage image,
222 uint32_t width,
223 uint32_t height
224 );
225
226 static VkImageView
227 createImageView( VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags );
228
229 static VkDescriptorBufferInfo fullBufferInfo( VkBuffer buffer );
230
231 static VkResult allocateDescriptorSets(
232 VkDevice device,
233 const VkDescriptorSetAllocateInfo * pAllocateInfo,
234 VkDescriptorSet * pDescriptorSets,
235 const std::string & name
236 );
237
238 static VkResult createSemaphore(
239 VkDevice device,
240 const VkSemaphoreCreateInfo * pCreateInfo,
241 const VkAllocationCallbacks * pAllocator,
242 VkSemaphore * pSemaphore,
243 const std::string & name
244 );
245
246 static VkResult allocateCommandBuffers(
247 VkDevice device,
248 const VkCommandBufferAllocateInfo * pAllocateInfo,
249 VkCommandBuffer * pCommandBuffers,
250 const std::string & name
251 );
252
253 static VkResult createDescriptorSetLayout(
254 VkDevice device,
255 const VkDescriptorSetLayoutCreateInfo * pCreateInfo,
256 const VkAllocationCallbacks * pAllocator,
257 VkDescriptorSetLayout * pSetLayout,
258 const std::string & name
259 );
260
261 static VkResult createPipelineLayout(
262 VkDevice device,
263 const VkPipelineLayoutCreateInfo * pCreateInfo,
264 const VkAllocationCallbacks * pAllocator,
265 VkPipelineLayout * pPipelineLayout,
266 const std::string & name
267 );
268
269 static void createFence(
270 VkDevice device,
271 const VkFenceCreateInfo * pCreateInfo,
272 const VkAllocationCallbacks * pAllocator,
273 VkFence * pFence,
274 const std::string & name
275 );
276
277 static VkResult createDescriptorPool(
278 VkDevice device,
279 const VkDescriptorPoolCreateInfo * pCreateInfo,
280 const VkAllocationCallbacks * pAllocator,
281 VkDescriptorPool * pDescriptorPool,
282 const std::string & name
283 );
284
285private:
286 static std::string getName( const std::string & name, const std::string & suffix );
287
288public:
289 /*static VkSampler createTextureSampler(const EngineCore::VulkanContext context);*/
290#ifdef IS_IN_DEBUG
298 static void
299 beginLabel( VkCommandBuffer commandBuffer, const char * pLabelName, const float color[4] = nullptr );
300
306 static void endLabel( VkCommandBuffer commandBuffer );
307
308private:
309 static std::unordered_map<uint64_t, std::string> objectNames;
310public:
311#else
312 // In release builds, these functions are empty and will be optimized away.
313 static void beginLabel( VkCommandBuffer, const char *, const float * ) {}
314
315 static void endLabel( VkCommandBuffer ) {}
316#endif
317
318public:
319#ifdef IS_IN_DEBUG
320
321# define VK_OBJECT_TYPE_CASE( VkType, VkEnum ) \
322 if constexpr ( std::is_same_v<VulkanObjectType, VkType> ) \
323 return VkEnum;
324
325 template <typename VulkanObjectType>
326 static constexpr VkObjectType getVulkanObjectType()
327 {
328 VK_OBJECT_TYPE_CASE( VkBuffer, VK_OBJECT_TYPE_BUFFER );
329 VK_OBJECT_TYPE_CASE( VkQueue, VK_OBJECT_TYPE_QUEUE );
330 VK_OBJECT_TYPE_CASE( VkDescriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL );
331 VK_OBJECT_TYPE_CASE( VkDescriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT );
332 VK_OBJECT_TYPE_CASE( VkDescriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET );
333 VK_OBJECT_TYPE_CASE( VkPipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT );
334 VK_OBJECT_TYPE_CASE( VkPipeline, VK_OBJECT_TYPE_PIPELINE );
335 VK_OBJECT_TYPE_CASE( VkCommandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER );
336 VK_OBJECT_TYPE_CASE( VkSemaphore, VK_OBJECT_TYPE_SEMAPHORE );
337 VK_OBJECT_TYPE_CASE( VkFence, VK_OBJECT_TYPE_FENCE );
338 VK_OBJECT_TYPE_CASE( VkImage, VK_OBJECT_TYPE_IMAGE );
339 VK_OBJECT_TYPE_CASE( VkDeviceMemory, VK_OBJECT_TYPE_DEVICE_MEMORY );
340 VK_OBJECT_TYPE_CASE( VkImageView, VK_OBJECT_TYPE_IMAGE_VIEW );
341 VK_OBJECT_TYPE_CASE( VkSampler, VK_OBJECT_TYPE_SAMPLER );
342 VK_OBJECT_TYPE_CASE( VkRenderPass, VK_OBJECT_TYPE_RENDER_PASS );
343 VK_OBJECT_TYPE_CASE( VkShaderModule, VK_OBJECT_TYPE_SHADER_MODULE );
344 VK_OBJECT_TYPE_CASE( VkCommandPool, VK_OBJECT_TYPE_COMMAND_POOL );
345
346 PLOGF << "Failed to find the type of " << typeid( VulkanObjectType ).name();
347 return VK_OBJECT_TYPE_UNKNOWN;
348 }
349
360 template <typename VulkanObjectType>
361 static void setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name );
362
363 template <typename VulkanObjectType>
364 static std::string getDebugName ( VulkanObjectType objectHandle );
365#else
366 template <typename VulkanObjectType>
367 static void setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name )
368 {
369 }
370
371 template <typename VulkanObjectType>
372 static std::string getDebugName ( VulkanObjectType objectHandle )
373 {
374 return "";
375 }
376#endif
377
378private:
381 static std::mutex s_mutex;
382};
383
384#ifdef IS_IN_DEBUG
385template <typename VulkanObjectType>
386void VulkanHelper::setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name )
387{
388 // Only proceed if the function pointer was successfully loaded
391 {
392 return;
393 }
394
395 VkDebugUtilsObjectNameInfoEXT nameInfo = {};
396 nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
397 nameInfo.objectHandle = reinterpret_cast<uint64_t>( objectHandle );
398 nameInfo.objectType = VulkanHelper::getVulkanObjectType<VulkanObjectType>();
399 nameInfo.pObjectName = name.c_str();
400
401 // Call the function
402 s_functions.vkSetDebugUtilsObjectNameEXT( device, &nameInfo );
403
404 objectNames.insert( {reinterpret_cast<uint64_t>(objectHandle), name} );
405}
406
407template <typename VulkanObjectType>
408std::string VulkanHelper::getDebugName( VulkanObjectType objectHandle )
409{
410 const auto objectHandle64 = reinterpret_cast<uint64_t>( objectHandle );
411 if (!objectNames.contains( objectHandle64 ) )
412 {
413 return "Unnamed Object";
414 }
415 return objectNames.find( objectHandle64 )->second;
416}
417#endif
418
433{
434public:
435#ifdef IS_IN_DEBUG
436 DebugLabel( VkCommandBuffer commandBuffer, const char * pLabelName, const float color[4] = nullptr )
437 : m_commandBuffer( commandBuffer )
438 {
439 VulkanHelper::beginLabel( m_commandBuffer, pLabelName, color );
440 }
441
443 {
444 VulkanHelper::endLabel( m_commandBuffer );
445 }
446#else
447 // In release builds, the constructor and destructor do nothing.
448 DebugLabel( VkCommandBuffer, const char *, const float * = nullptr ) {}
449
451#endif
452
453 // Make the class non-copyable and non-movable to prevent misuse.
454 DebugLabel( const DebugLabel & ) = delete;
455 DebugLabel & operator=( const DebugLabel & ) = delete;
456 DebugLabel( DebugLabel && ) = delete;
458
459private:
460#ifdef IS_IN_DEBUG
461 VkCommandBuffer m_commandBuffer;
462#endif
463};
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 VkResult createPipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout, const std::string &name)
static void createBufferWithStaging(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, VkDeviceSize size, VkBufferUsageFlags usage, const void *dataPtr, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
static void endSingleTimeCommands(VkDevice device, VkQueue graphicsQueue, VkCommandPool commandPool, VkCommandBuffer commandBuffer)
static void initializeDebugFunctions(VkInstance instance)
static VkImageView createImageView(VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags)
static void copyDataToBufferViaStaging(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, VkDeviceSize size, const void *dataPtr, VkBuffer buffer, VkDeviceMemory bufferMemory)
static VkDeviceSize align(VkDeviceSize value, VkDeviceSize alignment)
static bool findSuitableMemoryType(VkPhysicalDevice physicalDevice, VkMemoryRequirements2 requirements, VkMemoryPropertyFlags properties, uint32_t &out_typeIndex)
static void loadVkDeviceFunction(VkDevice device, const std::string &name, T &functionPointer)
static std::string strIsValid(void *object)
static std::string getDebugName(VulkanObjectType objectHandle)
static void copyBufferToImage(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, VkBuffer buffer, VkImage image, uint32_t width, uint32_t height)
static void recordBufferCopyMultiple(EngineCore::ApplicationContext *context, VkCommandBuffer commandBuffer, const std::vector< BufferCopyObject > &bufferCopyObjects)
static DynamicFunctionInitState s_functionInitializationState
static void copyBuffer(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, VkBuffer sourceBuffer, VkBuffer destinationBuffer, VkDeviceSize size)
static VulkanFunctions s_functions
static void endLabel(VkCommandBuffer)
static void createFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence, const std::string &name)
static VkResult allocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers, const std::string &name)
static VkResult createSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore, const std::string &name)
static void uploadDataToExistingBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkCommandPool commandPool, VkQueue queue, VkDeviceSize size, const void *dataPtr, VkBuffer targetBuffer)
static bool isValid(void *object)
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 setObjectName(VkDevice device, VulkanObjectType objectHandle, const std::string &name)
static void loadVkFunction(VkInstance instance, const std::string &name, T &functionPointer)
static uint32_t findMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties)
static void cleanupBuffer(VkDevice device, VkBuffer buffer, VkDeviceMemory bufferMemory)
static bool hasStencilComponent(VkFormat format)
static VkResult allocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets, const std::string &name)
static VkDescriptorBufferInfo fullBufferInfo(VkBuffer buffer)
static VkResult createDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool, const std::string &name)
static std::string getName(const std::string &name, const std::string &suffix)
static void initializeFunctions(VkInstance instance, VkDevice device)
static const VulkanFunctions & getFunctions()
static void createBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory)
static void beginLabel(VkCommandBuffer, const char *, const float *)
static std::mutex s_mutex
static VkResult createDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout, const std::string &name)
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 void copyBufferMultiple(VkDevice device, VkCommandPool commandPool, VkQueue graphicsQueue, const std::vector< BufferCopyObject > &bufferCopyObjects)
static VkCommandBuffer beginSingleTimeCommands(VkDevice device, VkCommandPool commandPool)
Log category system implementation.
VkBuffer sourceBuffer
VkDeviceSize srcOffset
Offset in source buffer (usually 0 for staging)
VkDeviceSize size
VkDeviceSize dstOffset
Offset in destination buffer (for partial uploads)
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