vkdoom_m/libraries/ZVulkan/src/vulkandevice.cpp
Magnus Norddahl 4bbc88d358 Updates ZVulkan to latest version.
Also changes vsync off from mailbox to immediate since otherwise it doesn't work in exclusive full screen mode.
And finally it fixes a scratch buffer alignment bug with the vk raytrace thing
2023-03-16 23:00:56 +01:00

161 lines
5 KiB
C++

#include "vulkandevice.h"
#include "vulkanobjects.h"
#include "vulkancompatibledevice.h"
#include <algorithm>
#include <set>
#include <string>
VulkanDevice::VulkanDevice(std::shared_ptr<VulkanInstance> instance, std::shared_ptr<VulkanSurface> surface, const VulkanCompatibleDevice& selectedDevice) : Instance(instance), Surface(surface)
{
PhysicalDevice = *selectedDevice.Device;
EnabledDeviceExtensions = selectedDevice.EnabledDeviceExtensions;
EnabledFeatures = selectedDevice.EnabledFeatures;
GraphicsFamily = selectedDevice.GraphicsFamily;
PresentFamily = selectedDevice.PresentFamily;
GraphicsTimeQueries = selectedDevice.GraphicsTimeQueries;
try
{
CreateDevice();
CreateAllocator();
}
catch (...)
{
ReleaseResources();
throw;
}
}
VulkanDevice::~VulkanDevice()
{
ReleaseResources();
}
bool VulkanDevice::SupportsExtension(const char* ext) const
{
return
EnabledDeviceExtensions.find(ext) != EnabledDeviceExtensions.end() ||
Instance->EnabledExtensions.find(ext) != Instance->EnabledExtensions.end();
}
void VulkanDevice::CreateAllocator()
{
VmaAllocatorCreateInfo allocinfo = {};
allocinfo.vulkanApiVersion = Instance->ApiVersion;
if (SupportsExtension(VK_KHR_DEDICATED_ALLOCATION_EXTENSION_NAME) && SupportsExtension(VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME))
allocinfo.flags |= VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT;
if (SupportsExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
allocinfo.flags |= VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
allocinfo.physicalDevice = PhysicalDevice.Device;
allocinfo.device = device;
allocinfo.instance = Instance->Instance;
allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024;
if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS)
VulkanError("Unable to create allocator");
}
void VulkanDevice::CreateDevice()
{
float queuePriority = 1.0f;
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
std::set<int> neededFamilies;
if (GraphicsFamily != -1)
neededFamilies.insert(GraphicsFamily);
if (PresentFamily != -1)
neededFamilies.insert(PresentFamily);
for (int index : neededFamilies)
{
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = index;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
queueCreateInfos.push_back(queueCreateInfo);
}
std::vector<const char*> extensionNames;
extensionNames.reserve(EnabledDeviceExtensions.size());
for (const auto& name : EnabledDeviceExtensions)
extensionNames.push_back(name.c_str());
VkDeviceCreateInfo deviceCreateInfo = { VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO };
deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
deviceCreateInfo.enabledExtensionCount = (uint32_t)extensionNames.size();
deviceCreateInfo.ppEnabledExtensionNames = extensionNames.data();
deviceCreateInfo.enabledLayerCount = 0;
VkPhysicalDeviceFeatures2 deviceFeatures2 = { VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2 };
deviceFeatures2.features = EnabledFeatures.Features;
void** next = const_cast<void**>(&deviceCreateInfo.pNext);
if (SupportsExtension(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME))
{
*next = &deviceFeatures2;
next = &deviceFeatures2.pNext;
}
else // vulkan 1.0 specified features in a different way
{
deviceCreateInfo.pEnabledFeatures = &deviceFeatures2.features;
}
if (SupportsExtension(VK_KHR_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME))
{
*next = &EnabledFeatures.BufferDeviceAddress;
next = &EnabledFeatures.BufferDeviceAddress.pNext;
}
if (SupportsExtension(VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME))
{
*next = &EnabledFeatures.AccelerationStructure;
next = &EnabledFeatures.AccelerationStructure.pNext;
}
if (SupportsExtension(VK_KHR_RAY_QUERY_EXTENSION_NAME))
{
*next = &EnabledFeatures.RayQuery;
next = &EnabledFeatures.RayQuery.pNext;
}
if (SupportsExtension(VK_EXT_DESCRIPTOR_INDEXING_EXTENSION_NAME))
{
*next = &EnabledFeatures.DescriptorIndexing;
next = &EnabledFeatures.DescriptorIndexing.pNext;
}
VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device);
CheckVulkanError(result, "Could not create vulkan device");
volkLoadDevice(device);
if (GraphicsFamily != -1)
vkGetDeviceQueue(device, GraphicsFamily, 0, &GraphicsQueue);
if (PresentFamily != -1)
vkGetDeviceQueue(device, PresentFamily, 0, &PresentQueue);
}
void VulkanDevice::ReleaseResources()
{
if (device)
vkDeviceWaitIdle(device);
if (allocator)
vmaDestroyAllocator(allocator);
if (device)
vkDestroyDevice(device, nullptr);
device = nullptr;
}
void VulkanDevice::SetObjectName(const char* name, uint64_t handle, VkObjectType type)
{
if (!DebugLayerActive) return;
VkDebugUtilsObjectNameInfoEXT info = {};
info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
info.objectHandle = handle;
info.objectType = type;
info.pObjectName = name;
vkSetDebugUtilsObjectNameEXT(device, &info);
}