mirror of
https://github.com/ZDoom/qzdoom.git
synced 2024-11-24 21:11:39 +00:00
- add vk_device and vk_listdevices that will allow selecting a different device on systems where this is desirable
- clean up the VulkanDevice class
This commit is contained in:
parent
389469c604
commit
21c83950a5
6 changed files with 387 additions and 301 deletions
|
@ -18,7 +18,7 @@ VkRenderBuffers::~VkRenderBuffers()
|
|||
VkSampleCountFlagBits VkRenderBuffers::GetBestSampleCount()
|
||||
{
|
||||
auto fb = GetVulkanFrameBuffer();
|
||||
const auto &limits = fb->device->deviceProperties.limits;
|
||||
const auto &limits = fb->device->PhysicalDevice.Properties.limits;
|
||||
VkSampleCountFlags deviceSampleCounts = limits.sampledImageColorSampleCounts & limits.sampledImageDepthSampleCounts & limits.sampledImageStencilSampleCounts;
|
||||
|
||||
int requestedSamples = clamp((int)gl_multisample, 0, 64);
|
||||
|
|
|
@ -370,7 +370,7 @@ inline void ImageBuilder::setUsage(VkImageUsageFlags usage, VmaMemoryUsage memor
|
|||
inline bool ImageBuilder::isFormatSupported(VulkanDevice *device)
|
||||
{
|
||||
VkImageFormatProperties properties = { };
|
||||
VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->physicalDevice, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties);
|
||||
VkResult result = vkGetPhysicalDeviceImageFormatProperties(device->PhysicalDevice.Device, imageInfo.format, imageInfo.imageType, imageInfo.tiling, imageInfo.usage, imageInfo.flags, &properties);
|
||||
if (result != VK_SUCCESS) return false;
|
||||
if (imageInfo.extent.width > properties.maxExtent.width) return false;
|
||||
if (imageInfo.extent.height > properties.maxExtent.height) return false;
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "vk_swapchain.h"
|
||||
#include "vk_objects.h"
|
||||
#include "c_cvars.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "i_system.h"
|
||||
#include "version.h"
|
||||
#include "doomerrors.h"
|
||||
|
@ -46,6 +47,10 @@ void I_GetVulkanDrawableSize(int *width, int *height);
|
|||
bool I_GetVulkanPlatformExtensions(unsigned int *count, const char **names);
|
||||
bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface);
|
||||
|
||||
// Physical device info
|
||||
static std::vector<VulkanPhysicalDevice> AvailableDevices;
|
||||
static std::vector<VulkanCompatibleDevice> SupportedDevices;
|
||||
|
||||
EXTERN_CVAR(Bool, vid_vsync);
|
||||
|
||||
CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||
|
@ -53,45 +58,139 @@ CUSTOM_CVAR(Bool, vk_debug, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINI
|
|||
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, vk_device, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||
{
|
||||
Printf("This won't take effect until " GAMENAME " is restarted.\n");
|
||||
}
|
||||
|
||||
CCMD(vk_listdevices)
|
||||
{
|
||||
for (size_t i = 0; i < SupportedDevices.size(); i++)
|
||||
{
|
||||
Printf("#%d - %s\n", (int)i, SupportedDevices[i].device->Properties.deviceName);
|
||||
}
|
||||
}
|
||||
|
||||
VulkanDevice::VulkanDevice()
|
||||
{
|
||||
if (volkInitialize() != VK_SUCCESS)
|
||||
{
|
||||
throw std::runtime_error("Unable to find Vulkan");
|
||||
}
|
||||
auto iver = volkGetInstanceVersion();
|
||||
if (iver == 0)
|
||||
{
|
||||
throw std::runtime_error("Vulkan not supported");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
createInstance();
|
||||
createSurface();
|
||||
selectPhysicalDevice();
|
||||
createDevice();
|
||||
createAllocator();
|
||||
InitVolk();
|
||||
CreateInstance();
|
||||
CreateSurface();
|
||||
|
||||
UsedDeviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||
UsedDeviceFeatures.shaderClipDistance = VK_TRUE;
|
||||
UsedDeviceFeatures.fragmentStoresAndAtomics = VK_TRUE;
|
||||
UsedDeviceFeatures.depthClamp = VK_TRUE;
|
||||
UsedDeviceFeatures.shaderClipDistance = VK_TRUE;
|
||||
|
||||
SelectPhysicalDevice();
|
||||
CreateDevice();
|
||||
CreateAllocator();
|
||||
|
||||
int width, height;
|
||||
I_GetVulkanDrawableSize(&width, &height);
|
||||
swapChain = std::make_unique<VulkanSwapChain>(this, width, height, vid_vsync);
|
||||
|
||||
createSemaphores();
|
||||
CreateSemaphores();
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
releaseResources();
|
||||
ReleaseResources();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
VulkanDevice::~VulkanDevice()
|
||||
{
|
||||
releaseResources();
|
||||
ReleaseResources();
|
||||
}
|
||||
|
||||
void VulkanDevice::windowResized()
|
||||
bool VulkanDevice::CheckFeatures(const VkPhysicalDeviceFeatures &f)
|
||||
{
|
||||
return
|
||||
f.samplerAnisotropy == VK_TRUE &&
|
||||
f.shaderClipDistance == VK_TRUE &&
|
||||
f.fragmentStoresAndAtomics == VK_TRUE &&
|
||||
f.depthClamp == VK_TRUE &&
|
||||
f.shaderClipDistance == VK_TRUE;
|
||||
}
|
||||
|
||||
void VulkanDevice::SelectPhysicalDevice()
|
||||
{
|
||||
AvailableDevices = GetPhysicalDevices(instance);
|
||||
|
||||
for (size_t idx = 0; idx < AvailableDevices.size(); idx++)
|
||||
{
|
||||
const auto &info = AvailableDevices[idx];
|
||||
|
||||
if (!CheckFeatures(info.Features))
|
||||
continue;
|
||||
|
||||
VulkanCompatibleDevice dev;
|
||||
dev.device = &AvailableDevices[idx];
|
||||
|
||||
int i = 0;
|
||||
for (const auto& queueFamily : info.QueueFamilies)
|
||||
{
|
||||
// Only accept a decent GPU for now..
|
||||
VkQueueFlags gpuFlags = (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT);
|
||||
if (queueFamily.queueCount > 0 && (queueFamily.queueFlags & gpuFlags) == gpuFlags)
|
||||
{
|
||||
dev.graphicsFamily = i;
|
||||
dev.transferFamily = i;
|
||||
}
|
||||
|
||||
VkBool32 presentSupport = false;
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceSupportKHR(info.Device, i, surface, &presentSupport);
|
||||
if (result == VK_SUCCESS && queueFamily.queueCount > 0 && presentSupport)
|
||||
dev.presentFamily = i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
std::set<std::string> requiredExtensionSearch(EnabledDeviceExtensions.begin(), EnabledDeviceExtensions.end());
|
||||
for (const auto &ext : info.Extensions)
|
||||
requiredExtensionSearch.erase(ext.extensionName);
|
||||
if (!requiredExtensionSearch.empty())
|
||||
continue;
|
||||
|
||||
if (dev.graphicsFamily != -1 && dev.presentFamily != -1 && dev.transferFamily != -1)
|
||||
{
|
||||
SupportedDevices.push_back(dev);
|
||||
}
|
||||
}
|
||||
|
||||
if (SupportedDevices.empty())
|
||||
throw std::runtime_error("No Vulkan device supports the minimum requirements of this application");
|
||||
|
||||
// The device order returned by Vulkan can be anything. Prefer discrete > integrated > virtual gpu > cpu > other
|
||||
std::stable_sort(SupportedDevices.begin(), SupportedDevices.end(), [&](const auto &a, const auto b) {
|
||||
|
||||
// Sort by GPU type first. This will ensure the "best" device is most likely to map to vk_device 0
|
||||
static const int typeSort[] = { 4, 1, 0, 2, 3 };
|
||||
int sortA = a.device->Properties.deviceType < 5 ? typeSort[a.device->Properties.deviceType] : (int)a.device->Properties.deviceType;
|
||||
int sortB = b.device->Properties.deviceType < 5 ? typeSort[b.device->Properties.deviceType] : (int)b.device->Properties.deviceType;
|
||||
if (sortA < sortB)
|
||||
return true;
|
||||
|
||||
// Then sort by the device's unique ID so that vk_device uses a consistent order
|
||||
int sortUUID = memcmp(a.device->Properties.pipelineCacheUUID, b.device->Properties.pipelineCacheUUID, VK_UUID_SIZE);
|
||||
return sortUUID < 0;
|
||||
});
|
||||
|
||||
size_t selected = vk_device;
|
||||
if (selected >= SupportedDevices.size())
|
||||
selected = 0;
|
||||
|
||||
PhysicalDevice = *SupportedDevices[selected].device;
|
||||
graphicsFamily = SupportedDevices[selected].graphicsFamily;
|
||||
presentFamily = SupportedDevices[selected].presentFamily;
|
||||
transferFamily = SupportedDevices[selected].transferFamily;
|
||||
}
|
||||
|
||||
void VulkanDevice::WindowResized()
|
||||
{
|
||||
int width, height;
|
||||
I_GetVulkanDrawableSize(&width, &height);
|
||||
|
@ -100,20 +199,20 @@ void VulkanDevice::windowResized()
|
|||
swapChain = std::make_unique<VulkanSwapChain>(this, width, height, vid_vsync);
|
||||
}
|
||||
|
||||
void VulkanDevice::waitPresent()
|
||||
void VulkanDevice::WaitPresent()
|
||||
{
|
||||
vkWaitForFences(device, 1, &renderFinishedFence->fence, VK_TRUE, std::numeric_limits<uint64_t>::max());
|
||||
vkResetFences(device, 1, &renderFinishedFence->fence);
|
||||
}
|
||||
|
||||
void VulkanDevice::beginFrame()
|
||||
void VulkanDevice::BeginFrame()
|
||||
{
|
||||
VkResult result = vkAcquireNextImageKHR(device, swapChain->swapChain, std::numeric_limits<uint64_t>::max(), imageAvailableSemaphore->semaphore, VK_NULL_HANDLE, &presentImageIndex);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("Failed to acquire next image!");
|
||||
}
|
||||
|
||||
void VulkanDevice::presentFrame()
|
||||
void VulkanDevice::PresentFrame()
|
||||
{
|
||||
VkSemaphore waitSemaphores[] = { renderFinishedSemaphore->semaphore };
|
||||
VkSwapchainKHR swapChains[] = { swapChain->swapChain };
|
||||
|
@ -129,7 +228,135 @@ void VulkanDevice::presentFrame()
|
|||
vkQueuePresentKHR(presentQueue, &presentInfo);
|
||||
}
|
||||
|
||||
VkBool32 VulkanDevice::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData)
|
||||
void VulkanDevice::CreateAllocator()
|
||||
{
|
||||
VmaAllocatorCreateInfo allocinfo = {};
|
||||
// allocinfo.flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; // To do: enable this for better performance
|
||||
allocinfo.physicalDevice = PhysicalDevice.Device;
|
||||
allocinfo.device = device;
|
||||
allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024;
|
||||
if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS)
|
||||
throw std::runtime_error("Unable to create allocator");
|
||||
}
|
||||
|
||||
void VulkanDevice::CreateSemaphores()
|
||||
{
|
||||
imageAvailableSemaphore.reset(new VulkanSemaphore(this));
|
||||
renderFinishedSemaphore.reset(new VulkanSemaphore(this));
|
||||
renderFinishedFence.reset(new VulkanFence(this));
|
||||
}
|
||||
|
||||
void VulkanDevice::CreateDevice()
|
||||
{
|
||||
float queuePriority = 1.0f;
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
|
||||
std::set<int> neededFamilies;
|
||||
neededFamilies.insert(graphicsFamily);
|
||||
neededFamilies.insert(presentFamily);
|
||||
neededFamilies.insert(transferFamily);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
|
||||
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||
deviceCreateInfo.pEnabledFeatures = &UsedDeviceFeatures;
|
||||
deviceCreateInfo.enabledExtensionCount = (uint32_t)EnabledDeviceExtensions.size();
|
||||
deviceCreateInfo.ppEnabledExtensionNames = EnabledDeviceExtensions.data();
|
||||
deviceCreateInfo.enabledLayerCount = 0;
|
||||
|
||||
VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("Could not create vulkan device");
|
||||
|
||||
volkLoadDevice(device);
|
||||
|
||||
vkGetDeviceQueue(device, graphicsFamily, 0, &graphicsQueue);
|
||||
vkGetDeviceQueue(device, presentFamily, 0, &presentQueue);
|
||||
vkGetDeviceQueue(device, transferFamily, 0, &transferQueue);
|
||||
}
|
||||
|
||||
void VulkanDevice::CreateSurface()
|
||||
{
|
||||
if (!I_CreateVulkanSurface(instance, &surface))
|
||||
{
|
||||
throw std::runtime_error("Could not create vulkan surface");
|
||||
}
|
||||
}
|
||||
|
||||
void VulkanDevice::CreateInstance()
|
||||
{
|
||||
AvailableLayers = GetAvailableLayers();
|
||||
Extensions = GetExtensions();
|
||||
EnabledExtensions = GetPlatformExtensions();
|
||||
|
||||
std::string debugLayer = "VK_LAYER_LUNARG_standard_validation";
|
||||
bool wantDebugLayer = vk_debug;
|
||||
bool debugLayerFound = false;
|
||||
for (const VkLayerProperties &layer : AvailableLayers)
|
||||
{
|
||||
if (layer.layerName == debugLayer && wantDebugLayer)
|
||||
{
|
||||
EnabledValidationLayers.push_back(debugLayer.c_str());
|
||||
EnabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
debugLayerFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "GZDoom";
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_REVISION);
|
||||
appInfo.pEngineName = "GZDoom";
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||
|
||||
VkInstanceCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
createInfo.enabledExtensionCount = (uint32_t)EnabledExtensions.size();
|
||||
createInfo.enabledLayerCount = (uint32_t)EnabledValidationLayers.size();
|
||||
createInfo.ppEnabledLayerNames = EnabledValidationLayers.data();
|
||||
createInfo.ppEnabledExtensionNames = EnabledExtensions.data();
|
||||
|
||||
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("Could not create vulkan instance");
|
||||
|
||||
volkLoadInstance(instance);
|
||||
|
||||
if (debugLayerFound)
|
||||
{
|
||||
VkDebugUtilsMessengerCreateInfoEXT createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||
createInfo.messageSeverity =
|
||||
//VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
|
||||
//VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||
createInfo.messageType =
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||
createInfo.pfnUserCallback = DebugCallback;
|
||||
createInfo.pUserData = this;
|
||||
result = vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkCreateDebugUtilsMessengerEXT failed");
|
||||
}
|
||||
}
|
||||
|
||||
VkBool32 VulkanDevice::DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* callbackData, void* userData)
|
||||
{
|
||||
VulkanDevice *device = (VulkanDevice*)userData;
|
||||
|
||||
|
@ -179,249 +406,89 @@ VkBool32 VulkanDevice::debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT mess
|
|||
return VK_FALSE;
|
||||
}
|
||||
|
||||
void VulkanDevice::createInstance()
|
||||
std::vector<VkLayerProperties> VulkanDevice::GetAvailableLayers()
|
||||
{
|
||||
VkResult result;
|
||||
|
||||
uint32_t layerCount;
|
||||
vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
||||
availableLayers.resize(layerCount);
|
||||
vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
|
||||
VkResult result = vkEnumerateInstanceLayerProperties(&layerCount, nullptr);
|
||||
|
||||
std::vector<VkLayerProperties> availableLayers(layerCount);
|
||||
result = vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data());
|
||||
return availableLayers;
|
||||
}
|
||||
|
||||
std::vector<VkExtensionProperties> VulkanDevice::GetExtensions()
|
||||
{
|
||||
uint32_t extensionCount = 0;
|
||||
result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
|
||||
extensions.resize(extensionCount);
|
||||
vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
|
||||
VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr);
|
||||
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "GZDoom";
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(VER_MAJOR, VER_MINOR, VER_REVISION);
|
||||
appInfo.pEngineName = "GZDoom";
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(ENG_MAJOR, ENG_MINOR, ENG_REVISION);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||
|
||||
std::vector<const char *> enabledExtensions;
|
||||
|
||||
if (!I_GetVulkanPlatformExtensions(&extensionCount, nullptr))
|
||||
{
|
||||
throw std::runtime_error("Cannot obtain number of Vulkan extensions");
|
||||
}
|
||||
|
||||
enabledExtensions.resize(extensionCount);
|
||||
|
||||
if (!I_GetVulkanPlatformExtensions(&extensionCount, &enabledExtensions[0]))
|
||||
{
|
||||
throw std::runtime_error("Cannot obtain list of Vulkan extensions");
|
||||
}
|
||||
|
||||
std::vector<const char*> validationLayers;
|
||||
std::string debugLayer = "VK_LAYER_LUNARG_standard_validation";
|
||||
bool wantDebugLayer = vk_debug;
|
||||
bool debugLayerFound = false;
|
||||
for (const VkLayerProperties &layer : availableLayers)
|
||||
{
|
||||
if (layer.layerName == debugLayer && wantDebugLayer)
|
||||
{
|
||||
validationLayers.push_back(debugLayer.c_str());
|
||||
enabledExtensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
|
||||
debugLayerFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
VkInstanceCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
createInfo.enabledExtensionCount = (uint32_t)enabledExtensions.size();
|
||||
createInfo.enabledLayerCount = (uint32_t)validationLayers.size();
|
||||
createInfo.ppEnabledLayerNames = validationLayers.data();
|
||||
createInfo.ppEnabledExtensionNames = enabledExtensions.data();
|
||||
|
||||
result = vkCreateInstance(&createInfo, nullptr, &instance);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("Could not create vulkan instance");
|
||||
|
||||
volkLoadInstance(instance);
|
||||
|
||||
if (debugLayerFound)
|
||||
{
|
||||
VkDebugUtilsMessengerCreateInfoEXT createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
|
||||
createInfo.messageSeverity =
|
||||
//VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
|
||||
//VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
|
||||
createInfo.messageType =
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
|
||||
VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
|
||||
createInfo.pfnUserCallback = debugCallback;
|
||||
createInfo.pUserData = this;
|
||||
result = vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkCreateDebugUtilsMessengerEXT failed");
|
||||
}
|
||||
std::vector<VkExtensionProperties> extensions(extensionCount);
|
||||
result = vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data());
|
||||
return extensions;
|
||||
}
|
||||
|
||||
void VulkanDevice::createSurface()
|
||||
std::vector<VulkanPhysicalDevice> VulkanDevice::GetPhysicalDevices(VkInstance instance)
|
||||
{
|
||||
if (!I_CreateVulkanSurface(instance, &surface))
|
||||
{
|
||||
throw std::runtime_error("Could not create vulkan surface");
|
||||
}
|
||||
}
|
||||
|
||||
bool VulkanDevice::checkFeatures(const VkPhysicalDeviceFeatures &f)
|
||||
{
|
||||
return
|
||||
f.samplerAnisotropy == VK_TRUE &&
|
||||
f.shaderClipDistance == VK_TRUE &&
|
||||
f.fragmentStoresAndAtomics == VK_TRUE &&
|
||||
f.depthClamp == VK_TRUE &&
|
||||
f.shaderClipDistance == VK_TRUE;
|
||||
}
|
||||
|
||||
void VulkanDevice::selectPhysicalDevice()
|
||||
{
|
||||
VkResult result;
|
||||
|
||||
uint32_t deviceCount = 0;
|
||||
result = vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||
VkResult result = vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkEnumeratePhysicalDevices failed");
|
||||
else if (deviceCount == 0)
|
||||
throw std::runtime_error("Could not find any vulkan devices");
|
||||
if (deviceCount == 0)
|
||||
return {};
|
||||
|
||||
std::vector<VkPhysicalDevice> devices(deviceCount);
|
||||
result = vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkEnumeratePhysicalDevices failed (2)");
|
||||
|
||||
for (const auto &device : devices)
|
||||
std::vector<VulkanPhysicalDevice> devinfo(deviceCount);
|
||||
for (size_t i = 0; i < devices.size(); i++)
|
||||
{
|
||||
vkGetPhysicalDeviceProperties(device, &deviceProperties);
|
||||
vkGetPhysicalDeviceFeatures(device, &deviceFeatures);
|
||||
auto &dev = devinfo[i];
|
||||
dev.Device = devices[i];
|
||||
|
||||
bool isUsableDevice = /*deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU &&*/ checkFeatures(deviceFeatures);
|
||||
if (!isUsableDevice)
|
||||
continue;
|
||||
vkGetPhysicalDeviceMemoryProperties(dev.Device, &dev.MemoryProperties);
|
||||
vkGetPhysicalDeviceProperties(dev.Device, &dev.Properties);
|
||||
vkGetPhysicalDeviceFeatures(dev.Device, &dev.Features);
|
||||
|
||||
uint32_t queueFamilyCount = 0;
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(dev.Device, &queueFamilyCount, nullptr);
|
||||
dev.QueueFamilies.resize(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(dev.Device, &queueFamilyCount, dev.QueueFamilies.data());
|
||||
|
||||
std::vector<VkQueueFamilyProperties> queueFamilies(queueFamilyCount);
|
||||
vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data());
|
||||
|
||||
graphicsFamily = -1;
|
||||
computeFamily = -1;
|
||||
transferFamily = -1;
|
||||
sparseBindingFamily = -1;
|
||||
presentFamily = -1;
|
||||
|
||||
int i = 0;
|
||||
for (const auto& queueFamily : queueFamilies)
|
||||
{
|
||||
// Only accept a decent GPU for now..
|
||||
VkQueueFlags gpuFlags = (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_TRANSFER_BIT);
|
||||
if (queueFamily.queueCount > 0 && (queueFamily.queueFlags & gpuFlags) == gpuFlags)
|
||||
{
|
||||
graphicsFamily = i;
|
||||
computeFamily = i;
|
||||
transferFamily = i;
|
||||
sparseBindingFamily = i;
|
||||
}
|
||||
|
||||
VkBool32 presentSupport = false;
|
||||
result = vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface, &presentSupport);
|
||||
if (result == VK_SUCCESS && queueFamily.queueCount > 0 && presentSupport) presentFamily = i;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
uint32_t deviceExtensionCount;
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &deviceExtensionCount, nullptr);
|
||||
availableDeviceExtensions.resize(deviceExtensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(device, nullptr, &deviceExtensionCount, availableDeviceExtensions.data());
|
||||
|
||||
std::set<std::string> requiredExtensionSearch(requiredExtensions.begin(), requiredExtensions.end());
|
||||
for (const auto &ext : availableDeviceExtensions)
|
||||
requiredExtensionSearch.erase(ext.extensionName);
|
||||
if (!requiredExtensionSearch.empty())
|
||||
continue;
|
||||
|
||||
physicalDevice = device;
|
||||
return;
|
||||
uint32_t deviceExtensionCount = 0;
|
||||
vkEnumerateDeviceExtensionProperties(dev.Device, nullptr, &deviceExtensionCount, nullptr);
|
||||
dev.Extensions.resize(deviceExtensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(dev.Device, nullptr, &deviceExtensionCount, dev.Extensions.data());
|
||||
}
|
||||
|
||||
throw std::runtime_error("No Vulkan device supports the minimum requirements of this application");
|
||||
return devinfo;
|
||||
}
|
||||
|
||||
void VulkanDevice::createDevice()
|
||||
std::vector<const char *> VulkanDevice::GetPlatformExtensions()
|
||||
{
|
||||
float queuePriority = 1.0f;
|
||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos;
|
||||
uint32_t extensionCount = 0;
|
||||
if (!I_GetVulkanPlatformExtensions(&extensionCount, nullptr))
|
||||
throw std::runtime_error("Cannot obtain number of Vulkan extensions");
|
||||
|
||||
std::set<int> neededFamilies;
|
||||
neededFamilies.insert(graphicsFamily);
|
||||
neededFamilies.insert(presentFamily);
|
||||
neededFamilies.insert(computeFamily);
|
||||
std::vector<const char *> extensions(extensionCount);
|
||||
if (!I_GetVulkanPlatformExtensions(&extensionCount, extensions.data()))
|
||||
throw std::runtime_error("Cannot obtain list of Vulkan extensions");
|
||||
return extensions;
|
||||
}
|
||||
|
||||
for (int index : neededFamilies)
|
||||
void VulkanDevice::InitVolk()
|
||||
{
|
||||
if (volkInitialize() != VK_SUCCESS)
|
||||
{
|
||||
VkDeviceQueueCreateInfo queueCreateInfo = {};
|
||||
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queueCreateInfo.queueFamilyIndex = index;
|
||||
queueCreateInfo.queueCount = 1;
|
||||
queueCreateInfo.pQueuePriorities = &queuePriority;
|
||||
queueCreateInfos.push_back(queueCreateInfo);
|
||||
throw std::runtime_error("Unable to find Vulkan");
|
||||
}
|
||||
auto iver = volkGetInstanceVersion();
|
||||
if (iver == 0)
|
||||
{
|
||||
throw std::runtime_error("Vulkan not supported");
|
||||
}
|
||||
|
||||
VkPhysicalDeviceFeatures usedDeviceFeatures = {};
|
||||
usedDeviceFeatures.samplerAnisotropy = VK_TRUE;
|
||||
usedDeviceFeatures.shaderClipDistance = VK_TRUE;
|
||||
usedDeviceFeatures.fragmentStoresAndAtomics = VK_TRUE;
|
||||
usedDeviceFeatures.depthClamp = VK_TRUE;
|
||||
usedDeviceFeatures.shaderClipDistance = VK_TRUE;
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.queueCreateInfoCount = (uint32_t)queueCreateInfos.size();
|
||||
deviceCreateInfo.pQueueCreateInfos = queueCreateInfos.data();
|
||||
deviceCreateInfo.pEnabledFeatures = &usedDeviceFeatures;
|
||||
deviceCreateInfo.enabledExtensionCount = (uint32_t)requiredExtensions.size();
|
||||
deviceCreateInfo.ppEnabledExtensionNames = requiredExtensions.data();
|
||||
deviceCreateInfo.enabledLayerCount = 0;
|
||||
|
||||
VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &device);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("Could not create vulkan device");
|
||||
|
||||
volkLoadDevice(device);
|
||||
|
||||
vkGetDeviceQueue(device, graphicsFamily, 0, &graphicsQueue);
|
||||
vkGetDeviceQueue(device, presentFamily, 0, &presentQueue);
|
||||
}
|
||||
|
||||
void VulkanDevice::createAllocator()
|
||||
{
|
||||
VmaAllocatorCreateInfo allocinfo = {};
|
||||
// allocinfo.flags = VMA_ALLOCATOR_CREATE_KHR_DEDICATED_ALLOCATION_BIT; // To do: enable this for better performance
|
||||
allocinfo.physicalDevice = physicalDevice;
|
||||
allocinfo.device = device;
|
||||
allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024;
|
||||
if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS)
|
||||
throw std::runtime_error("Unable to create allocator");
|
||||
}
|
||||
|
||||
void VulkanDevice::createSemaphores()
|
||||
{
|
||||
imageAvailableSemaphore.reset(new VulkanSemaphore(this));
|
||||
renderFinishedSemaphore.reset(new VulkanSemaphore(this));
|
||||
renderFinishedFence.reset(new VulkanFence(this));
|
||||
}
|
||||
|
||||
void VulkanDevice::releaseResources()
|
||||
void VulkanDevice::ReleaseResources()
|
||||
{
|
||||
if (device)
|
||||
vkDeviceWaitIdle(device);
|
||||
|
@ -450,14 +517,11 @@ void VulkanDevice::releaseResources()
|
|||
instance = nullptr;
|
||||
}
|
||||
|
||||
uint32_t VulkanDevice::findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
|
||||
uint32_t VulkanDevice::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties)
|
||||
{
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
|
||||
|
||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++)
|
||||
for (uint32_t i = 0; i < PhysicalDevice.MemoryProperties.memoryTypeCount; i++)
|
||||
{
|
||||
if ((typeFilter & (1 << i)) && (memProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
if ((typeFilter & (1 << i)) && (PhysicalDevice.MemoryProperties.memoryTypes[i].propertyFlags & properties) == properties)
|
||||
return i;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,70 +11,90 @@ class VulkanSwapChain;
|
|||
class VulkanSemaphore;
|
||||
class VulkanFence;
|
||||
|
||||
class VulkanPhysicalDevice
|
||||
{
|
||||
public:
|
||||
VkPhysicalDevice Device = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<VkExtensionProperties> Extensions;
|
||||
std::vector<VkQueueFamilyProperties> QueueFamilies;
|
||||
VkPhysicalDeviceProperties Properties = {};
|
||||
VkPhysicalDeviceFeatures Features = {};
|
||||
VkPhysicalDeviceMemoryProperties MemoryProperties = {};
|
||||
};
|
||||
|
||||
class VulkanCompatibleDevice
|
||||
{
|
||||
public:
|
||||
VulkanPhysicalDevice *device = nullptr;
|
||||
int graphicsFamily = -1;
|
||||
int transferFamily = -1;
|
||||
int presentFamily = -1;
|
||||
};
|
||||
|
||||
class VulkanDevice
|
||||
{
|
||||
public:
|
||||
VulkanDevice();
|
||||
~VulkanDevice();
|
||||
|
||||
void windowResized();
|
||||
void waitPresent();
|
||||
void WindowResized();
|
||||
void WaitPresent();
|
||||
|
||||
void beginFrame();
|
||||
void presentFrame();
|
||||
void BeginFrame();
|
||||
void PresentFrame();
|
||||
|
||||
VkDevice device = nullptr;
|
||||
uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
|
||||
// Instance setup
|
||||
std::vector<VkLayerProperties> AvailableLayers;
|
||||
std::vector<VkExtensionProperties> Extensions;
|
||||
std::vector<const char *> EnabledExtensions;
|
||||
std::vector<const char*> EnabledValidationLayers;
|
||||
|
||||
// Device setup
|
||||
VkPhysicalDeviceFeatures UsedDeviceFeatures = {};
|
||||
std::vector<const char *> EnabledDeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||
VulkanPhysicalDevice PhysicalDevice;
|
||||
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VmaAllocator allocator = VK_NULL_HANDLE;
|
||||
|
||||
VkQueue graphicsQueue = VK_NULL_HANDLE;
|
||||
VkQueue presentQueue = VK_NULL_HANDLE;
|
||||
VkQueue transferQueue = VK_NULL_HANDLE;
|
||||
|
||||
int graphicsFamily = -1;
|
||||
int computeFamily = -1;
|
||||
int transferFamily = -1;
|
||||
int sparseBindingFamily = -1;
|
||||
int presentFamily = -1;
|
||||
|
||||
std::unique_ptr<VulkanSwapChain> swapChain;
|
||||
uint32_t presentImageIndex = 0;
|
||||
|
||||
VkQueue graphicsQueue = nullptr;
|
||||
|
||||
std::unique_ptr<VulkanSemaphore> imageAvailableSemaphore;
|
||||
std::unique_ptr<VulkanSemaphore> renderFinishedSemaphore;
|
||||
std::unique_ptr<VulkanFence> renderFinishedFence;
|
||||
|
||||
VmaAllocator allocator = VK_NULL_HANDLE;
|
||||
|
||||
std::vector<VkLayerProperties> availableLayers;
|
||||
std::vector<VkExtensionProperties> extensions;
|
||||
std::vector<VkExtensionProperties> availableDeviceExtensions;
|
||||
VkPhysicalDeviceProperties deviceProperties;
|
||||
VkPhysicalDeviceFeatures deviceFeatures;
|
||||
|
||||
VkPhysicalDevice physicalDevice = {};
|
||||
|
||||
uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties);
|
||||
|
||||
private:
|
||||
void createInstance();
|
||||
void createSurface();
|
||||
void selectPhysicalDevice();
|
||||
void createDevice();
|
||||
void createAllocator();
|
||||
void createSemaphores();
|
||||
void releaseResources();
|
||||
void CreateInstance();
|
||||
void CreateSurface();
|
||||
void SelectPhysicalDevice();
|
||||
void CreateDevice();
|
||||
void CreateAllocator();
|
||||
void CreateSemaphores();
|
||||
void ReleaseResources();
|
||||
|
||||
static bool checkFeatures(const VkPhysicalDeviceFeatures &f);
|
||||
static bool CheckFeatures(const VkPhysicalDeviceFeatures &f);
|
||||
|
||||
VkDebugUtilsMessengerEXT debugMessenger = VK_NULL_HANDLE;
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData);
|
||||
|
||||
std::vector<const char *> requiredExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
|
||||
static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData);
|
||||
|
||||
VkInstance instance = nullptr;
|
||||
VkSurfaceKHR surface = 0;
|
||||
|
||||
VkQueue presentQueue = nullptr;
|
||||
|
||||
VulkanDevice(const VulkanDevice &) = delete;
|
||||
VulkanDevice &operator=(const VulkanDevice &) = delete;
|
||||
|
||||
friend class VulkanSwapChain;
|
||||
static void InitVolk();
|
||||
static std::vector<VkLayerProperties> GetAvailableLayers();
|
||||
static std::vector<VkExtensionProperties> GetExtensions();
|
||||
static std::vector<const char *> GetPlatformExtensions();
|
||||
static std::vector<VulkanPhysicalDevice> GetPhysicalDevices(VkInstance instance);
|
||||
};
|
||||
|
|
|
@ -102,8 +102,8 @@ void VulkanFrameBuffer::InitializeState()
|
|||
gl_vendorstring = "Vulkan";
|
||||
hwcaps = RFL_SHADER_STORAGE_BUFFER | RFL_BUFFER_STORAGE;
|
||||
glslversion = 4.50f;
|
||||
uniformblockalignment = (unsigned int)device->deviceProperties.limits.minUniformBufferOffsetAlignment;
|
||||
maxuniformblock = device->deviceProperties.limits.maxUniformBufferRange;
|
||||
uniformblockalignment = (unsigned int)device->PhysicalDevice.Properties.limits.minUniformBufferOffsetAlignment;
|
||||
maxuniformblock = device->PhysicalDevice.Properties.limits.maxUniformBufferRange;
|
||||
|
||||
mUploadSemaphore.reset(new VulkanSemaphore(device));
|
||||
mGraphicsCommandPool.reset(new VulkanCommandPool(device, device->graphicsFamily));
|
||||
|
@ -149,12 +149,12 @@ void VulkanFrameBuffer::Update()
|
|||
int newHeight = GetClientHeight();
|
||||
if (lastSwapWidth != newWidth || lastSwapHeight != newHeight)
|
||||
{
|
||||
device->windowResized();
|
||||
device->WindowResized();
|
||||
lastSwapWidth = newWidth;
|
||||
lastSwapHeight = newHeight;
|
||||
}
|
||||
|
||||
device->beginFrame();
|
||||
device->BeginFrame();
|
||||
|
||||
GetPostprocess()->SetActiveRenderTarget();
|
||||
|
||||
|
@ -220,8 +220,8 @@ void VulkanFrameBuffer::Update()
|
|||
|
||||
Finish.Reset();
|
||||
Finish.Clock();
|
||||
device->presentFrame();
|
||||
device->waitPresent();
|
||||
device->PresentFrame();
|
||||
device->WaitPresent();
|
||||
|
||||
mDrawCommands.reset();
|
||||
mUploadCommands.reset();
|
||||
|
@ -478,7 +478,7 @@ void VulkanFrameBuffer::SetVSync(bool vsync)
|
|||
{
|
||||
if (device->swapChain->vsync != vsync)
|
||||
{
|
||||
device->windowResized();
|
||||
device->WindowResized();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -596,33 +596,35 @@ unsigned int VulkanFrameBuffer::GetLightBufferBlockSize() const
|
|||
|
||||
void VulkanFrameBuffer::PrintStartupLog()
|
||||
{
|
||||
const auto props = device->PhysicalDevice.Properties;
|
||||
|
||||
FString deviceType;
|
||||
switch (device->deviceProperties.deviceType)
|
||||
switch (props.deviceType)
|
||||
{
|
||||
case VK_PHYSICAL_DEVICE_TYPE_OTHER: deviceType = "other"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU: deviceType = "integrated gpu"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU: deviceType = "discrete gpu"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU: deviceType = "virtual gpu"; break;
|
||||
case VK_PHYSICAL_DEVICE_TYPE_CPU: deviceType = "cpu"; break;
|
||||
default: deviceType.Format("%d", (int)device->deviceProperties.deviceType); break;
|
||||
default: deviceType.Format("%d", (int)props.deviceType); break;
|
||||
}
|
||||
|
||||
FString apiVersion, driverVersion;
|
||||
apiVersion.Format("%d.%d.%d", VK_VERSION_MAJOR(device->deviceProperties.apiVersion), VK_VERSION_MINOR(device->deviceProperties.apiVersion), VK_VERSION_PATCH(device->deviceProperties.apiVersion));
|
||||
driverVersion.Format("%d.%d.%d", VK_VERSION_MAJOR(device->deviceProperties.driverVersion), VK_VERSION_MINOR(device->deviceProperties.driverVersion), VK_VERSION_PATCH(device->deviceProperties.driverVersion));
|
||||
apiVersion.Format("%d.%d.%d", VK_VERSION_MAJOR(props.apiVersion), VK_VERSION_MINOR(props.apiVersion), VK_VERSION_PATCH(props.apiVersion));
|
||||
driverVersion.Format("%d.%d.%d", VK_VERSION_MAJOR(props.driverVersion), VK_VERSION_MINOR(props.driverVersion), VK_VERSION_PATCH(props.driverVersion));
|
||||
|
||||
Printf("Vulkan device: " TEXTCOLOR_ORANGE "%s\n", device->deviceProperties.deviceName);
|
||||
Printf("Vulkan device: " TEXTCOLOR_ORANGE "%s\n", props.deviceName);
|
||||
Printf("Vulkan device type: %s\n", deviceType.GetChars());
|
||||
Printf("Vulkan version: %s (api) %s (driver)\n", apiVersion.GetChars(), driverVersion.GetChars());
|
||||
|
||||
Printf(PRINT_LOG, "Vulkan extensions:");
|
||||
for (const VkExtensionProperties &p : device->availableDeviceExtensions)
|
||||
for (const VkExtensionProperties &p : device->PhysicalDevice.Extensions)
|
||||
{
|
||||
Printf(PRINT_LOG, " %s", p.extensionName);
|
||||
}
|
||||
Printf(PRINT_LOG, "\n");
|
||||
|
||||
const auto &limits = device->deviceProperties.limits;
|
||||
const auto &limits = props.limits;
|
||||
Printf("Max. texture size: %d\n", limits.maxImageDimension2D);
|
||||
Printf("Max. uniform buffer range: %d\n", limits.maxUniformBufferRange);
|
||||
Printf("Min. uniform buffer offset alignment: %d\n", limits.minUniformBufferOffsetAlignment);
|
||||
|
|
|
@ -4,31 +4,31 @@
|
|||
VulkanSwapChain::VulkanSwapChain(VulkanDevice *device, int width, int height, bool vsync) : vsync(vsync), device(device)
|
||||
{
|
||||
VkSurfaceCapabilitiesKHR surfaceCapabilities;
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->physicalDevice, device->surface, &surfaceCapabilities);
|
||||
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->surface, &surfaceCapabilities);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed");
|
||||
|
||||
uint32_t surfaceFormatCount = 0;
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->physicalDevice, device->surface, &surfaceFormatCount, nullptr);
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||
else if (surfaceFormatCount == 0)
|
||||
throw std::runtime_error("No surface formats supported");
|
||||
|
||||
std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->physicalDevice, device->surface, &surfaceFormatCount, surfaceFormats.data());
|
||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, surfaceFormats.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||
|
||||
uint32_t presentModeCount = 0;
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, device->surface, &presentModeCount, nullptr);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, nullptr);
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
||||
else if (presentModeCount == 0)
|
||||
throw std::runtime_error("No surface present modes supported");
|
||||
|
||||
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device->physicalDevice, device->surface, &presentModeCount, presentModes.data());
|
||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, presentModes.data());
|
||||
if (result != VK_SUCCESS)
|
||||
throw std::runtime_error("vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
||||
|
||||
|
|
Loading…
Reference in a new issue