mirror of
https://github.com/ZDoom/gzdoom.git
synced 2024-11-26 22:11:43 +00:00
- create a new error class for vulkan errors as they are only recoverable during initialization (unlike CRecoverableError which is recoverable during normal processing)
- improve vulkan errors by including the status code returned by vulkan if they fail
This commit is contained in:
parent
afa644fe47
commit
756c593e96
9 changed files with 126 additions and 90 deletions
|
@ -282,7 +282,7 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer ()
|
||||||
device = new VulkanDevice();
|
device = new VulkanDevice();
|
||||||
fb = new VulkanFrameBuffer(nullptr, fullscreen, device);
|
fb = new VulkanFrameBuffer(nullptr, fullscreen, device);
|
||||||
}
|
}
|
||||||
catch (CRecoverableError const&)
|
catch (CVulkanError const&)
|
||||||
{
|
{
|
||||||
if (Priv::window != nullptr)
|
if (Priv::window != nullptr)
|
||||||
{
|
{
|
||||||
|
|
|
@ -177,7 +177,11 @@ std::unique_ptr<VulkanShader> ShaderBuilder::create(const char *shadername, Vulk
|
||||||
VkShaderModule shaderModule;
|
VkShaderModule shaderModule;
|
||||||
VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule);
|
VkResult result = vkCreateShaderModule(device->device, &createInfo, nullptr, &shaderModule);
|
||||||
if (result != VK_SUCCESS)
|
if (result != VK_SUCCESS)
|
||||||
I_FatalError("Could not create vulkan shader module for '%s'", shadername);
|
{
|
||||||
|
FString msg;
|
||||||
|
msg.Format("Could not create vulkan shader module for '%s': %s", shadername, VkResultToString(result).GetChars());
|
||||||
|
VulkanError(msg.GetChars());
|
||||||
|
}
|
||||||
|
|
||||||
return std::make_unique<VulkanShader>(device, shaderModule);
|
return std::make_unique<VulkanShader>(device, shaderModule);
|
||||||
}
|
}
|
||||||
|
|
|
@ -430,8 +430,7 @@ inline std::unique_ptr<VulkanImage> ImageBuilder::create(VulkanDevice *device, V
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
|
|
||||||
VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr);
|
VkResult result = vmaCreateImage(device->allocator, &imageInfo, &allocInfo, &image, &allocation, nullptr);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create vulkan image");
|
||||||
I_FatalError("Could not create vulkan image");
|
|
||||||
|
|
||||||
if (allocatedBytes != nullptr)
|
if (allocatedBytes != nullptr)
|
||||||
{
|
{
|
||||||
|
@ -480,8 +479,7 @@ inline std::unique_ptr<VulkanImageView> ImageViewBuilder::create(VulkanDevice *d
|
||||||
{
|
{
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
VkResult result = vkCreateImageView(device->device, &viewInfo, nullptr, &view);
|
VkResult result = vkCreateImageView(device->device, &viewInfo, nullptr, &view);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create texture image view");
|
||||||
I_FatalError("Could not create texture image view");
|
|
||||||
|
|
||||||
return std::make_unique<VulkanImageView>(device, view);
|
return std::make_unique<VulkanImageView>(device, view);
|
||||||
}
|
}
|
||||||
|
@ -552,8 +550,7 @@ inline std::unique_ptr<VulkanSampler> SamplerBuilder::create(VulkanDevice *devic
|
||||||
{
|
{
|
||||||
VkSampler sampler;
|
VkSampler sampler;
|
||||||
VkResult result = vkCreateSampler(device->device, &samplerInfo, nullptr, &sampler);
|
VkResult result = vkCreateSampler(device->device, &samplerInfo, nullptr, &sampler);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create texture sampler");
|
||||||
I_FatalError("Could not create texture sampler");
|
|
||||||
return std::make_unique<VulkanSampler>(device, sampler);
|
return std::make_unique<VulkanSampler>(device, sampler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,8 +587,7 @@ inline std::unique_ptr<VulkanBuffer> BufferBuilder::create(VulkanDevice *device)
|
||||||
VmaAllocation allocation;
|
VmaAllocation allocation;
|
||||||
|
|
||||||
VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
|
VkResult result = vmaCreateBuffer(device->allocator, &bufferInfo, &allocInfo, &buffer, &allocation, nullptr);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not allocate memory for vulkan buffer");
|
||||||
I_FatalError("could not allocate memory for vulkan buffer");
|
|
||||||
|
|
||||||
return std::make_unique<VulkanBuffer>(device, buffer, allocation, bufferInfo.size);
|
return std::make_unique<VulkanBuffer>(device, buffer, allocation, bufferInfo.size);
|
||||||
}
|
}
|
||||||
|
@ -650,8 +646,7 @@ inline std::unique_ptr<VulkanDescriptorSetLayout> DescriptorSetLayoutBuilder::cr
|
||||||
{
|
{
|
||||||
VkDescriptorSetLayout layout;
|
VkDescriptorSetLayout layout;
|
||||||
VkResult result = vkCreateDescriptorSetLayout(device->device, &layoutInfo, nullptr, &layout);
|
VkResult result = vkCreateDescriptorSetLayout(device->device, &layoutInfo, nullptr, &layout);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create descriptor set layout");
|
||||||
I_FatalError("Could not create descriptor set layout");
|
|
||||||
return std::make_unique<VulkanDescriptorSetLayout>(device, layout);
|
return std::make_unique<VulkanDescriptorSetLayout>(device, layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -684,8 +679,7 @@ inline std::unique_ptr<VulkanDescriptorPool> DescriptorPoolBuilder::create(Vulka
|
||||||
{
|
{
|
||||||
VkDescriptorPool descriptorPool;
|
VkDescriptorPool descriptorPool;
|
||||||
VkResult result = vkCreateDescriptorPool(device->device, &poolInfo, nullptr, &descriptorPool);
|
VkResult result = vkCreateDescriptorPool(device->device, &poolInfo, nullptr, &descriptorPool);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create descriptor pool");
|
||||||
I_FatalError("Could not create descriptor pool");
|
|
||||||
return std::make_unique<VulkanDescriptorPool>(device, descriptorPool);
|
return std::make_unique<VulkanDescriptorPool>(device, descriptorPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -707,8 +701,7 @@ inline std::unique_ptr<VulkanQueryPool> QueryPoolBuilder::create(VulkanDevice *d
|
||||||
{
|
{
|
||||||
VkQueryPool queryPool;
|
VkQueryPool queryPool;
|
||||||
VkResult result = vkCreateQueryPool(device->device, &poolInfo, nullptr, &queryPool);
|
VkResult result = vkCreateQueryPool(device->device, &poolInfo, nullptr, &queryPool);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create query pool");
|
||||||
I_FatalError("Could not create query pool");
|
|
||||||
return std::make_unique<VulkanQueryPool>(device, queryPool);
|
return std::make_unique<VulkanQueryPool>(device, queryPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -751,8 +744,7 @@ inline std::unique_ptr<VulkanFramebuffer> FramebufferBuilder::create(VulkanDevic
|
||||||
{
|
{
|
||||||
VkFramebuffer framebuffer = 0;
|
VkFramebuffer framebuffer = 0;
|
||||||
VkResult result = vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer);
|
VkResult result = vkCreateFramebuffer(device->device, &framebufferInfo, nullptr, &framebuffer);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create framebuffer");
|
||||||
I_FatalError("Failed to create framebuffer");
|
|
||||||
return std::make_unique<VulkanFramebuffer>(device, framebuffer);
|
return std::make_unique<VulkanFramebuffer>(device, framebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1042,8 +1034,7 @@ inline std::unique_ptr<VulkanPipeline> GraphicsPipelineBuilder::create(VulkanDev
|
||||||
{
|
{
|
||||||
VkPipeline pipeline = 0;
|
VkPipeline pipeline = 0;
|
||||||
VkResult result = vkCreateGraphicsPipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline);
|
VkResult result = vkCreateGraphicsPipelines(device->device, VK_NULL_HANDLE, 1, &pipelineInfo, nullptr, &pipeline);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create graphics pipeline");
|
||||||
I_FatalError("Could not create graphics pipeline");
|
|
||||||
return std::make_unique<VulkanPipeline>(device, pipeline);
|
return std::make_unique<VulkanPipeline>(device, pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1076,8 +1067,7 @@ inline std::unique_ptr<VulkanPipelineLayout> PipelineLayoutBuilder::create(Vulka
|
||||||
{
|
{
|
||||||
VkPipelineLayout pipelineLayout;
|
VkPipelineLayout pipelineLayout;
|
||||||
VkResult result = vkCreatePipelineLayout(device->device, &pipelineLayoutInfo, nullptr, &pipelineLayout);
|
VkResult result = vkCreatePipelineLayout(device->device, &pipelineLayoutInfo, nullptr, &pipelineLayout);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create pipeline layout");
|
||||||
I_FatalError("Could not create pipeline layout");
|
|
||||||
return std::make_unique<VulkanPipelineLayout>(device, pipelineLayout);
|
return std::make_unique<VulkanPipelineLayout>(device, pipelineLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1172,8 +1162,7 @@ inline std::unique_ptr<VulkanRenderPass> RenderPassBuilder::create(VulkanDevice
|
||||||
{
|
{
|
||||||
VkRenderPass renderPass = 0;
|
VkRenderPass renderPass = 0;
|
||||||
VkResult result = vkCreateRenderPass(device->device, &renderPassInfo, nullptr, &renderPass);
|
VkResult result = vkCreateRenderPass(device->device, &renderPassInfo, nullptr, &renderPass);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create render pass");
|
||||||
I_FatalError("Could not create render pass");
|
|
||||||
return std::make_unique<VulkanRenderPass>(device, renderPass);
|
return std::make_unique<VulkanRenderPass>(device, renderPass);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1305,8 +1294,7 @@ inline void QueueSubmit::addSignal(VulkanSemaphore *semaphore)
|
||||||
inline void QueueSubmit::execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence)
|
inline void QueueSubmit::execute(VulkanDevice *device, VkQueue queue, VulkanFence *fence)
|
||||||
{
|
{
|
||||||
VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fence ? fence->fence : VK_NULL_HANDLE);
|
VkResult result = vkQueueSubmit(device->graphicsQueue, 1, &submitInfo, fence ? fence->fence : VK_NULL_HANDLE);
|
||||||
if (result < VK_SUCCESS)
|
CheckVulkanError(result, "Could not submit command buffer");
|
||||||
I_FatalError("Failed to submit command buffer");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -117,7 +117,7 @@ void VulkanDevice::SelectPhysicalDevice()
|
||||||
{
|
{
|
||||||
AvailableDevices = GetPhysicalDevices(instance);
|
AvailableDevices = GetPhysicalDevices(instance);
|
||||||
if (AvailableDevices.empty())
|
if (AvailableDevices.empty())
|
||||||
I_Error("No Vulkan devices found. Either the graphics card has no vulkan support or the driver is too old.");
|
VulkanError("No Vulkan devices found. Either the graphics card has no vulkan support or the driver is too old.");
|
||||||
|
|
||||||
for (size_t idx = 0; idx < AvailableDevices.size(); idx++)
|
for (size_t idx = 0; idx < AvailableDevices.size(); idx++)
|
||||||
{
|
{
|
||||||
|
@ -169,7 +169,7 @@ void VulkanDevice::SelectPhysicalDevice()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SupportedDevices.empty())
|
if (SupportedDevices.empty())
|
||||||
I_Error("No Vulkan device supports the minimum requirements of this application");
|
VulkanError("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
|
// 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) {
|
std::stable_sort(SupportedDevices.begin(), SupportedDevices.end(), [&](const auto &a, const auto b) {
|
||||||
|
@ -221,7 +221,7 @@ void VulkanDevice::CreateAllocator()
|
||||||
allocinfo.device = device;
|
allocinfo.device = device;
|
||||||
allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024;
|
allocinfo.preferredLargeHeapBlockSize = 64 * 1024 * 1024;
|
||||||
if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS)
|
if (vmaCreateAllocator(&allocinfo, &allocator) != VK_SUCCESS)
|
||||||
I_Error("Unable to create allocator");
|
VulkanError("Unable to create allocator");
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanDevice::CreateDevice()
|
void VulkanDevice::CreateDevice()
|
||||||
|
@ -253,8 +253,7 @@ void VulkanDevice::CreateDevice()
|
||||||
deviceCreateInfo.enabledLayerCount = 0;
|
deviceCreateInfo.enabledLayerCount = 0;
|
||||||
|
|
||||||
VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device);
|
VkResult result = vkCreateDevice(PhysicalDevice.Device, &deviceCreateInfo, nullptr, &device);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create vulkan device");
|
||||||
I_Error("Could not create vulkan device");
|
|
||||||
|
|
||||||
volkLoadDevice(device);
|
volkLoadDevice(device);
|
||||||
|
|
||||||
|
@ -266,7 +265,7 @@ void VulkanDevice::CreateSurface()
|
||||||
{
|
{
|
||||||
if (!I_CreateVulkanSurface(instance, &surface))
|
if (!I_CreateVulkanSurface(instance, &surface))
|
||||||
{
|
{
|
||||||
I_Error("Could not create vulkan surface");
|
VulkanError("Could not create vulkan surface");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,8 +317,7 @@ void VulkanDevice::CreateInstance()
|
||||||
createInfo.ppEnabledExtensionNames = EnabledExtensions.data();
|
createInfo.ppEnabledExtensionNames = EnabledExtensions.data();
|
||||||
|
|
||||||
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
|
VkResult result = vkCreateInstance(&createInfo, nullptr, &instance);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create vulkan instance");
|
||||||
I_Error("Could not create vulkan instance");
|
|
||||||
|
|
||||||
volkLoadInstance(instance);
|
volkLoadInstance(instance);
|
||||||
|
|
||||||
|
@ -339,8 +337,7 @@ void VulkanDevice::CreateInstance()
|
||||||
createInfo.pfnUserCallback = DebugCallback;
|
createInfo.pfnUserCallback = DebugCallback;
|
||||||
createInfo.pUserData = this;
|
createInfo.pUserData = this;
|
||||||
result = vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger);
|
result = vkCreateDebugUtilsMessengerEXT(instance, &createInfo, nullptr, &debugMessenger);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkCreateDebugUtilsMessengerEXT failed");
|
||||||
I_Error("vkCreateDebugUtilsMessengerEXT failed");
|
|
||||||
|
|
||||||
DebugLayerActive = true;
|
DebugLayerActive = true;
|
||||||
}
|
}
|
||||||
|
@ -441,15 +438,13 @@ std::vector<VulkanPhysicalDevice> VulkanDevice::GetPhysicalDevices(VkInstance in
|
||||||
VkResult result = vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
VkResult result = vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||||
if (result == VK_ERROR_INITIALIZATION_FAILED) // Some drivers return this when a card does not support vulkan
|
if (result == VK_ERROR_INITIALIZATION_FAILED) // Some drivers return this when a card does not support vulkan
|
||||||
return {};
|
return {};
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkEnumeratePhysicalDevices failed");
|
||||||
I_Error("vkEnumeratePhysicalDevices failed");
|
|
||||||
if (deviceCount == 0)
|
if (deviceCount == 0)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::vector<VkPhysicalDevice> devices(deviceCount);
|
std::vector<VkPhysicalDevice> devices(deviceCount);
|
||||||
result = vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
|
result = vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data());
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkEnumeratePhysicalDevices failed (2)");
|
||||||
I_Error("vkEnumeratePhysicalDevices failed (2)");
|
|
||||||
|
|
||||||
std::vector<VulkanPhysicalDevice> devinfo(deviceCount);
|
std::vector<VulkanPhysicalDevice> devinfo(deviceCount);
|
||||||
for (size_t i = 0; i < devices.size(); i++)
|
for (size_t i = 0; i < devices.size(); i++)
|
||||||
|
@ -478,11 +473,11 @@ std::vector<const char *> VulkanDevice::GetPlatformExtensions()
|
||||||
{
|
{
|
||||||
uint32_t extensionCount = 0;
|
uint32_t extensionCount = 0;
|
||||||
if (!I_GetVulkanPlatformExtensions(&extensionCount, nullptr))
|
if (!I_GetVulkanPlatformExtensions(&extensionCount, nullptr))
|
||||||
I_Error("Cannot obtain number of Vulkan extensions");
|
VulkanError("Cannot obtain number of Vulkan extensions");
|
||||||
|
|
||||||
std::vector<const char *> extensions(extensionCount);
|
std::vector<const char *> extensions(extensionCount);
|
||||||
if (!I_GetVulkanPlatformExtensions(&extensionCount, extensions.data()))
|
if (!I_GetVulkanPlatformExtensions(&extensionCount, extensions.data()))
|
||||||
I_Error("Cannot obtain list of Vulkan extensions");
|
VulkanError("Cannot obtain list of Vulkan extensions");
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -490,12 +485,12 @@ void VulkanDevice::InitVolk()
|
||||||
{
|
{
|
||||||
if (volkInitialize() != VK_SUCCESS)
|
if (volkInitialize() != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
I_Error("Unable to find Vulkan");
|
VulkanError("Unable to find Vulkan");
|
||||||
}
|
}
|
||||||
auto iver = volkGetInstanceVersion();
|
auto iver = volkGetInstanceVersion();
|
||||||
if (iver == 0)
|
if (iver == 0)
|
||||||
{
|
{
|
||||||
I_Error("Vulkan not supported");
|
VulkanError("Vulkan not supported");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +526,46 @@ uint32_t VulkanDevice::FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
I_FatalError("failed to find suitable memory type!");
|
VulkanError("failed to find suitable memory type!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FString VkResultToString(VkResult result)
|
||||||
|
{
|
||||||
|
switch (result)
|
||||||
|
{
|
||||||
|
case VK_SUCCESS: return "success";
|
||||||
|
case VK_NOT_READY: return "not ready";
|
||||||
|
case VK_TIMEOUT: return "timeout";
|
||||||
|
case VK_EVENT_SET: return "event set";
|
||||||
|
case VK_EVENT_RESET: return "event reset";
|
||||||
|
case VK_INCOMPLETE: return "incomplete";
|
||||||
|
case VK_ERROR_OUT_OF_HOST_MEMORY: return "out of host memory";
|
||||||
|
case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "out of device memory";
|
||||||
|
case VK_ERROR_INITIALIZATION_FAILED: return "initialization failed";
|
||||||
|
case VK_ERROR_DEVICE_LOST: return "device lost";
|
||||||
|
case VK_ERROR_MEMORY_MAP_FAILED: return "memory map failed";
|
||||||
|
case VK_ERROR_LAYER_NOT_PRESENT: return "layer not present";
|
||||||
|
case VK_ERROR_EXTENSION_NOT_PRESENT: return "extension not present";
|
||||||
|
case VK_ERROR_FEATURE_NOT_PRESENT: return "feature not present";
|
||||||
|
case VK_ERROR_INCOMPATIBLE_DRIVER: return "incompatible driver";
|
||||||
|
case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects";
|
||||||
|
case VK_ERROR_FORMAT_NOT_SUPPORTED: return "format not supported";
|
||||||
|
case VK_ERROR_FRAGMENTED_POOL: return "fragmented pool";
|
||||||
|
case VK_ERROR_OUT_OF_POOL_MEMORY: return "out of pool memory";
|
||||||
|
case VK_ERROR_INVALID_EXTERNAL_HANDLE: return "invalid external handle";
|
||||||
|
case VK_ERROR_SURFACE_LOST_KHR: return "surface lost";
|
||||||
|
case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "native window in use";
|
||||||
|
case VK_SUBOPTIMAL_KHR: return "suboptimal";
|
||||||
|
case VK_ERROR_OUT_OF_DATE_KHR: return "out of date";
|
||||||
|
case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "incompatible display";
|
||||||
|
case VK_ERROR_VALIDATION_FAILED_EXT: return "validation failed";
|
||||||
|
case VK_ERROR_INVALID_SHADER_NV: return "invalid shader";
|
||||||
|
case VK_ERROR_FRAGMENTATION_EXT: return "fragmentation";
|
||||||
|
case VK_ERROR_NOT_PERMITTED_EXT: return "not permitted";
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
FString res;
|
||||||
|
res.Format("vkResult %d", (int)result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include "volk/volk.h"
|
#include "volk/volk.h"
|
||||||
#include "vk_mem_alloc/vk_mem_alloc.h"
|
#include "vk_mem_alloc/vk_mem_alloc.h"
|
||||||
|
#include "utility/doomerrors.h"
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -99,3 +100,20 @@ private:
|
||||||
static std::vector<const char *> GetPlatformExtensions();
|
static std::vector<const char *> GetPlatformExtensions();
|
||||||
static std::vector<VulkanPhysicalDevice> GetPhysicalDevices(VkInstance instance);
|
static std::vector<VulkanPhysicalDevice> GetPhysicalDevices(VkInstance instance);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FString VkResultToString(VkResult result);
|
||||||
|
|
||||||
|
inline void VulkanError(const char *text)
|
||||||
|
{
|
||||||
|
throw CVulkanError(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void CheckVulkanError(VkResult result, const char *text)
|
||||||
|
{
|
||||||
|
if (result >= VK_SUCCESS)
|
||||||
|
return;
|
||||||
|
|
||||||
|
FString msg;
|
||||||
|
msg.Format("%s: %s", text, VkResultToString(result).GetChars());
|
||||||
|
throw CVulkanError(msg.GetChars());
|
||||||
|
}
|
||||||
|
|
|
@ -393,8 +393,7 @@ inline VulkanSemaphore::VulkanSemaphore(VulkanDevice *device) : device(device)
|
||||||
VkSemaphoreCreateInfo semaphoreInfo = {};
|
VkSemaphoreCreateInfo semaphoreInfo = {};
|
||||||
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
|
||||||
VkResult result = vkCreateSemaphore(device->device, &semaphoreInfo, nullptr, &semaphore);
|
VkResult result = vkCreateSemaphore(device->device, &semaphoreInfo, nullptr, &semaphore);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create semaphore");
|
||||||
I_Error("Failed to create semaphore!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VulkanSemaphore::~VulkanSemaphore()
|
inline VulkanSemaphore::~VulkanSemaphore()
|
||||||
|
@ -409,8 +408,7 @@ inline VulkanFence::VulkanFence(VulkanDevice *device) : device(device)
|
||||||
VkFenceCreateInfo fenceInfo = {};
|
VkFenceCreateInfo fenceInfo = {};
|
||||||
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
||||||
VkResult result = vkCreateFence(device->device, &fenceInfo, nullptr, &fence);
|
VkResult result = vkCreateFence(device->device, &fenceInfo, nullptr, &fence);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create fence!");
|
||||||
I_Error("Failed to create fence!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VulkanFence::~VulkanFence()
|
inline VulkanFence::~VulkanFence()
|
||||||
|
@ -451,8 +449,7 @@ inline VulkanCommandPool::VulkanCommandPool(VulkanDevice *device, int queueFamil
|
||||||
poolInfo.flags = 0;
|
poolInfo.flags = 0;
|
||||||
|
|
||||||
VkResult result = vkCreateCommandPool(device->device, &poolInfo, nullptr, &pool);
|
VkResult result = vkCreateCommandPool(device->device, &poolInfo, nullptr, &pool);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create command pool");
|
||||||
I_Error("Could not create command pool");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VulkanCommandPool::~VulkanCommandPool()
|
inline VulkanCommandPool::~VulkanCommandPool()
|
||||||
|
@ -542,8 +539,7 @@ inline VulkanCommandBuffer::VulkanCommandBuffer(VulkanCommandPool *pool) : pool(
|
||||||
allocInfo.commandBufferCount = 1;
|
allocInfo.commandBufferCount = 1;
|
||||||
|
|
||||||
VkResult result = vkAllocateCommandBuffers(pool->device->device, &allocInfo, &buffer);
|
VkResult result = vkAllocateCommandBuffers(pool->device->device, &allocInfo, &buffer);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create command buffer");
|
||||||
I_Error("Could not create command buffer");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline VulkanCommandBuffer::~VulkanCommandBuffer()
|
inline VulkanCommandBuffer::~VulkanCommandBuffer()
|
||||||
|
@ -559,15 +555,13 @@ inline void VulkanCommandBuffer::begin()
|
||||||
beginInfo.pInheritanceInfo = nullptr;
|
beginInfo.pInheritanceInfo = nullptr;
|
||||||
|
|
||||||
VkResult result = vkBeginCommandBuffer(buffer, &beginInfo);
|
VkResult result = vkBeginCommandBuffer(buffer, &beginInfo);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not begin recording command buffer");
|
||||||
I_Error("Failed to begin recording command buffer!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void VulkanCommandBuffer::end()
|
inline void VulkanCommandBuffer::end()
|
||||||
{
|
{
|
||||||
VkResult result = vkEndCommandBuffer(buffer);
|
VkResult result = vkEndCommandBuffer(buffer);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not end command buffer recording");
|
||||||
I_Error("Failed to record command buffer!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void VulkanCommandBuffer::debugFullPipelineBarrier()
|
inline void VulkanCommandBuffer::debugFullPipelineBarrier()
|
||||||
|
@ -959,8 +953,7 @@ inline std::unique_ptr<VulkanDescriptorSet> VulkanDescriptorPool::allocate(Vulka
|
||||||
|
|
||||||
VkDescriptorSet descriptorSet;
|
VkDescriptorSet descriptorSet;
|
||||||
VkResult result = vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet);
|
VkResult result = vkAllocateDescriptorSets(device->device, &allocInfo, &descriptorSet);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not allocate descriptor sets");
|
||||||
I_FatalError("Could not allocate descriptor sets");
|
|
||||||
|
|
||||||
return std::make_unique<VulkanDescriptorSet>(device, this, descriptorSet);
|
return std::make_unique<VulkanDescriptorSet>(device, this, descriptorSet);
|
||||||
}
|
}
|
||||||
|
@ -979,8 +972,7 @@ inline VulkanQueryPool::~VulkanQueryPool()
|
||||||
inline bool VulkanQueryPool::getResults(uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void *data, VkDeviceSize stride, VkQueryResultFlags flags)
|
inline bool VulkanQueryPool::getResults(uint32_t firstQuery, uint32_t queryCount, size_t dataSize, void *data, VkDeviceSize stride, VkQueryResultFlags flags)
|
||||||
{
|
{
|
||||||
VkResult result = vkGetQueryPoolResults(device->device, pool, firstQuery, queryCount, dataSize, data, stride, flags);
|
VkResult result = vkGetQueryPoolResults(device->device, pool, firstQuery, queryCount, dataSize, data, stride, flags);
|
||||||
if (result != VK_SUCCESS && result != VK_NOT_READY)
|
CheckVulkanError(result, "vkGetQueryPoolResults failed");
|
||||||
I_Error("vkGetQueryPoolResults failed");
|
|
||||||
return result == VK_SUCCESS;
|
return result == VK_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,19 +63,19 @@ uint32_t VulkanSwapChain::AcquireImage(int width, int height, VulkanSemaphore *s
|
||||||
}
|
}
|
||||||
else if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY)
|
else if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_ERROR_OUT_OF_DEVICE_MEMORY)
|
||||||
{
|
{
|
||||||
I_FatalError("vkAcquireNextImageKHR failed: out of memory");
|
VulkanError("vkAcquireNextImageKHR failed: out of memory");
|
||||||
}
|
}
|
||||||
else if (result == VK_ERROR_DEVICE_LOST)
|
else if (result == VK_ERROR_DEVICE_LOST)
|
||||||
{
|
{
|
||||||
I_FatalError("vkAcquireNextImageKHR failed: device lost");
|
VulkanError("vkAcquireNextImageKHR failed: device lost");
|
||||||
}
|
}
|
||||||
else if (result == VK_ERROR_SURFACE_LOST_KHR)
|
else if (result == VK_ERROR_SURFACE_LOST_KHR)
|
||||||
{
|
{
|
||||||
I_FatalError("vkAcquireNextImageKHR failed: surface lost");
|
VulkanError("vkAcquireNextImageKHR failed: surface lost");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
I_FatalError("vkAcquireNextImageKHR failed");
|
VulkanError("vkAcquireNextImageKHR failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return imageIndex;
|
return imageIndex;
|
||||||
|
@ -102,19 +102,19 @@ void VulkanSwapChain::QueuePresent(uint32_t imageIndex, VulkanSemaphore *semapho
|
||||||
// The spec says we can recover from this.
|
// The spec says we can recover from this.
|
||||||
// However, if we are out of memory it is better to crash now than in some other weird place further away from the source of the problem.
|
// However, if we are out of memory it is better to crash now than in some other weird place further away from the source of the problem.
|
||||||
|
|
||||||
I_FatalError("vkQueuePresentKHR failed: out of memory");
|
VulkanError("vkQueuePresentKHR failed: out of memory");
|
||||||
}
|
}
|
||||||
else if (result == VK_ERROR_DEVICE_LOST)
|
else if (result == VK_ERROR_DEVICE_LOST)
|
||||||
{
|
{
|
||||||
I_FatalError("vkQueuePresentKHR failed: device lost");
|
VulkanError("vkQueuePresentKHR failed: device lost");
|
||||||
}
|
}
|
||||||
else if (result == VK_ERROR_SURFACE_LOST_KHR)
|
else if (result == VK_ERROR_SURFACE_LOST_KHR)
|
||||||
{
|
{
|
||||||
I_FatalError("vkQueuePresentKHR failed: surface lost");
|
VulkanError("vkQueuePresentKHR failed: surface lost");
|
||||||
}
|
}
|
||||||
else if (result != VK_SUCCESS)
|
else if (result != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
I_FatalError("vkQueuePresentKHR failed");
|
VulkanError("vkQueuePresentKHR failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,8 +225,7 @@ void VulkanSwapChain::CreateViews()
|
||||||
|
|
||||||
VkImageView view;
|
VkImageView view;
|
||||||
VkResult result = vkCreateImageView(device->device, &createInfo, nullptr, &view);
|
VkResult result = vkCreateImageView(device->device, &createInfo, nullptr, &view);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "Could not create image view for swapchain image");
|
||||||
I_Error("Could not create image view for swapchain image");
|
|
||||||
|
|
||||||
device->SetDebugObjectName("SwapChainImageView", (uint64_t)view, VK_OBJECT_TYPE_IMAGE_VIEW);
|
device->SetDebugObjectName("SwapChainImageView", (uint64_t)view, VK_OBJECT_TYPE_IMAGE_VIEW);
|
||||||
|
|
||||||
|
@ -238,7 +237,7 @@ void VulkanSwapChain::SelectFormat()
|
||||||
{
|
{
|
||||||
std::vector<VkSurfaceFormatKHR> surfaceFormats = GetSurfaceFormats();
|
std::vector<VkSurfaceFormatKHR> surfaceFormats = GetSurfaceFormats();
|
||||||
if (surfaceFormats.empty())
|
if (surfaceFormats.empty())
|
||||||
I_Error("No surface formats supported");
|
VulkanError("No surface formats supported");
|
||||||
|
|
||||||
if (surfaceFormats.size() == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED)
|
if (surfaceFormats.size() == 1 && surfaceFormats.front().format == VK_FORMAT_UNDEFINED)
|
||||||
{
|
{
|
||||||
|
@ -276,7 +275,7 @@ void VulkanSwapChain::SelectPresentMode()
|
||||||
std::vector<VkPresentModeKHR> presentModes = GetPresentModes();
|
std::vector<VkPresentModeKHR> presentModes = GetPresentModes();
|
||||||
|
|
||||||
if (presentModes.empty())
|
if (presentModes.empty())
|
||||||
I_Error("No surface present modes supported");
|
VulkanError("No surface present modes supported");
|
||||||
|
|
||||||
swapChainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
swapChainPresentMode = VK_PRESENT_MODE_FIFO_KHR;
|
||||||
if (vid_vsync)
|
if (vid_vsync)
|
||||||
|
@ -327,13 +326,11 @@ void VulkanSwapChain::GetImages()
|
||||||
{
|
{
|
||||||
uint32_t imageCount;
|
uint32_t imageCount;
|
||||||
VkResult result = vkGetSwapchainImagesKHR(device->device, swapChain, &imageCount, nullptr);
|
VkResult result = vkGetSwapchainImagesKHR(device->device, swapChain, &imageCount, nullptr);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkGetSwapchainImagesKHR failed");
|
||||||
I_Error("vkGetSwapchainImagesKHR failed");
|
|
||||||
|
|
||||||
swapChainImages.resize(imageCount);
|
swapChainImages.resize(imageCount);
|
||||||
result = vkGetSwapchainImagesKHR(device->device, swapChain, &imageCount, swapChainImages.data());
|
result = vkGetSwapchainImagesKHR(device->device, swapChain, &imageCount, swapChainImages.data());
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkGetSwapchainImagesKHR failed (2)");
|
||||||
I_Error("vkGetSwapchainImagesKHR failed (2)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanSwapChain::ReleaseViews()
|
void VulkanSwapChain::ReleaseViews()
|
||||||
|
@ -356,8 +353,7 @@ VkSurfaceCapabilitiesKHR VulkanSwapChain::GetSurfaceCapabilities()
|
||||||
{
|
{
|
||||||
VkSurfaceCapabilitiesKHR surfaceCapabilities;
|
VkSurfaceCapabilitiesKHR surfaceCapabilities;
|
||||||
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->surface, &surfaceCapabilities);
|
VkResult result = vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device->PhysicalDevice.Device, device->surface, &surfaceCapabilities);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed");
|
||||||
I_Error("vkGetPhysicalDeviceSurfaceCapabilitiesKHR failed");
|
|
||||||
return surfaceCapabilities;
|
return surfaceCapabilities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,15 +361,13 @@ std::vector<VkSurfaceFormatKHR> VulkanSwapChain::GetSurfaceFormats()
|
||||||
{
|
{
|
||||||
uint32_t surfaceFormatCount = 0;
|
uint32_t surfaceFormatCount = 0;
|
||||||
VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, nullptr);
|
VkResult result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, nullptr);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||||
I_Error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
if (surfaceFormatCount == 0)
|
||||||
else if (surfaceFormatCount == 0)
|
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
|
std::vector<VkSurfaceFormatKHR> surfaceFormats(surfaceFormatCount);
|
||||||
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, surfaceFormats.data());
|
result = vkGetPhysicalDeviceSurfaceFormatsKHR(device->PhysicalDevice.Device, device->surface, &surfaceFormatCount, surfaceFormats.data());
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
||||||
I_Error("vkGetPhysicalDeviceSurfaceFormatsKHR failed");
|
|
||||||
return surfaceFormats;
|
return surfaceFormats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,14 +375,12 @@ std::vector<VkPresentModeKHR> VulkanSwapChain::GetPresentModes()
|
||||||
{
|
{
|
||||||
uint32_t presentModeCount = 0;
|
uint32_t presentModeCount = 0;
|
||||||
VkResult result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, nullptr);
|
VkResult result = vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, nullptr);
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
||||||
I_Error("vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
if (presentModeCount == 0)
|
||||||
else if (presentModeCount == 0)
|
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
std::vector<VkPresentModeKHR> presentModes(presentModeCount);
|
||||||
vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, presentModes.data());
|
vkGetPhysicalDeviceSurfacePresentModesKHR(device->PhysicalDevice.Device, device->surface, &presentModeCount, presentModes.data());
|
||||||
if (result != VK_SUCCESS)
|
CheckVulkanError(result, "vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
||||||
I_Error("vkGetPhysicalDeviceSurfacePresentModesKHR failed");
|
|
||||||
return presentModes;
|
return presentModes;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,13 @@ public:
|
||||||
CFatalError(const char *message) : CDoomError(message) {}
|
CFatalError(const char *message) : CDoomError(message) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CVulkanError : public CDoomError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CVulkanError() : CDoomError() {}
|
||||||
|
CVulkanError(const char *message) : CDoomError(message) {}
|
||||||
|
};
|
||||||
|
|
||||||
void I_Error (const char *error, ...) GCCPRINTF(1,2);
|
void I_Error (const char *error, ...) GCCPRINTF(1,2);
|
||||||
void I_FatalError (const char *error, ...) GCCPRINTF(1,2);
|
void I_FatalError (const char *error, ...) GCCPRINTF(1,2);
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ void I_InitGraphics ()
|
||||||
{
|
{
|
||||||
Video = new Win32VulkanVideo();
|
Video = new Win32VulkanVideo();
|
||||||
}
|
}
|
||||||
catch (CRecoverableError &error)
|
catch (CVulkanError &error)
|
||||||
{
|
{
|
||||||
Printf(TEXTCOLOR_RED "Initialization of Vulkan failed: %s\n", error.what());
|
Printf(TEXTCOLOR_RED "Initialization of Vulkan failed: %s\n", error.what());
|
||||||
Video = new Win32GLVideo();
|
Video = new Win32GLVideo();
|
||||||
|
|
Loading…
Reference in a new issue