summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/frontend/emu_window.h2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp13
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp35
-rw-r--r--src/video_core/renderer_vulkan/vk_pipeline_cache.cpp4
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp120
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h16
-rw-r--r--src/video_core/vulkan_common/vulkan_instance.cpp27
-rw-r--r--src/video_core/vulkan_common/vulkan_surface.cpp38
-rw-r--r--src/yuzu/bootmanager.cpp4
-rw-r--r--src/yuzu/configuration/configure_graphics.cpp2
-rw-r--r--src/yuzu/startup_checks.cpp2
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp27
13 files changed, 191 insertions, 101 deletions
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h
index ac1906d5e..95363b645 100644
--- a/src/core/frontend/emu_window.h
+++ b/src/core/frontend/emu_window.h
@@ -17,6 +17,8 @@ enum class WindowSystemType {
Windows,
X11,
Wayland,
+ Cocoa,
+ Android,
};
/**
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index 265ac9c85..0f86a8004 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -402,8 +402,10 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
ctx.AddCapability(spv::Capability::SparseResidency);
}
if (info.uses_demote_to_helper_invocation && profile.support_demote_to_helper_invocation) {
- ctx.AddExtension("SPV_EXT_demote_to_helper_invocation");
- ctx.AddCapability(spv::Capability::DemoteToHelperInvocationEXT);
+ if (profile.supported_spirv < 0x00010600) {
+ ctx.AddExtension("SPV_EXT_demote_to_helper_invocation");
+ }
+ ctx.AddCapability(spv::Capability::DemoteToHelperInvocation);
}
if (info.stores[IR::Attribute::ViewportIndex]) {
ctx.AddCapability(spv::Capability::MultiViewport);
@@ -426,12 +428,11 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id ||
info.uses_subgroup_shuffles) &&
profile.support_vote) {
- ctx.AddExtension("SPV_KHR_shader_ballot");
- ctx.AddCapability(spv::Capability::SubgroupBallotKHR);
+ ctx.AddCapability(spv::Capability::GroupNonUniformBallot);
+ ctx.AddCapability(spv::Capability::GroupNonUniformShuffle);
if (!profile.warp_size_potentially_larger_than_guest) {
// vote ops are only used when not taking the long path
- ctx.AddExtension("SPV_KHR_subgroup_vote");
- ctx.AddCapability(spv::Capability::SubgroupVoteKHR);
+ ctx.AddCapability(spv::Capability::GroupNonUniformVote);
}
}
if (info.uses_int64_bit_atomics && profile.support_int64_atomics) {
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
index 7ad0b08ac..fb2c792c1 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_control_flow.cpp
@@ -12,7 +12,7 @@ void EmitJoin(EmitContext&) {
void EmitDemoteToHelperInvocation(EmitContext& ctx) {
if (ctx.profile.support_demote_to_helper_invocation) {
- ctx.OpDemoteToHelperInvocationEXT();
+ ctx.OpDemoteToHelperInvocation();
} else {
const Id kill_label{ctx.OpLabel()};
const Id impossible_label{ctx.OpLabel()};
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
index 7cbbbfaa6..2c90f2368 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
@@ -6,6 +6,10 @@
namespace Shader::Backend::SPIRV {
namespace {
+Id SubgroupScope(EmitContext& ctx) {
+ return ctx.Const(static_cast<u32>(spv::Scope::Subgroup));
+}
+
Id GetThreadId(EmitContext& ctx) {
return ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id);
}
@@ -49,8 +53,9 @@ Id GetMaxThreadId(EmitContext& ctx, Id thread_id, Id clamp, Id segmentation_mask
}
Id SelectValue(EmitContext& ctx, Id in_range, Id value, Id src_thread_id) {
- return ctx.OpSelect(ctx.U32[1], in_range,
- ctx.OpSubgroupReadInvocationKHR(ctx.U32[1], value, src_thread_id), value);
+ return ctx.OpSelect(
+ ctx.U32[1], in_range,
+ ctx.OpGroupNonUniformShuffle(ctx.U32[1], SubgroupScope(ctx), value, src_thread_id), value);
}
Id GetUpperClamp(EmitContext& ctx, Id invocation_id, Id clamp) {
@@ -71,40 +76,46 @@ Id EmitLaneId(EmitContext& ctx) {
Id EmitVoteAll(EmitContext& ctx, Id pred) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
- return ctx.OpSubgroupAllKHR(ctx.U1, pred);
+ return ctx.OpGroupNonUniformAll(ctx.U1, SubgroupScope(ctx), pred);
}
- const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)};
+ const Id mask_ballot{
+ ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), ctx.true_value)};
const Id active_mask{WarpExtract(ctx, mask_ballot)};
- const Id ballot{WarpExtract(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))};
+ const Id ballot{
+ WarpExtract(ctx, ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred))};
const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)};
return ctx.OpIEqual(ctx.U1, lhs, active_mask);
}
Id EmitVoteAny(EmitContext& ctx, Id pred) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
- return ctx.OpSubgroupAnyKHR(ctx.U1, pred);
+ return ctx.OpGroupNonUniformAny(ctx.U1, SubgroupScope(ctx), pred);
}
- const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)};
+ const Id mask_ballot{
+ ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), ctx.true_value)};
const Id active_mask{WarpExtract(ctx, mask_ballot)};
- const Id ballot{WarpExtract(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))};
+ const Id ballot{
+ WarpExtract(ctx, ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred))};
const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)};
return ctx.OpINotEqual(ctx.U1, lhs, ctx.u32_zero_value);
}
Id EmitVoteEqual(EmitContext& ctx, Id pred) {
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
- return ctx.OpSubgroupAllEqualKHR(ctx.U1, pred);
+ return ctx.OpGroupNonUniformAllEqual(ctx.U1, SubgroupScope(ctx), pred);
}
- const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)};
+ const Id mask_ballot{
+ ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), ctx.true_value)};
const Id active_mask{WarpExtract(ctx, mask_ballot)};
- const Id ballot{WarpExtract(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))};
+ const Id ballot{
+ WarpExtract(ctx, ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred))};
const Id lhs{ctx.OpBitwiseXor(ctx.U32[1], ballot, active_mask)};
return ctx.OpLogicalOr(ctx.U1, ctx.OpIEqual(ctx.U1, lhs, ctx.u32_zero_value),
ctx.OpIEqual(ctx.U1, lhs, active_mask));
}
Id EmitSubgroupBallot(EmitContext& ctx, Id pred) {
- const Id ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], pred)};
+ const Id ballot{ctx.OpGroupNonUniformBallot(ctx.U32[4], SubgroupScope(ctx), pred)};
if (!ctx.profile.warp_size_potentially_larger_than_guest) {
return ctx.OpCompositeExtract(ctx.U32[1], ballot, 0U);
}
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
index 150413b04..29da442fa 100644
--- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
@@ -54,7 +54,7 @@ using VideoCommon::FileEnvironment;
using VideoCommon::GenericEnvironment;
using VideoCommon::GraphicsEnvironment;
-constexpr u32 CACHE_VERSION = 7;
+constexpr u32 CACHE_VERSION = 8;
template <typename Container>
auto MakeSpan(Container& container) {
@@ -289,7 +289,7 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, const Device& device
const auto& float_control{device.FloatControlProperties()};
const VkDriverIdKHR driver_id{device.GetDriverID()};
profile = Shader::Profile{
- .supported_spirv = device.IsKhrSpirv1_4Supported() ? 0x00010400U : 0x00010000U,
+ .supported_spirv = device.SupportedSpirvVersion(),
.unified_descriptor_binding = true,
.support_descriptor_aliasing = true,
.support_int8 = device.IsInt8Supported(),
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index ddecfca13..a16a8275b 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -74,23 +74,14 @@ enum class NvidiaArchitecture {
};
constexpr std::array REQUIRED_EXTENSIONS{
- VK_KHR_MAINTENANCE1_EXTENSION_NAME,
- VK_KHR_STORAGE_BUFFER_STORAGE_CLASS_EXTENSION_NAME,
- VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME,
- VK_KHR_16BIT_STORAGE_EXTENSION_NAME,
- VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
- VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
- VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
- VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME,
- VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
- VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME,
- VK_KHR_VARIABLE_POINTERS_EXTENSION_NAME,
VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
- VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME,
- VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME,
VK_EXT_ROBUSTNESS_2_EXTENSION_NAME,
+
+ // Core in 1.2, but required due to use of extension methods,
+ // and well-supported by drivers
+ VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME,
+ VK_KHR_DESCRIPTOR_UPDATE_TEMPLATE_EXTENSION_NAME,
VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME,
- VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME,
#ifdef _WIN32
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
#endif
@@ -99,6 +90,17 @@ constexpr std::array REQUIRED_EXTENSIONS{
#endif
};
+constexpr std::array REQUIRED_EXTENSIONS_BEFORE_1_2{
+ VK_KHR_8BIT_STORAGE_EXTENSION_NAME,
+ VK_KHR_SHADER_FLOAT_CONTROLS_EXTENSION_NAME,
+ VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME,
+ VK_KHR_DRIVER_PROPERTIES_EXTENSION_NAME,
+};
+
+constexpr std::array REQUIRED_EXTENSIONS_BEFORE_1_3{
+ VK_EXT_SHADER_DEMOTE_TO_HELPER_INVOCATION_EXTENSION_NAME,
+};
+
template <typename T>
void SetNext(void**& next, T& data) {
*next = &data;
@@ -327,7 +329,8 @@ NvidiaArchitecture GetNvidiaArchitecture(vk::PhysicalDevice physical,
Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR surface,
const vk::InstanceDispatch& dld_)
: instance{instance_}, dld{dld_}, physical{physical_}, properties{physical.GetProperties()},
- supported_extensions{GetSupportedExtensions(physical)},
+ instance_version{properties.apiVersion}, supported_extensions{GetSupportedExtensions(
+ physical)},
format_properties(GetFormatProperties(physical)) {
CheckSuitability(surface != nullptr);
SetupFamilies(surface);
@@ -451,8 +454,8 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
};
SetNext(next, variable_pointers);
- VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote{
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT,
+ VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures demote{
+ .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES,
.pNext = nullptr,
.shaderDemoteToHelperInvocation = true,
};
@@ -896,28 +899,51 @@ std::string Device::GetDriverName() const {
}
}
+static std::vector<const char*> ExtensionsRequiredForInstanceVersion(u32 available_version) {
+ std::vector<const char*> extensions{REQUIRED_EXTENSIONS.begin(), REQUIRED_EXTENSIONS.end()};
+
+ if (available_version < VK_API_VERSION_1_2) {
+ extensions.insert(extensions.end(), REQUIRED_EXTENSIONS_BEFORE_1_2.begin(),
+ REQUIRED_EXTENSIONS_BEFORE_1_2.end());
+ }
+
+ if (available_version < VK_API_VERSION_1_3) {
+ extensions.insert(extensions.end(), REQUIRED_EXTENSIONS_BEFORE_1_3.begin(),
+ REQUIRED_EXTENSIONS_BEFORE_1_3.end());
+ }
+
+ return extensions;
+}
+
void Device::CheckSuitability(bool requires_swapchain) const {
- std::bitset<REQUIRED_EXTENSIONS.size()> available_extensions;
- bool has_swapchain = false;
- for (const VkExtensionProperties& property : physical.EnumerateDeviceExtensionProperties()) {
- const std::string_view name{property.extensionName};
- for (size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) {
- if (available_extensions[i]) {
- continue;
- }
- available_extensions[i] = name == REQUIRED_EXTENSIONS[i];
- }
- has_swapchain = has_swapchain || name == VK_KHR_SWAPCHAIN_EXTENSION_NAME;
+ std::vector<const char*> required_extensions =
+ ExtensionsRequiredForInstanceVersion(instance_version);
+ std::vector<const char*> available_extensions;
+
+ if (requires_swapchain) {
+ required_extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
}
- for (size_t i = 0; i < REQUIRED_EXTENSIONS.size(); ++i) {
- if (available_extensions[i]) {
- continue;
+
+ auto extension_properties = physical.EnumerateDeviceExtensionProperties();
+
+ for (const VkExtensionProperties& property : extension_properties) {
+ available_extensions.push_back(property.extensionName);
+ }
+
+ bool has_all_required_extensions = true;
+ for (const char* requirement_name : required_extensions) {
+ const bool found =
+ std::ranges::any_of(available_extensions, [&](const char* extension_name) {
+ return std::strcmp(requirement_name, extension_name) == 0;
+ });
+
+ if (!found) {
+ LOG_ERROR(Render_Vulkan, "Missing required extension: {}", requirement_name);
+ has_all_required_extensions = false;
}
- LOG_ERROR(Render_Vulkan, "Missing required extension: {}", REQUIRED_EXTENSIONS[i]);
- throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT);
}
- if (requires_swapchain && !has_swapchain) {
- LOG_ERROR(Render_Vulkan, "Missing required extension: VK_KHR_swapchain");
+
+ if (!has_all_required_extensions) {
throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT);
}
@@ -940,9 +966,8 @@ void Device::CheckSuitability(bool requires_swapchain) const {
throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT);
}
}
- VkPhysicalDeviceShaderDemoteToHelperInvocationFeaturesEXT demote{};
- demote.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES_EXT;
+ VkPhysicalDeviceShaderDemoteToHelperInvocationFeatures demote{};
+ demote.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_DEMOTE_TO_HELPER_INVOCATION_FEATURES;
demote.pNext = nullptr;
VkPhysicalDeviceVariablePointerFeaturesKHR variable_pointers{};
@@ -960,7 +985,7 @@ void Device::CheckSuitability(bool requires_swapchain) const {
physical.GetFeatures2KHR(features2);
const VkPhysicalDeviceFeatures& features{features2.features};
- const std::array feature_report{
+ std::vector feature_report{
std::make_pair(features.robustBufferAccess, "robustBufferAccess"),
std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"),
std::make_pair(features.imageCubeArray, "imageCubeArray"),
@@ -983,27 +1008,30 @@ void Device::CheckSuitability(bool requires_swapchain) const {
"shaderStorageImageWriteWithoutFormat"),
std::make_pair(features.shaderClipDistance, "shaderClipDistance"),
std::make_pair(features.shaderCullDistance, "shaderCullDistance"),
- std::make_pair(demote.shaderDemoteToHelperInvocation, "shaderDemoteToHelperInvocation"),
std::make_pair(variable_pointers.variablePointers, "variablePointers"),
std::make_pair(variable_pointers.variablePointersStorageBuffer,
"variablePointersStorageBuffer"),
std::make_pair(robustness2.robustBufferAccess2, "robustBufferAccess2"),
std::make_pair(robustness2.robustImageAccess2, "robustImageAccess2"),
std::make_pair(robustness2.nullDescriptor, "nullDescriptor"),
+ std::make_pair(demote.shaderDemoteToHelperInvocation, "shaderDemoteToHelperInvocation"),
};
+
+ bool has_all_required_features = true;
for (const auto& [is_supported, name] : feature_report) {
- if (is_supported) {
- continue;
+ if (!is_supported) {
+ LOG_ERROR(Render_Vulkan, "Missing required feature: {}", name);
+ has_all_required_features = false;
}
- LOG_ERROR(Render_Vulkan, "Missing required feature: {}", name);
+ }
+
+ if (!has_all_required_features) {
throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT);
}
}
std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
- std::vector<const char*> extensions;
- extensions.reserve(8 + REQUIRED_EXTENSIONS.size());
- extensions.insert(extensions.begin(), REQUIRED_EXTENSIONS.begin(), REQUIRED_EXTENSIONS.end());
+ std::vector<const char*> extensions = ExtensionsRequiredForInstanceVersion(instance_version);
if (requires_surface) {
extensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
}
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index d7cc6c593..c85fbba77 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -211,11 +211,6 @@ public:
return khr_uniform_buffer_standard_layout;
}
- /// Returns true if the device supports VK_KHR_spirv_1_4.
- bool IsKhrSpirv1_4Supported() const {
- return khr_spirv_1_4;
- }
-
/// Returns true if the device supports VK_KHR_push_descriptor.
bool IsKhrPushDescriptorSupported() const {
return khr_push_descriptor;
@@ -316,6 +311,17 @@ public:
return ext_shader_atomic_int64;
}
+ /// Returns the minimum supported version of SPIR-V.
+ u32 SupportedSpirvVersion() const {
+ if (instance_version >= VK_API_VERSION_1_3) {
+ return 0x00010600U;
+ }
+ if (khr_spirv_1_4) {
+ return 0x00010400U;
+ }
+ return 0x00010000U;
+ }
+
/// Returns true when a known debugging tool is attached.
bool HasDebuggingToolAttached() const {
return has_renderdoc || has_nsight_graphics;
diff --git a/src/video_core/vulkan_common/vulkan_instance.cpp b/src/video_core/vulkan_common/vulkan_instance.cpp
index a082e3059..35e073e16 100644
--- a/src/video_core/vulkan_common/vulkan_instance.cpp
+++ b/src/video_core/vulkan_common/vulkan_instance.cpp
@@ -14,13 +14,15 @@
#include "video_core/vulkan_common/vulkan_wrapper.h"
// Include these late to avoid polluting previous headers
-#ifdef _WIN32
+#if defined(_WIN32)
#include <windows.h>
// ensure include order
#include <vulkan/vulkan_win32.h>
-#endif
-
-#if !defined(_WIN32) && !defined(__APPLE__)
+#elif defined(__APPLE__)
+#include <vulkan/vulkan_macos.h>
+#elif defined(__ANDROID__)
+#include <vulkan/vulkan_android.h>
+#else
#include <X11/Xlib.h>
#include <vulkan/vulkan_wayland.h>
#include <vulkan/vulkan_xlib.h>
@@ -39,8 +41,15 @@ namespace {
case Core::Frontend::WindowSystemType::Windows:
extensions.push_back(VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
break;
-#endif
-#if !defined(_WIN32) && !defined(__APPLE__)
+#elif defined(__APPLE__)
+ case Core::Frontend::WindowSystemType::Cocoa:
+ extensions.push_back(VK_MVK_MACOS_SURFACE_EXTENSION_NAME);
+ break;
+#elif defined(__ANDROID__)
+ case Core::Frontend::WindowSystemType::Android:
+ extensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
+ break;
+#else
case Core::Frontend::WindowSystemType::X11:
extensions.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
break;
@@ -59,6 +68,10 @@ namespace {
extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
}
extensions.push_back(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME);
+
+#ifdef __APPLE__
+ extensions.push_back(VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME);
+#endif
return extensions;
}
@@ -140,7 +153,7 @@ vk::Instance CreateInstance(const Common::DynamicLibrary& library, vk::InstanceD
}
vk::Instance instance =
std::async([&] {
- return vk::Instance::Create(required_version, layers, extensions, dld);
+ return vk::Instance::Create(available_version, layers, extensions, dld);
}).get();
if (!vk::Load(*instance, dld)) {
LOG_ERROR(Render_Vulkan, "Failed to load Vulkan instance function pointers");
diff --git a/src/video_core/vulkan_common/vulkan_surface.cpp b/src/video_core/vulkan_common/vulkan_surface.cpp
index 69f9c494b..fa9bafa20 100644
--- a/src/video_core/vulkan_common/vulkan_surface.cpp
+++ b/src/video_core/vulkan_common/vulkan_surface.cpp
@@ -11,9 +11,11 @@
#include <windows.h>
// ensure include order
#include <vulkan/vulkan_win32.h>
-#endif
-
-#if !defined(_WIN32) && !defined(__APPLE__)
+#elif defined(__APPLE__)
+#include <vulkan/vulkan_macos.h>
+#elif defined(__ANDROID__)
+#include <vulkan/vulkan_android.h>
+#else
#include <X11/Xlib.h>
#include <vulkan/vulkan_wayland.h>
#include <vulkan/vulkan_xlib.h>
@@ -40,8 +42,33 @@ vk::SurfaceKHR CreateSurface(const vk::Instance& instance,
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
}
}
-#endif
-#if !defined(_WIN32) && !defined(__APPLE__)
+#elif defined(__APPLE__)
+ if (window_info.type == Core::Frontend::WindowSystemType::Cocoa) {
+ const VkMacOSSurfaceCreateInfoMVK mvk_ci{VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
+ nullptr, 0, window_info.render_surface};
+ const auto vkCreateMacOSSurfaceMVK = reinterpret_cast<PFN_vkCreateMacOSSurfaceMVK>(
+ dld.vkGetInstanceProcAddr(*instance, "vkCreateMacOSSurfaceMVK"));
+ if (!vkCreateMacOSSurfaceMVK ||
+ vkCreateMacOSSurfaceMVK(*instance, &mvk_ci, nullptr, &unsafe_surface) != VK_SUCCESS) {
+ LOG_ERROR(Render_Vulkan, "Failed to initialize Metal surface");
+ throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
+ }
+ }
+#elif defined(__ANDROID__)
+ if (window_info.type == Core::Frontend::WindowSystemType::Android) {
+ const VkAndroidSurfaceCreateInfoKHR android_ci{
+ VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR, nullptr, 0,
+ reinterpret_cast<ANativeWindow*>(window_info.render_surface)};
+ const auto vkCreateAndroidSurfaceKHR = reinterpret_cast<PFN_vkCreateAndroidSurfaceKHR>(
+ dld.vkGetInstanceProcAddr(*instance, "vkCreateAndroidSurfaceKHR"));
+ if (!vkCreateAndroidSurfaceKHR ||
+ vkCreateAndroidSurfaceKHR(*instance, &android_ci, nullptr, &unsafe_surface) !=
+ VK_SUCCESS) {
+ LOG_ERROR(Render_Vulkan, "Failed to initialize Android surface");
+ throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
+ }
+ }
+#else
if (window_info.type == Core::Frontend::WindowSystemType::X11) {
const VkXlibSurfaceCreateInfoKHR xlib_ci{
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, nullptr, 0,
@@ -70,6 +97,7 @@ vk::SurfaceKHR CreateSurface(const vk::Instance& instance,
}
}
#endif
+
if (!unsafe_surface) {
LOG_ERROR(Render_Vulkan, "Presentation not supported on this platform");
throw vk::Exception(VK_ERROR_INITIALIZATION_FAILED);
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index c934069dd..ccf1c50f4 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -267,6 +267,10 @@ static Core::Frontend::WindowSystemType GetWindowSystemType() {
return Core::Frontend::WindowSystemType::X11;
else if (platform_name == QStringLiteral("wayland"))
return Core::Frontend::WindowSystemType::Wayland;
+ else if (platform_name == QStringLiteral("cocoa"))
+ return Core::Frontend::WindowSystemType::Cocoa;
+ else if (platform_name == QStringLiteral("android"))
+ return Core::Frontend::WindowSystemType::Android;
LOG_CRITICAL(Frontend, "Unknown Qt platform!");
return Core::Frontend::WindowSystemType::Windows;
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp
index f1385e972..20bc651f1 100644
--- a/src/yuzu/configuration/configure_graphics.cpp
+++ b/src/yuzu/configuration/configure_graphics.cpp
@@ -360,7 +360,7 @@ void ConfigureGraphics::RetrieveVulkanDevices() try {
vk::InstanceDispatch dld;
const Common::DynamicLibrary library = OpenLibrary();
- const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_0);
+ const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1);
const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
vulkan_devices.clear();
diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp
index ccdcf10fa..563818362 100644
--- a/src/yuzu/startup_checks.cpp
+++ b/src/yuzu/startup_checks.cpp
@@ -27,7 +27,7 @@ void CheckVulkan() {
Vulkan::vk::InstanceDispatch dld;
const Common::DynamicLibrary library = Vulkan::OpenLibrary();
const Vulkan::vk::Instance instance =
- Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_0);
+ Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_1);
} catch (const Vulkan::vk::Exception& exception) {
fmt::print(stderr, "Failed to initialize Vulkan: {}\n", exception.what());
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
index 25948328c..0d580fe4f 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_vk.cpp
@@ -51,11 +51,6 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
window_info.type = Core::Frontend::WindowSystemType::Windows;
window_info.render_surface = reinterpret_cast<void*>(wm.info.win.window);
break;
-#else
- case SDL_SYSWM_TYPE::SDL_SYSWM_WINDOWS:
- LOG_CRITICAL(Frontend, "Window manager subsystem Windows not compiled");
- std::exit(EXIT_FAILURE);
- break;
#endif
#ifdef SDL_VIDEO_DRIVER_X11
case SDL_SYSWM_TYPE::SDL_SYSWM_X11:
@@ -63,11 +58,6 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
window_info.display_connection = wm.info.x11.display;
window_info.render_surface = reinterpret_cast<void*>(wm.info.x11.window);
break;
-#else
- case SDL_SYSWM_TYPE::SDL_SYSWM_X11:
- LOG_CRITICAL(Frontend, "Window manager subsystem X11 not compiled");
- std::exit(EXIT_FAILURE);
- break;
#endif
#ifdef SDL_VIDEO_DRIVER_WAYLAND
case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND:
@@ -75,14 +65,21 @@ EmuWindow_SDL2_VK::EmuWindow_SDL2_VK(InputCommon::InputSubsystem* input_subsyste
window_info.display_connection = wm.info.wl.display;
window_info.render_surface = wm.info.wl.surface;
break;
-#else
- case SDL_SYSWM_TYPE::SDL_SYSWM_WAYLAND:
- LOG_CRITICAL(Frontend, "Window manager subsystem Wayland not compiled");
- std::exit(EXIT_FAILURE);
+#endif
+#ifdef SDL_VIDEO_DRIVER_COCOA
+ case SDL_SYSWM_TYPE::SDL_SYSWM_COCOA:
+ window_info.type = Core::Frontend::WindowSystemType::Cocoa;
+ window_info.render_surface = SDL_Metal_CreateView(render_window);
+ break;
+#endif
+#ifdef SDL_VIDEO_DRIVER_ANDROID
+ case SDL_SYSWM_TYPE::SDL_SYSWM_ANDROID:
+ window_info.type = Core::Frontend::WindowSystemType::Android;
+ window_info.render_surface = reinterpret_cast<void*>(wm.info.android.window);
break;
#endif
default:
- LOG_CRITICAL(Frontend, "Window manager subsystem not implemented");
+ LOG_CRITICAL(Frontend, "Window manager subsystem {} not implemented", wm.subsystem);
std::exit(EXIT_FAILURE);
break;
}