PeriDyno 1.0.0
Loading...
Searching...
No Matches
VkContext.cpp
Go to the documentation of this file.
1#include "VkContext.h"
2
3#define VMA_IMPLEMENTATION
4#include "VulkanMemoryAllocator/include/vk_mem_alloc.h"
5
6namespace dyno {
13 {
15 this->physicalDevice = physicalDevice;
16
17 // Store Properties features, limits and properties of the physical device for later use
18 // Device properties also contain limits and sparse properties
19 vkGetPhysicalDeviceProperties(physicalDevice, &properties);
20 // Features should be checked by the examples before using them
21 vkGetPhysicalDeviceFeatures(physicalDevice, &features);
22 // Memory properties are used regularly for creating all kinds of buffers
23 vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memoryProperties);
24 // Queue family properties, used for setting up requested queues upon device creation
25 uint32_t queueFamilyCount;
27 assert(queueFamilyCount > 0);
28 queueFamilyProperties.resize(queueFamilyCount);
30
31 // Get list of supported extensions
32 uint32_t extCount = 0;
33 vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extCount, nullptr);
34 if (extCount > 0)
35 {
36 std::vector<VkExtensionProperties> extensions(extCount);
37 if (vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extCount, &extensions.front()) == VK_SUCCESS)
38 {
39 for (auto ext : extensions)
40 {
41 supportedExtensions.push_back(ext.extensionName);
42 }
43 }
44 }
45 }
46
53 {
54 for (const auto &pool : poolMap)
55 {
56 vmaDestroyPool(g_Allocator, pool.second.pool);
57 }
58 vmaDestroyAllocator(g_Allocator);
59
60 if (commandPool)
61 {
62 vkDestroyCommandPool(logicalDevice, commandPool, nullptr);
63 }
64 if (logicalDevice)
65 {
66 vkDestroyDevice(logicalDevice, nullptr);
67 }
68 }
69
70
72 {
73 return this->queueFamilyIndices.graphics != this->queueFamilyIndices.compute;
74 }
75
87 uint32_t VkContext::getMemoryType(uint32_t typeBits, VkMemoryPropertyFlags properties, VkBool32 *memTypeFound) const
88 {
89 for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++)
90 {
91 if ((typeBits & 1) == 1)
92 {
93 if ((memoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
94 {
95 if (memTypeFound)
96 {
97 *memTypeFound = true;
98 }
99 return i;
100 }
101 }
102 typeBits >>= 1;
103 }
104
105 if (memTypeFound)
106 {
107 *memTypeFound = false;
108 return 0;
109 }
110 else
111 {
112 throw std::runtime_error("Could not find a matching memory type");
113 }
114 }
115
125 uint32_t VkContext::getQueueFamilyIndex(VkQueueFlagBits queueFlags) const
126 {
127 // Dedicated queue for compute
128 // Try to find a queue family index that supports compute but not graphics
129 if (queueFlags & VK_QUEUE_COMPUTE_BIT)
130 {
131 for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilyProperties.size()); i++)
132 {
133 if ((queueFamilyProperties[i].queueFlags & queueFlags) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0))
134 {
135 return i;
136 }
137 }
138 }
139
140 // Dedicated queue for transfer
141 // Try to find a queue family index that supports transfer but not graphics and compute
142 if (queueFlags & VK_QUEUE_TRANSFER_BIT)
143 {
144 for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilyProperties.size()); i++)
145 {
146 if ((queueFamilyProperties[i].queueFlags & queueFlags) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0) && ((queueFamilyProperties[i].queueFlags & VK_QUEUE_COMPUTE_BIT) == 0))
147 {
148 return i;
149 }
150 }
151 }
152
153 // For other queue types or if no separate compute queue is present, return the first one to support the requested flags
154 for (uint32_t i = 0; i < static_cast<uint32_t>(queueFamilyProperties.size()); i++)
155 {
156 if (queueFamilyProperties[i].queueFlags & queueFlags)
157 {
158 return i;
159 }
160 }
161
162 throw std::runtime_error("Could not find a matching queue family index");
163 }
164
175 VkResult VkContext::createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, std::vector<const char*> enabledExtensions, void* pNextChain, bool useSwapChain, VkQueueFlags requestedQueueTypes)
176 {
177 // Desired queues need to be requested upon logical device creation
178 // Due to differing queue family configurations of Vulkan implementations this can be a bit tricky, especially if the application
179 // requests different queue types
180
181 std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
182
183 // Get queue family indices for the requested queue family types
184 // Note that the indices may overlap depending on the implementation
185
186 const float defaultQueuePriority(0.0f);
187
188 // Graphics queue
189 if (requestedQueueTypes & VK_QUEUE_GRAPHICS_BIT)
190 {
191 queueFamilyIndices.graphics = getQueueFamilyIndex(VK_QUEUE_GRAPHICS_BIT);
192 VkDeviceQueueCreateInfo queueInfo{};
193 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
194 queueInfo.queueFamilyIndex = queueFamilyIndices.graphics;
195 queueInfo.queueCount = 1;
196 queueInfo.pQueuePriorities = &defaultQueuePriority;
197 queueCreateInfos.push_back(queueInfo);
198 }
199 else
200 {
201 queueFamilyIndices.graphics = VK_NULL_HANDLE;
202 }
203
204 // Dedicated compute queue
205 if (requestedQueueTypes & VK_QUEUE_COMPUTE_BIT)
206 {
207 queueFamilyIndices.compute = getQueueFamilyIndex(VK_QUEUE_COMPUTE_BIT);
208 if (queueFamilyIndices.compute != queueFamilyIndices.graphics)
209 {
210 // If compute family index differs, we need an additional queue create info for the compute queue
211 VkDeviceQueueCreateInfo queueInfo{};
212 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
213 queueInfo.queueFamilyIndex = queueFamilyIndices.compute;
214 queueInfo.queueCount = 1;
215 queueInfo.pQueuePriorities = &defaultQueuePriority;
216 queueCreateInfos.push_back(queueInfo);
217 }
218 }
219 else
220 {
221 // Else we use the same queue
222 queueFamilyIndices.compute = queueFamilyIndices.graphics;
223 }
224
225 // Dedicated transfer queue
226 if (requestedQueueTypes & VK_QUEUE_TRANSFER_BIT)
227 {
228 queueFamilyIndices.transfer = getQueueFamilyIndex(VK_QUEUE_TRANSFER_BIT);
229 if ((queueFamilyIndices.transfer != queueFamilyIndices.graphics) && (queueFamilyIndices.transfer != queueFamilyIndices.compute))
230 {
231 // If compute family index differs, we need an additional queue create info for the compute queue
232 VkDeviceQueueCreateInfo queueInfo{};
233 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
234 queueInfo.queueFamilyIndex = queueFamilyIndices.transfer;
235 queueInfo.queueCount = 1;
236 queueInfo.pQueuePriorities = &defaultQueuePriority;
237 queueCreateInfos.push_back(queueInfo);
238 }
239 }
240 else
241 {
242 // Else we use the same queue
243 queueFamilyIndices.transfer = queueFamilyIndices.graphics;
244 }
245
246 // Create the logical device representation
247 std::vector<const char*> deviceExtensions(enabledExtensions);
248 if (useSwapChain)
249 {
250 // If the device will be used for presenting to a display via a swapchain we need to request the swapchain extension
251 deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
252 }
253
254 VkDeviceCreateInfo deviceCreateInfo = {};
255 deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
256 deviceCreateInfo.queueCreateInfoCount = static_cast<uint32_t>(queueCreateInfos.size());;
257 deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
258 deviceCreateInfo.pEnabledFeatures = &enabledFeatures;
259
260 VkPhysicalDeviceShaderAtomicFloatFeaturesEXT physicalDeviceShaderAtomicFloatFeaturesEXT{};
261 physicalDeviceShaderAtomicFloatFeaturesEXT.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_ATOMIC_FLOAT_FEATURES_EXT;
262 physicalDeviceShaderAtomicFloatFeaturesEXT.shaderBufferFloat32AtomicAdd = true;
263 deviceCreateInfo.pNext = &physicalDeviceShaderAtomicFloatFeaturesEXT;
264
265 // If a pNext(Chain) has been passed, we need to add it to the device creation info
266 VkPhysicalDeviceFeatures2 physicalDeviceFeatures2{};
267 if (pNextChain) {
268 physicalDeviceFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
269 physicalDeviceFeatures2.features = enabledFeatures;
270 physicalDeviceFeatures2.pNext = pNextChain;
271 deviceCreateInfo.pEnabledFeatures = nullptr;
272 deviceCreateInfo.pNext = &physicalDeviceFeatures2;
273 }
274
275 // Enable the debug marker extension if it is present (likely meaning a debugging tool is present)
276 if (extensionSupported(VK_EXT_DEBUG_MARKER_EXTENSION_NAME))
277 {
278 deviceExtensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
279 enableDebugMarkers = true;
280 }
281
282 if (extensionSupported(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME)) {
283 deviceExtensions.push_back(VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME);
284 }
285
286 if (extensionSupported(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME)) {
287 deviceExtensions.push_back(VK_EXT_SHADER_ATOMIC_FLOAT_EXTENSION_NAME);
288 }
289
290 if (deviceExtensions.size() > 0)
291 {
292 for (const char* enabledExtension : deviceExtensions)
293 {
294 if (!extensionSupported(enabledExtension)) {
295 std::cerr << "Enabled device extension \"" << enabledExtension << "\" is not present at device level\n";
296 }
297 }
298
299 deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size();
300 deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
301 }
302
303 this->enabledFeatures = enabledFeatures;
304
305 VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &logicalDevice);
306 if (result != VK_SUCCESS)
307 {
308 return result;
309 }
310
311 // Create a default command pool for graphics command buffers
313
314 // Get a graphics queue from the device
315 vkGetDeviceQueue(logicalDevice, this->queueFamilyIndices.graphics, 0, &graphicsQueue);
316
317 vkGetDeviceQueue(logicalDevice, this->queueFamilyIndices.compute, 0, &computeQueue);
318
319 vkGetDeviceQueue(logicalDevice, this->queueFamilyIndices.transfer, 0, &transferQueue);
320
322
323 return result;
324 }
325
326
328 {
329 VkPipelineCacheCreateInfo pipelineCacheCreateInfo = {};
330 pipelineCacheCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
331 VK_CHECK_RESULT(vkCreatePipelineCache(logicalDevice, &pipelineCacheCreateInfo, nullptr, &pipelineCache));
332 }
333
346 VkResult VkContext::createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, VkBuffer *buffer, VkDeviceMemory *memory, void *data)
347 {
348 // Create the buffer handle
349 VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(usageFlags, size);
350 bufferCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
351 VK_CHECK_RESULT(vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, buffer));
352
353 // Create the memory backing up the buffer handle
354 VkMemoryRequirements memReqs;
355 VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo();
356 vkGetBufferMemoryRequirements(logicalDevice, *buffer, &memReqs);
357 memAlloc.allocationSize = memReqs.size;
358 // Find a memory type index that fits the properties of the buffer
359 memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags);
360 // If the buffer has VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT set we also need to enable the appropriate flag during allocation
361 VkMemoryAllocateFlagsInfoKHR allocFlagsInfo{};
362 if (usageFlags & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
363 allocFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR;
364 allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
365 memAlloc.pNext = &allocFlagsInfo;
366 }
367 VK_CHECK_RESULT(vkAllocateMemory(logicalDevice, &memAlloc, nullptr, memory));
368
369 // If a pointer to the buffer data has been passed, map the buffer and copy over the data
370 if (data != nullptr)
371 {
372 void *mapped;
373 VK_CHECK_RESULT(vkMapMemory(logicalDevice, *memory, 0, size, 0, &mapped));
374 memcpy(mapped, data, size);
375 // If host coherency hasn't been requested, do a manual flush to make writes visible
376 if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
377 {
378 VkMappedMemoryRange mappedRange = vks::initializers::mappedMemoryRange();
379 mappedRange.memory = *memory;
380 mappedRange.offset = 0;
381 mappedRange.size = size;
382 vkFlushMappedMemoryRanges(logicalDevice, 1, &mappedRange);
383 }
384 vkUnmapMemory(logicalDevice, *memory);
385 }
386
387 // Attach the memory to the buffer object
388 VK_CHECK_RESULT(vkBindBufferMemory(logicalDevice, *buffer, *memory, 0));
389
390 return VK_SUCCESS;
391 }
392
404 VkResult VkContext::createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, std::shared_ptr<vks::Buffer> &buffer, VkDeviceSize size, const void *data)
405 {
406 buffer->device = logicalDevice;
407
408 // Create the buffer handle
409 VkBufferCreateInfo bufferCreateInfo = vks::initializers::bufferCreateInfo(usageFlags, size);
410 VK_CHECK_RESULT(vkCreateBuffer(logicalDevice, &bufferCreateInfo, nullptr, &buffer->buffer));
411
412 // Create the memory backing up the buffer handle
413 VkMemoryRequirements memReqs;
414 VkMemoryAllocateInfo memAlloc = vks::initializers::memoryAllocateInfo();
415 vkGetBufferMemoryRequirements(logicalDevice, buffer->buffer, &memReqs);
416 memAlloc.allocationSize = memReqs.size;
417 // Find a memory type index that fits the properties of the buffer
418 memAlloc.memoryTypeIndex = getMemoryType(memReqs.memoryTypeBits, memoryPropertyFlags);
419 // If the buffer has VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT set we also need to enable the appropriate flag during allocation
420 VkMemoryAllocateFlagsInfoKHR allocFlagsInfo{};
421 if (usageFlags & VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT) {
422 allocFlagsInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO_KHR;
423 allocFlagsInfo.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT_KHR;
424 memAlloc.pNext = &allocFlagsInfo;
425 }
426 VK_CHECK_RESULT(vkAllocateMemory(logicalDevice, &memAlloc, nullptr, &buffer->memory));
427
428 buffer->usePool = VK_FALSE;
429 buffer->alignment = memReqs.alignment;
430 buffer->size = size;
431 buffer->usageFlags = usageFlags;
432 buffer->memoryPropertyFlags = memoryPropertyFlags;
433
434 // If a pointer to the buffer data has been passed, map the buffer and copy over the data
435 if (data != nullptr)
436 {
437 VK_CHECK_RESULT(buffer->map());
438 memcpy(buffer->mapped, data, size);
439 if ((memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0)
440 buffer->flush();
441
442 buffer->unmap();
443 }
444
445 // Initialize a default descriptor that covers the whole buffer size
446 buffer->setupDescriptor();
447
448 // Attach the memory to the buffer object
449 return buffer->bind();
450 }
451
461 VkResult VkContext::createBuffer(uint32_t poolType, std::shared_ptr<vks::Buffer> &buffer, const void *data)
462 {
463 VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
464 bufferCreateInfo.size = buffer->size;
465 bufferCreateInfo.usage = buffer->usageFlags;
466
467 VmaAllocationCreateInfo allocationCreateInfo = {};
468 allocationCreateInfo.usage = static_cast<VmaMemoryUsage>(poolMap[poolType].usage);
469 allocationCreateInfo.pool = poolMap[poolType].pool;
470
471 VmaAllocationInfo allocationInfo;
472 VkResult ret = vmaCreateBuffer(g_Allocator, &bufferCreateInfo, &allocationCreateInfo, &buffer->buffer, &buffer->allocation, &allocationInfo);
473 VK_CHECK_RESULT(ret);
474
475 buffer->usePool = VK_TRUE;
476 buffer->memory = allocationInfo.deviceMemory;
477 buffer->offset = allocationInfo.offset;
478 buffer->allocator = g_Allocator;
479 buffer->device = deviceHandle();
480
481 if (data != nullptr) {
482 ret = vmaMapMemory(buffer->allocator, buffer->allocation, (void**)&buffer->mapped);
483 VK_CHECK_RESULT(ret);
484 memcpy(buffer->mapped, data, buffer->size);
485
486 if ((buffer->memoryPropertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) == 0) {
487 vmaFlushAllocation(buffer->allocator, buffer->allocation, allocationInfo.offset, allocationInfo.size);
488 }
489 vmaUnmapMemory(buffer->allocator, buffer->allocation);
490 buffer->mapped = nullptr;
491 }
492 buffer->setupDescriptor();
493 return VK_SUCCESS;
494 }
495
504 VkResult VkContext::createMemoryPool(VkInstance instance, uint32_t apiVerion)
505 {
506 useMemoryPool = false;
507 VmaAllocatorCreateInfo allocatorInfo = {};
508 allocatorInfo.vulkanApiVersion = apiVerion;
509 allocatorInfo.physicalDevice = physicalDeviceHandle();
510 allocatorInfo.device = deviceHandle();
511 allocatorInfo.instance = instance;
512 vmaCreateAllocator(&allocatorInfo, &g_Allocator);
513
514 VmaPoolCreateInfo poolCreateInfo = {};
515 poolCreateInfo.blockSize = 20 * 1024 * 1024; // 20M
516 poolCreateInfo.minBlockCount = 1;
517 poolCreateInfo.maxBlockCount = 2;
518
519 VmaAllocationCreateInfo allocationCreateInfo = {};
520 VkBufferCreateInfo bufferCreateInfo = { VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO };
521 bufferCreateInfo.size = 1024;
522
523 MemoryPoolInfo memoryPoolInfo = {};
524 for (uint32_t type = DevicePool; type < EndType; ++type) {
525 switch (type) {
526 case DevicePool: {
527 // Device memory pool
528 allocationCreateInfo.usage = VMA_MEMORY_USAGE_GPU_ONLY;
529 allocationCreateInfo.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
530 bufferCreateInfo.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
531 VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT |
532 VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
533 break;
534 }
535 case HostPool: {
536 // Host memory pool
537 allocationCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
538 allocationCreateInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
539 bufferCreateInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
540 break;
541 }
542 case UniformPool: {
543 // Uniform memory pool
544 allocationCreateInfo.usage = VMA_MEMORY_USAGE_CPU_ONLY;
545 allocationCreateInfo.requiredFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
546 bufferCreateInfo.usage = VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
547 break;
548 }
549 default:
550 break;
551 }
552
553 memoryPoolInfo.usage = allocationCreateInfo.usage;
554 vmaFindMemoryTypeIndexForBufferInfo(g_Allocator, &bufferCreateInfo, &allocationCreateInfo, &poolCreateInfo.memoryTypeIndex);
555 VkResult res = vmaCreatePool(g_Allocator, &poolCreateInfo, &memoryPoolInfo.pool);
556 if (res != VK_SUCCESS) {
557 vks::tools::exitFatal("Could not create memory pool : \n" + vks::tools::errorString(res), res);
558 return res;
559 }
560 poolMap[type] = memoryPoolInfo;
561 }
562
563 return VK_SUCCESS;
564 }
565
576 void VkContext::copyBuffer(vks::Buffer *src, vks::Buffer *dst, VkQueue queue, VkBufferCopy *copyRegion)
577 {
578 assert(dst->size <= src->size);
579 assert(src->buffer);
580 VkCommandBuffer copyCmd = createCommandBuffer(VK_COMMAND_BUFFER_LEVEL_PRIMARY, true);
581 VkBufferCopy bufferCopy{};
582 if (copyRegion == nullptr)
583 {
584 bufferCopy.size = src->size;
585 }
586 else
587 {
588 bufferCopy = *copyRegion;
589 }
590
591 vkCmdCopyBuffer(copyCmd, src->buffer, dst->buffer, 1, &bufferCopy);
592
593 flushCommandBuffer(copyCmd, queue);
594 }
595
606 VkCommandPool VkContext::createCommandPool(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags createFlags)
607 {
608 VkCommandPoolCreateInfo cmdPoolInfo = {};
609 cmdPoolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
610 cmdPoolInfo.queueFamilyIndex = queueFamilyIndex;
611 cmdPoolInfo.flags = createFlags;
612 VkCommandPool cmdPool;
613 VK_CHECK_RESULT(vkCreateCommandPool(logicalDevice, &cmdPoolInfo, nullptr, &cmdPool));
614 return cmdPool;
615 }
616
626 VkCommandBuffer VkContext::createCommandBuffer(VkCommandBufferLevel level, VkCommandPool pool, bool begin)
627 {
628 VkCommandBufferAllocateInfo cmdBufAllocateInfo = vks::initializers::commandBufferAllocateInfo(pool, level, 1);
629 VkCommandBuffer cmdBuffer;
630 VK_CHECK_RESULT(vkAllocateCommandBuffers(logicalDevice, &cmdBufAllocateInfo, &cmdBuffer));
631 // If requested, also start recording for the new command buffer
632 if (begin)
633 {
634 VkCommandBufferBeginInfo cmdBufInfo = vks::initializers::commandBufferBeginInfo();
635 VK_CHECK_RESULT(vkBeginCommandBuffer(cmdBuffer, &cmdBufInfo));
636 }
637 return cmdBuffer;
638 }
639
640 VkCommandBuffer VkContext::createCommandBuffer(VkCommandBufferLevel level, bool begin)
641 {
642 return createCommandBuffer(level, commandPool, begin);
643 }
644
656 void VkContext::flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, VkCommandPool pool, bool free)
657 {
658 if (commandBuffer == VK_NULL_HANDLE)
659 {
660 return;
661 }
662
663 VK_CHECK_RESULT(vkEndCommandBuffer(commandBuffer));
664
665 VkSubmitInfo submitInfo = vks::initializers::submitInfo();
666 submitInfo.commandBufferCount = 1;
667 submitInfo.pCommandBuffers = &commandBuffer;
668 // Create fence to ensure that the command buffer has finished executing
669 VkFenceCreateInfo fenceInfo = vks::initializers::fenceCreateInfo(VK_FLAGS_NONE);
670 VkFence fence;
671 VK_CHECK_RESULT(vkCreateFence(logicalDevice, &fenceInfo, nullptr, &fence));
672 // Submit to the queue
673 VK_CHECK_RESULT(vkQueueSubmit(queue, 1, &submitInfo, fence));
674 // Wait for the fence to signal that command buffer has finished executing
675 VK_CHECK_RESULT(vkWaitForFences(logicalDevice, 1, &fence, VK_TRUE, DEFAULT_FENCE_TIMEOUT));
676 vkDestroyFence(logicalDevice, fence, nullptr);
677 if (free)
678 {
679 vkFreeCommandBuffers(logicalDevice, pool, 1, &commandBuffer);
680 }
681 }
682
683 void VkContext::flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, bool free)
684 {
685 return flushCommandBuffer(commandBuffer, queue, commandPool, free);
686 }
687
695 bool VkContext::extensionSupported(std::string extension)
696 {
697 return (std::find(supportedExtensions.begin(), supportedExtensions.end(), extension) != supportedExtensions.end());
698 }
699
709 VkFormat VkContext::getSupportedDepthFormat(bool checkSamplingSupport)
710 {
711 // All depth formats may be optional, so we need to find a suitable depth format to use
712 std::vector<VkFormat> depthFormats = { VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_D32_SFLOAT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D16_UNORM };
713 for (auto& format : depthFormats)
714 {
715 VkFormatProperties formatProperties;
716 vkGetPhysicalDeviceFormatProperties(physicalDevice, format, &formatProperties);
717 // Format must support depth stencil attachment for optimal tiling
718 if (formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
719 {
720 if (checkSamplingSupport) {
721 if (!(formatProperties.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
722 continue;
723 }
724 }
725 return format;
726 }
727 }
728 throw std::runtime_error("Could not find a matching depth format");
729 }
730}
assert(queueCount >=1)
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL)
#define DEFAULT_FENCE_TIMEOUT
Definition VulkanTools.h:41
#define VK_CHECK_RESULT(f)
Definition VulkanTools.h:55
#define VK_FLAGS_NONE
Definition VulkanTools.h:39
VkResult createBuffer(VkBufferUsageFlags usageFlags, VkMemoryPropertyFlags memoryPropertyFlags, VkDeviceSize size, VkBuffer *buffer, VkDeviceMemory *memory, void *data=nullptr)
VkCommandPool commandPool
Default command pool for the graphics queue family index.
Definition VkContext.h:71
bool extensionSupported(std::string extension)
std::vector< std::string > supportedExtensions
List of extensions supported by the device.
Definition VkContext.h:69
VkQueue computeQueue
Definition VkContext.h:74
uint32_t getQueueFamilyIndex(VkQueueFlagBits queueFlags) const
void flushCommandBuffer(VkCommandBuffer commandBuffer, VkQueue queue, VkCommandPool pool, bool free=true)
VkCommandBuffer createCommandBuffer(VkCommandBufferLevel level, VkCommandPool pool, bool begin=false)
VkPhysicalDeviceFeatures features
Features of the physical device that an application can use to check if a feature is supported.
Definition VkContext.h:61
VkContext(VkPhysicalDevice physicalDevice)
Definition VkContext.cpp:12
VkPhysicalDevice physicalDeviceHandle()
Definition VkContext.h:31
struct dyno::VkContext::@247250360024255345354242335264053265034214002126 queueFamilyIndices
VkResult createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, std::vector< const char * > enabledExtensions, void *pNextChain, bool useSwapChain=true, VkQueueFlags requestedQueueTypes=VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT)
bool enableDebugMarkers
Set to true when the debug marker extension is detected.
Definition VkContext.h:77
VkCommandPool createCommandPool(uint32_t queueFamilyIndex, VkCommandPoolCreateFlags createFlags=VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT)
VkQueue graphicsQueue
Definition VkContext.h:73
uint32_t getMemoryType(uint32_t typeBits, VkMemoryPropertyFlags properties, VkBool32 *memTypeFound=nullptr) const
Definition VkContext.cpp:87
void copyBuffer(vks::Buffer *src, vks::Buffer *dst, VkQueue queue, VkBufferCopy *copyRegion=nullptr)
VkPhysicalDevice physicalDevice
Physical device representation.
Definition VkContext.h:55
VkQueue transferQueue
Definition VkContext.h:75
VkResult createMemoryPool(VkInstance instance, uint32_t apiVerion)
VkPipelineCache pipelineCache
Contains queue family indices.
Definition VkContext.h:81
VkPhysicalDeviceMemoryProperties memoryProperties
Memory types and heaps of the physical device.
Definition VkContext.h:65
bool isComputeQueueSpecial()
Definition VkContext.cpp:71
VkPhysicalDeviceProperties properties
Properties of the physical device including limits that the application can check against.
Definition VkContext.h:59
VkPhysicalDeviceFeatures enabledFeatures
Features that have been enabled for use on the physical device.
Definition VkContext.h:63
VmaAllocator g_Allocator
Definition VkContext.h:109
void createPipelineCache()
std::vector< VkQueueFamilyProperties > queueFamilyProperties
Queue family properties of the physical device.
Definition VkContext.h:67
std::map< VkFlags, MemoryPoolInfo > poolMap
Definition VkContext.h:108
VkFormat getSupportedDepthFormat(bool checkSamplingSupport)
VkDevice deviceHandle()
Definition VkContext.h:26
VkDevice logicalDevice
Logical device representation (application's view of the device)
Definition VkContext.h:57
Encapsulates access to a Vulkan buffer backed up by device memory.
VkDeviceSize size
VkBuffer buffer
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
VkCommandBufferAllocateInfo commandBufferAllocateInfo(VkCommandPool commandPool, VkCommandBufferLevel level, uint32_t bufferCount)
VkFenceCreateInfo fenceCreateInfo(VkFenceCreateFlags flags=0)
VkMemoryAllocateInfo memoryAllocateInfo()
VkCommandBufferBeginInfo commandBufferBeginInfo()
VkBufferCreateInfo bufferCreateInfo()
VkMappedMemoryRange mappedMemoryRange()
std::string errorString(VkResult errorCode)
Returns an error code as a string.
void exitFatal(const std::string &message, int32_t exitCode)