From 29a0ca23918092d252f440b2f55f68bb3c991366 Mon Sep 17 00:00:00 2001
From: ReinUsesLisp <reinuseslisp@airmail.cc>
Date: Mon, 29 Jun 2020 02:34:17 -0300
Subject: [PATCH] renderer_vulkan: Create a Vulkan 1.0 instance when 1.1 is not
 available

This commit doesn't make yuzu compatible with Vulkan 1.0 yet, it only
creates an 1.0 instance.
---
 .../renderer_vulkan/renderer_vulkan.cpp       |  5 +++-
 src/video_core/renderer_vulkan/wrapper.cpp    | 23 +++++++++++++++----
 src/video_core/renderer_vulkan/wrapper.h      |  4 +++-
 3 files changed, 26 insertions(+), 6 deletions(-)

diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
index 6e49699d0..6f9eadbeb 100644
--- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp
+++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp
@@ -180,7 +180,10 @@ vk::Instance CreateInstance(Common::DynamicLibrary& library, vk::InstanceDispatc
         }
     }
 
-    vk::Instance instance = vk::Instance::Create(layers, extensions, dld);
+    // Limit the maximum version of Vulkan to avoid using untested version.
+    const u32 version = std::min(vk::AvailableVersion(dld), static_cast<u32>(VK_API_VERSION_1_1));
+
+    vk::Instance instance = vk::Instance::Create(version, layers, extensions, dld);
     if (!instance) {
         LOG_ERROR(Render_Vulkan, "Failed to create Vulkan instance");
         return {};
diff --git a/src/video_core/renderer_vulkan/wrapper.cpp b/src/video_core/renderer_vulkan/wrapper.cpp
index 013865aa4..56055af1b 100644
--- a/src/video_core/renderer_vulkan/wrapper.cpp
+++ b/src/video_core/renderer_vulkan/wrapper.cpp
@@ -10,6 +10,7 @@
 #include <vector>
 
 #include "common/common_types.h"
+#include "common/logging/log.h"
 
 #include "video_core/renderer_vulkan/wrapper.h"
 
@@ -375,18 +376,17 @@ VkResult Free(VkDevice device, VkCommandPool handle, Span<VkCommandBuffer> buffe
     return VK_SUCCESS;
 }
 
-Instance Instance::Create(Span<const char*> layers, Span<const char*> extensions,
+Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
                           InstanceDispatch& dld) noexcept {
-    static constexpr VkApplicationInfo application_info{
+    const VkApplicationInfo application_info{
         .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
         .pNext = nullptr,
         .pApplicationName = "yuzu Emulator",
         .applicationVersion = VK_MAKE_VERSION(0, 1, 0),
         .pEngineName = "yuzu Emulator",
         .engineVersion = VK_MAKE_VERSION(0, 1, 0),
-        .apiVersion = VK_API_VERSION_1_1,
+        .apiVersion = version,
     };
-
     const VkInstanceCreateInfo ci{
         .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
         .pNext = nullptr,
@@ -775,6 +775,21 @@ VkPhysicalDeviceMemoryProperties PhysicalDevice::GetMemoryProperties() const noe
     return properties;
 }
 
+u32 AvailableVersion(const InstanceDispatch& dld) noexcept {
+    PFN_vkEnumerateInstanceVersion vkEnumerateInstanceVersion;
+    if (!Proc(vkEnumerateInstanceVersion, dld, "vkEnumerateInstanceVersion")) {
+        // If the procedure is not found, Vulkan 1.0 is assumed
+        return VK_API_VERSION_1_0;
+    }
+    u32 version;
+    if (const VkResult result = vkEnumerateInstanceVersion(&version); result != VK_SUCCESS) {
+        LOG_ERROR(Render_Vulkan, "vkEnumerateInstanceVersion returned {}, assuming Vulkan 1.1",
+                  ToString(result));
+        return VK_API_VERSION_1_1;
+    }
+    return version;
+}
+
 std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
     const InstanceDispatch& dld) {
     u32 num;
diff --git a/src/video_core/renderer_vulkan/wrapper.h b/src/video_core/renderer_vulkan/wrapper.h
index b9d3fedc1..748a94d2f 100644
--- a/src/video_core/renderer_vulkan/wrapper.h
+++ b/src/video_core/renderer_vulkan/wrapper.h
@@ -563,7 +563,7 @@ class Instance : public Handle<VkInstance, NoOwner, InstanceDispatch> {
 
 public:
     /// Creates a Vulkan instance. Use "operator bool" for error handling.
-    static Instance Create(Span<const char*> layers, Span<const char*> extensions,
+    static Instance Create(u32 version, Span<const char*> layers, Span<const char*> extensions,
                            InstanceDispatch& dld) noexcept;
 
     /// Enumerates physical devices.
@@ -1048,6 +1048,8 @@ private:
     const DeviceDispatch* dld;
 };
 
+u32 AvailableVersion(const InstanceDispatch& dld) noexcept;
+
 std::optional<std::vector<VkExtensionProperties>> EnumerateInstanceExtensionProperties(
     const InstanceDispatch& dld);