Commit e0ed0ea2 authored by Andreas Traczyk's avatar Andreas Traczyk
Browse files

vulkan(Windows): verify vulkan instance creation with vulkan-1.dll

Add another supplementary check using functions from the vulkan-1
module before trying with QVulkanInstance.

Gitlab: #746
Change-Id: I8975ef8765675aca95c4fee648853ea74c0c8ec9
parent 0e819a64
......@@ -20,6 +20,7 @@
#include "mainapplication.h"
#include "instancemanager.h"
#include "utils.h"
#include "version.h"
#include <QCryptographicHash>
......@@ -117,6 +118,19 @@ main(int argc, char* argv[])
#else
if (std::invoke([] {
#if defined(HAS_VULKAN) && !defined(Q_OS_LINUX)
// Somehow, several bug reports show that, on Windows, QVulkanInstance
// verification passes, but goes on to fail when creating the QQuickWindow
// with "Failed to initialize graphics backend for Vulkan".
// Here we allow platform-specific checks using native Vulkan libraries.
// Currently only implemented on Windows.
try {
Utils::testVulkanSupport();
} catch (const std::exception& e) {
qWarning() << "Vulkan instance cannot be created:" << e.what();
return false;
}
// Check using Qt's QVulkanInstance.
QVulkanInstance inst;
inst.setLayers({"VK_LAYER_KHRONOS_validation"});
bool ok = inst.create();
......@@ -128,6 +142,7 @@ main(int argc, char* argv[])
qWarning() << "VK_LAYER_KHRONOS_validation layer is not available.";
return false;
}
return true;
#else
return false;
......
......@@ -51,6 +51,51 @@
#include <windows.h>
#endif
void
Utils::testVulkanSupport()
{
#if defined(Q_OS_WIN)
// Checks Vulkan support using the vulkan functions loaded directly
// from vulkan-1.dll.
struct DllLoader
{
explicit DllLoader(const std::string& filename)
: module(LoadLibraryA(filename.c_str()))
{
if (module == nullptr) {
throw std::runtime_error("Can't load module.");
}
}
~DllLoader()
{
FreeLibrary(module);
}
HMODULE module;
} vk {"vulkan-1.dll"};
typedef void*(__stdcall * PFN_vkGetInstanceProcAddr)(void*, const char*);
auto vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
GetProcAddress(vk.module, "vkGetInstanceProcAddr");
if (!vkGetInstanceProcAddr) {
throw std::runtime_error("Missing vkGetInstanceProcAddr proc.");
}
typedef int(__stdcall * PFN_vkCreateInstance)(int*, void*, void**);
auto vkCreateInstance = (PFN_vkCreateInstance) vkGetInstanceProcAddr(vk.module,
"vkCreateInstance");
if (!vkCreateInstance) {
throw std::runtime_error("Missing vkCreateInstance proc.");
}
void* instance = 0;
int VkInstanceCreateInfo[16] = {1};
auto result = vkCreateInstance(VkInstanceCreateInfo, 0, &instance);
if (!instance || result != 0) {
throw std::runtime_error("Can't create Vulkan instance.");
}
#endif
}
bool
Utils::CreateStartupLink(const std::wstring& wstrAppName)
{
......
......@@ -56,6 +56,9 @@ class LRCInstance;
namespace Utils {
// Throws if Vulkan cannot be instantiated.
void testVulkanSupport();
// App System
bool CreateStartupLink(const std::wstring& wstrAppName);
void DeleteStartupLink(const std::wstring& wstrAppName);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment