mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-31 02:34:11 +01:00 
			
		
		
		
	Merge pull request #9303 from liamwhite/new-vulkan-init
Vulkan: update initialization
This commit is contained in:
		
						commit
						c043ba8467
					
				
							
								
								
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							| @ -27,7 +27,7 @@ | ||||
|     url = https://github.com/KhronosGroup/Vulkan-Headers.git | ||||
| [submodule "sirit"] | ||||
|     path = externals/sirit | ||||
|     url = https://github.com/ReinUsesLisp/sirit | ||||
|     url = https://github.com/yuzu-emu/sirit | ||||
| [submodule "mbedtls"] | ||||
|     path = externals/mbedtls | ||||
|     url = https://github.com/yuzu-emu/mbedtls | ||||
|  | ||||
							
								
								
									
										2
									
								
								externals/sirit
									
									
									
									
										vendored
									
									
								
							
							
								
								
								
								
								
								
							
						
						
									
										2
									
								
								externals/sirit
									
									
									
									
										vendored
									
									
								
							| @ -1 +1 @@ | ||||
| Subproject commit aa292d56650bc28f2b2d75973fab2e61d0136f9c | ||||
| Subproject commit d7ad93a88864bda94e282e95028f90b5784e4d20 | ||||
| @ -17,6 +17,8 @@ enum class WindowSystemType { | ||||
|     Windows, | ||||
|     X11, | ||||
|     Wayland, | ||||
|     Cocoa, | ||||
|     Android, | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  | ||||
| @ -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) { | ||||
|  | ||||
| @ -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()}; | ||||
|  | ||||
| @ -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); | ||||
|     } | ||||
|  | ||||
| @ -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(), | ||||
|  | ||||
| @ -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; | ||||
|         } | ||||
|         LOG_ERROR(Render_Vulkan, "Missing required extension: {}", REQUIRED_EXTENSIONS[i]); | ||||
|         throw vk::Exception(VK_ERROR_EXTENSION_NOT_PRESENT); | ||||
| 
 | ||||
|     auto extension_properties = physical.EnumerateDeviceExtensionProperties(); | ||||
| 
 | ||||
|     for (const VkExtensionProperties& property : extension_properties) { | ||||
|         available_extensions.push_back(property.extensionName); | ||||
|     } | ||||
|     if (requires_swapchain && !has_swapchain) { | ||||
|         LOG_ERROR(Render_Vulkan, "Missing required extension: VK_KHR_swapchain"); | ||||
| 
 | ||||
|     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; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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); | ||||
|     } | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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"); | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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(); | ||||
|  | ||||
| @ -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()); | ||||
|  | ||||
| @ -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; | ||||
|     } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user