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
43{
47 VkBuffer sourceBuffer = VK_NULL_HANDLE;
48
52 VkBuffer destinationBuffer = VK_NULL_HANDLE;
53
57 VkDeviceSize size = VK_WHOLE_SIZE;
58
62 VkDeviceSize srcOffset = 0;
63
67 VkDeviceSize dstOffset = 0;
68};
69
76
82{
83public:
84 static void initializeDebugFunctions(VkInstance instance);
85 static void initializeFunctions( VkInstance instance, VkDevice device );
86 static const VulkanFunctions & getFunctions();
87
88 template <typename T>
89 static void loadVkFunction( VkInstance instance, const std::string & name, T & functionPointer )
90 {
91 functionPointer = reinterpret_cast<T>( vkGetInstanceProcAddr( instance, name.c_str() ) );
92
93 if ( !functionPointer )
94 {
95 std::stringstream error;
96 error << "Vulkan INSTANCE extension function " << name << " is not supported!";
97 PLOGE << error.str();
98 throw std::runtime_error( error.str() );
99 }
100 }
101
102 template <typename T>
103 static void loadVkDeviceFunction( VkDevice device, const std::string & name, T & functionPointer )
104 {
105 functionPointer = reinterpret_cast<T>( vkGetDeviceProcAddr( device, name.c_str() ) );
106 if ( !functionPointer )
107 {
108 std::stringstream error;
109 error << "Vulkan DEVICE extension function " << name << " is not supported!";
110 PLOGE << error.str();
111 throw std::runtime_error( error.str() );
112 }
113 }
114
115 static void createBuffer(
116 VkDevice device,
117 VkPhysicalDevice physicalDevice,
118 VkDeviceSize size,
119 VkBufferUsageFlags usage,
120 VkMemoryPropertyFlags properties,
121 VkBuffer & buffer,
122 VkDeviceMemory & bufferMemory
123 );
124
126 VkDevice device,
127 VkPhysicalDevice physicalDevice,
128 VkCommandPool commandPool,
129 VkQueue queue,
130 VkDeviceSize size,
131 const void * dataPtr,
132 VkBuffer targetBuffer
133 );
134
135 static bool isValid( void * object );
136
137 static std::string strIsValid( void * object );
138
139 static uint32_t findMemoryType(
140 VkPhysicalDevice physicalDevice,
141 uint32_t typeFilter,
142 VkMemoryPropertyFlags properties
143 );
144
146 VkPhysicalDevice physicalDevice,
147 VkMemoryRequirements2 requirements,
148 VkMemoryPropertyFlags properties,
149 uint32_t & out_typeIndex
150 );
151
152 static VkDeviceSize align( VkDeviceSize value, VkDeviceSize alignment );
153
154 static void copyBuffer(
155 VkDevice device,
156 VkCommandPool commandPool,
157 VkQueue graphicsQueue,
158 VkBuffer sourceBuffer,
159 VkBuffer destinationBuffer,
160 VkDeviceSize size
161 );
162
164 VkDevice device,
165 VkCommandPool commandPool,
166 VkQueue graphicsQueue,
167 const std::vector<BufferCopyObject> & bufferCopyObjects
168 );
169
172 VkCommandBuffer commandBuffer,
173 const std::vector<BufferCopyObject> & bufferCopyObjects
174 );
175
176 static VkCommandBuffer beginSingleTimeCommands( VkDevice device, VkCommandPool commandPool );
178 VkDevice device,
179 VkQueue graphicsQueue,
180 VkCommandPool commandPool,
181 VkCommandBuffer commandBuffer
182 );
183 static void cleanupBuffer( VkDevice device, VkBuffer buffer, VkDeviceMemory bufferMemory );
184 static void createImage(
185 VkDevice device,
186 VkPhysicalDevice physicalDevice,
187 uint32_t width,
188 uint32_t height,
189 VkFormat format,
190 VkImageTiling tiling,
191 VkImageUsageFlags usage,
192 VkMemoryPropertyFlags properties,
193 VkImage & image,
194 VkDeviceMemory & imageMemory
195 );
196
198 VkCommandBuffer commandBuffer,
199 VkDevice device,
200 VkQueue graphicsQueue,
201 VkCommandPool commandPool,
202 VkImage image,
203 VkFormat format,
204 VkImageLayout oldLayout,
205 VkImageLayout newLayout,
206 uint32_t layerCount = 1
207 );
208
209 static bool hasStencilComponent( VkFormat format );
210
211 static void copyBufferToImage(
212 VkDevice device,
213 VkCommandPool commandPool,
214 VkQueue graphicsQueue,
215 VkBuffer buffer,
216 VkImage image,
217 uint32_t width,
218 uint32_t height
219 );
220
221 static VkImageView
222 createImageView( VkDevice device, VkImage image, VkFormat format, VkImageAspectFlags aspectFlags );
223
224 static VkDescriptorBufferInfo fullBufferInfo( VkBuffer buffer );
225
226 static VkResult allocateDescriptorSets(
227 VkDevice device,
228 const VkDescriptorSetAllocateInfo * pAllocateInfo,
229 VkDescriptorSet * pDescriptorSets,
230 const std::string & name
231 );
232
233 static VkResult createSemaphore(
234 VkDevice device,
235 const VkSemaphoreCreateInfo * pCreateInfo,
236 const VkAllocationCallbacks * pAllocator,
237 VkSemaphore * pSemaphore,
238 const std::string & name
239 );
240
241 static VkResult allocateCommandBuffers(
242 VkDevice device,
243 const VkCommandBufferAllocateInfo * pAllocateInfo,
244 VkCommandBuffer * pCommandBuffers,
245 const std::string & name
246 );
247
249 VkDevice device,
250 const VkDescriptorSetLayoutCreateInfo * pCreateInfo,
251 const VkAllocationCallbacks * pAllocator,
252 VkDescriptorSetLayout * pSetLayout,
253 const std::string & name
254 );
255
256 static VkResult createPipelineLayout(
257 VkDevice device,
258 const VkPipelineLayoutCreateInfo * pCreateInfo,
259 const VkAllocationCallbacks * pAllocator,
260 VkPipelineLayout * pPipelineLayout,
261 const std::string & name
262 );
263
264 static void createFence(
265 VkDevice device,
266 const VkFenceCreateInfo * pCreateInfo,
267 const VkAllocationCallbacks * pAllocator,
268 VkFence * pFence,
269 const std::string & name
270 );
271
272 static VkResult createDescriptorPool(
273 VkDevice device,
274 const VkDescriptorPoolCreateInfo * pCreateInfo,
275 const VkAllocationCallbacks * pAllocator,
276 VkDescriptorPool * pDescriptorPool,
277 const std::string & name
278 );
279
280private:
281 static std::string getName( const std::string & name, const std::string & suffix );
282
283public:
284 /*static VkSampler createTextureSampler(const EngineCore::VulkanContext context);*/
285#ifdef IS_IN_DEBUG
293 static void
294 beginLabel( VkCommandBuffer commandBuffer, const char * pLabelName, const float color[4] = nullptr );
295
301 static void endLabel( VkCommandBuffer commandBuffer );
302
303private:
304 static std::unordered_map<uint64_t, std::string> objectNames;
305public:
306#else
307 // In release builds, these functions are empty and will be optimized away.
308 static void beginLabel( VkCommandBuffer, const char *, const float * ) {}
309
310 static void endLabel( VkCommandBuffer ) {}
311#endif
312
313public:
314#ifdef IS_IN_DEBUG
315
316# define VK_OBJECT_TYPE_CASE( VkType, VkEnum ) \
317 if constexpr ( std::is_same_v<VulkanObjectType, VkType> ) \
318 return VkEnum;
319
320 template <typename VulkanObjectType>
321 static constexpr VkObjectType getVulkanObjectType()
322 {
323 VK_OBJECT_TYPE_CASE( VkBuffer, VK_OBJECT_TYPE_BUFFER );
324 VK_OBJECT_TYPE_CASE( VkQueue, VK_OBJECT_TYPE_QUEUE );
325 VK_OBJECT_TYPE_CASE( VkDescriptorPool, VK_OBJECT_TYPE_DESCRIPTOR_POOL );
326 VK_OBJECT_TYPE_CASE( VkDescriptorSetLayout, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT );
327 VK_OBJECT_TYPE_CASE( VkDescriptorSet, VK_OBJECT_TYPE_DESCRIPTOR_SET );
328 VK_OBJECT_TYPE_CASE( VkPipelineLayout, VK_OBJECT_TYPE_PIPELINE_LAYOUT );
329 VK_OBJECT_TYPE_CASE( VkPipeline, VK_OBJECT_TYPE_PIPELINE );
330 VK_OBJECT_TYPE_CASE( VkCommandBuffer, VK_OBJECT_TYPE_COMMAND_BUFFER );
331 VK_OBJECT_TYPE_CASE( VkSemaphore, VK_OBJECT_TYPE_SEMAPHORE );
332 VK_OBJECT_TYPE_CASE( VkFence, VK_OBJECT_TYPE_FENCE );
333 VK_OBJECT_TYPE_CASE( VkImage, VK_OBJECT_TYPE_IMAGE );
334 VK_OBJECT_TYPE_CASE( VkDeviceMemory, VK_OBJECT_TYPE_DEVICE_MEMORY );
335 VK_OBJECT_TYPE_CASE( VkImageView, VK_OBJECT_TYPE_IMAGE_VIEW );
336 VK_OBJECT_TYPE_CASE( VkSampler, VK_OBJECT_TYPE_SAMPLER );
337 VK_OBJECT_TYPE_CASE( VkRenderPass, VK_OBJECT_TYPE_RENDER_PASS );
338 VK_OBJECT_TYPE_CASE( VkShaderModule, VK_OBJECT_TYPE_SHADER_MODULE );
339 VK_OBJECT_TYPE_CASE( VkCommandPool, VK_OBJECT_TYPE_COMMAND_POOL );
340
341 PLOGF << "Failed to find the type of " << typeid( VulkanObjectType ).name();
342 return VK_OBJECT_TYPE_UNKNOWN;
343 }
344
355 template <typename VulkanObjectType>
356 static void setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name );
357
358 template <typename VulkanObjectType>
359 static std::string getDebugName ( VulkanObjectType objectHandle );
360#else
361 template <typename VulkanObjectType>
362 static void setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name )
363 {
364 }
365
366 template <typename VulkanObjectType>
367 static std::string getDebugName ( VulkanObjectType objectHandle )
368 {
369 return "";
370 }
371#endif
372
373private:
376 static std::mutex s_mutex;
377};
378
379#ifdef IS_IN_DEBUG
380template <typename VulkanObjectType>
381void VulkanHelper::setObjectName( VkDevice device, VulkanObjectType objectHandle, const std::string & name )
382{
383 // Only proceed if the function pointer was successfully loaded
386 {
387 return;
388 }
389
390 VkDebugUtilsObjectNameInfoEXT nameInfo = {};
391 nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
392 nameInfo.objectHandle = reinterpret_cast<uint64_t>( objectHandle );
393 nameInfo.objectType = VulkanHelper::getVulkanObjectType<VulkanObjectType>();
394 nameInfo.pObjectName = name.c_str();
395
396 // Call the function
397 s_functions.vkSetDebugUtilsObjectNameEXT( device, &nameInfo );
398
399 objectNames.insert( {reinterpret_cast<uint64_t>(objectHandle), name} );
400}
401
402template <typename VulkanObjectType>
403std::string VulkanHelper::getDebugName( VulkanObjectType objectHandle )
404{
405 const auto objectHandle64 = reinterpret_cast<uint64_t>( objectHandle );
406 if (!objectNames.contains( objectHandle64 ) )
407 {
408 return "Unnamed Object";
409 }
410 return objectNames.find( objectHandle64 )->second;
411}
412#endif
413
428{
429public:
430#ifdef IS_IN_DEBUG
431 DebugLabel( VkCommandBuffer commandBuffer, const char * pLabelName, const float color[4] = nullptr )
432 : m_commandBuffer( commandBuffer )
433 {
434 VulkanHelper::beginLabel( m_commandBuffer, pLabelName, color );
435 }
436
438 {
439 VulkanHelper::endLabel( m_commandBuffer );
440 }
441#else
442 // In release builds, the constructor and destructor do nothing.
443 DebugLabel( VkCommandBuffer, const char *, const float * = nullptr ) {}
444
446#endif
447
448 // Make the class non-copyable and non-movable to prevent misuse.
449 DebugLabel( const DebugLabel & ) = delete;
450 DebugLabel & operator=( const DebugLabel & ) = delete;
451 DebugLabel( DebugLabel && ) = delete;
453
454private:
455#ifdef IS_IN_DEBUG
456 VkCommandBuffer m_commandBuffer;
457#endif
458};
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)
Manages IBL (Image-Based Lighting) resources for specular reflections.
Description of one 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.
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