diff --git a/Ryujinx.Graphics.Vulkan/BufferManager.cs b/Ryujinx.Graphics.Vulkan/BufferManager.cs index f324037123..9c50e6ff38 100644 --- a/Ryujinx.Graphics.Vulkan/BufferManager.cs +++ b/Ryujinx.Graphics.Vulkan/BufferManager.cs @@ -14,6 +14,12 @@ namespace Ryujinx.Graphics.Vulkan MemoryPropertyFlags.HostCoherentBit | MemoryPropertyFlags.HostCachedBit; + // Some drivers don't expose a "HostCached" memory type, + // so we need those alternative flags for the allocation to succeed there. + private const MemoryPropertyFlags DefaultBufferMemoryAltFlags = + MemoryPropertyFlags.HostVisibleBit | + MemoryPropertyFlags.HostCoherentBit; + private const MemoryPropertyFlags DeviceLocalBufferMemoryFlags = MemoryPropertyFlags.DeviceLocalBit; @@ -94,9 +100,21 @@ namespace Ryujinx.Graphics.Vulkan gd.Api.CreateBuffer(_device, in bufferCreateInfo, null, out var buffer).ThrowOnError(); gd.Api.GetBufferMemoryRequirements(_device, buffer, out var requirements); - var allocateFlags = deviceLocal ? DeviceLocalBufferMemoryFlags : DefaultBufferMemoryFlags; + MemoryPropertyFlags allocateFlags; + MemoryPropertyFlags allocateFlagsAlt; - var allocation = gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, requirements, allocateFlags); + if (deviceLocal) + { + allocateFlags = DeviceLocalBufferMemoryFlags; + allocateFlagsAlt = DeviceLocalBufferMemoryFlags; + } + else + { + allocateFlags = DefaultBufferMemoryFlags; + allocateFlagsAlt = DefaultBufferMemoryAltFlags; + } + + var allocation = gd.MemoryAllocator.AllocateDeviceMemory(_physicalDevice, requirements, allocateFlags, allocateFlagsAlt); if (allocation.Memory.Handle == 0UL) { diff --git a/Ryujinx.Graphics.Vulkan/FramebufferParams.cs b/Ryujinx.Graphics.Vulkan/FramebufferParams.cs index 751ef5ebf0..84ac0b051d 100644 --- a/Ryujinx.Graphics.Vulkan/FramebufferParams.cs +++ b/Ryujinx.Graphics.Vulkan/FramebufferParams.cs @@ -23,7 +23,7 @@ namespace Ryujinx.Graphics.Vulkan public int[] AttachmentIndices { get; } public int AttachmentsCount { get; } - public int MaxColorAttachmentIndex { get; } + public int MaxColorAttachmentIndex => AttachmentIndices.Length > 0 ? AttachmentIndices[AttachmentIndices.Length - 1] : -1; public bool HasDepthStencil { get; } public int ColorAttachmentsCount => AttachmentsCount - (HasDepthStencil ? 1 : 0); @@ -67,7 +67,6 @@ namespace Ryujinx.Graphics.Vulkan AttachmentSamples = new uint[count]; AttachmentFormats = new VkFormat[count]; AttachmentIndices = new int[count]; - MaxColorAttachmentIndex = colors.Length - 1; uint width = uint.MaxValue; uint height = uint.MaxValue; diff --git a/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs b/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs index eea4e60b35..83c0a32430 100644 --- a/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs +++ b/Ryujinx.Graphics.Vulkan/MemoryAllocator.cs @@ -27,7 +27,16 @@ namespace Ryujinx.Graphics.Vulkan MemoryRequirements requirements, MemoryPropertyFlags flags = 0) { - int memoryTypeIndex = FindSuitableMemoryTypeIndex(_api, physicalDevice, requirements.MemoryTypeBits, flags); + return AllocateDeviceMemory(physicalDevice, requirements, flags, flags); + } + + public MemoryAllocation AllocateDeviceMemory( + PhysicalDevice physicalDevice, + MemoryRequirements requirements, + MemoryPropertyFlags flags, + MemoryPropertyFlags alternativeFlags) + { + int memoryTypeIndex = FindSuitableMemoryTypeIndex(_api, physicalDevice, requirements.MemoryTypeBits, flags, alternativeFlags); if (memoryTypeIndex < 0) { return default; @@ -56,21 +65,35 @@ namespace Ryujinx.Graphics.Vulkan return newBl.Allocate(size, alignment, map); } - private static int FindSuitableMemoryTypeIndex(Vk api, PhysicalDevice physicalDevice, uint memoryTypeBits, MemoryPropertyFlags flags) + private static int FindSuitableMemoryTypeIndex( + Vk api, + PhysicalDevice physicalDevice, + uint memoryTypeBits, + MemoryPropertyFlags flags, + MemoryPropertyFlags alternativeFlags) { + int bestCandidateIndex = -1; + api.GetPhysicalDeviceMemoryProperties(physicalDevice, out var properties); for (int i = 0; i < properties.MemoryTypeCount; i++) { var type = properties.MemoryTypes[i]; - if ((memoryTypeBits & (1 << i)) != 0 && type.PropertyFlags.HasFlag(flags)) + if ((memoryTypeBits & (1 << i)) != 0) { - return i; + if (type.PropertyFlags.HasFlag(flags)) + { + return i; + } + else if (type.PropertyFlags.HasFlag(alternativeFlags)) + { + bestCandidateIndex = i; + } } } - return -1; + return bestCandidateIndex; } public void Dispose() diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index 1c0c836bba..c4a9f2df56 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -1344,8 +1344,7 @@ namespace Ryujinx.Graphics.Vulkan var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan(); FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats); - int maxAttachmentIndex = FramebufferParams.MaxColorAttachmentIndex + (FramebufferParams.HasDepthStencil ? 1 : 0); - for (int i = FramebufferParams.AttachmentFormats.Length; i <= maxAttachmentIndex; i++) + for (int i = FramebufferParams.AttachmentFormats.Length; i < dstAttachmentFormats.Length; i++) { dstAttachmentFormats[i] = 0; } diff --git a/Ryujinx.Graphics.Vulkan/Vendor.cs b/Ryujinx.Graphics.Vulkan/Vendor.cs index 087d6e9dca..5e0290c0a6 100644 --- a/Ryujinx.Graphics.Vulkan/Vendor.cs +++ b/Ryujinx.Graphics.Vulkan/Vendor.cs @@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.Vulkan Intel, Nvidia, ARM, + Broadcom, Qualcomm, Apple, Unknown @@ -28,6 +29,7 @@ namespace Ryujinx.Graphics.Vulkan 0x106B => Vendor.Apple, 0x10DE => Vendor.Nvidia, 0x13B5 => Vendor.ARM, + 0x14E4 => Vendor.Broadcom, 0x8086 => Vendor.Intel, 0x5143 => Vendor.Qualcomm, _ => Vendor.Unknown @@ -43,6 +45,7 @@ namespace Ryujinx.Graphics.Vulkan 0x106B => "Apple", 0x10DE => "NVIDIA", 0x13B5 => "ARM", + 0x14E4 => "Broadcom", 0x1AE0 => "Google", 0x5143 => "Qualcomm", 0x8086 => "Intel", diff --git a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs index fe9462aa3e..d9dcc0b25c 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs @@ -162,7 +162,6 @@ namespace Ryujinx.Graphics.Vulkan if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.ErrorBitExt)) { Logger.Error?.Print(LogClass.Gpu, msg); - //throw new Exception(msg); } else if (messageSeverity.HasFlag(DebugUtilsMessageSeverityFlagsEXT.WarningBitExt)) { @@ -379,14 +378,34 @@ namespace Ryujinx.Graphics.Vulkan SType = StructureType.PhysicalDeviceFeatures2 }; - PhysicalDeviceCustomBorderColorFeaturesEXT featuresCustomBorderColorSupported = new PhysicalDeviceCustomBorderColorFeaturesEXT() + PhysicalDeviceVulkan11Features supportedFeaturesVk11 = new PhysicalDeviceVulkan11Features() { - SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt + SType = StructureType.PhysicalDeviceVulkan11Features, + PNext = features2.PNext + }; + + features2.PNext = &supportedFeaturesVk11; + + PhysicalDeviceCustomBorderColorFeaturesEXT supportedFeaturesCustomBorderColor = new PhysicalDeviceCustomBorderColorFeaturesEXT() + { + SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt, + PNext = features2.PNext }; if (supportedExtensions.Contains("VK_EXT_custom_border_color")) { - features2.PNext = &featuresCustomBorderColorSupported; + features2.PNext = &supportedFeaturesCustomBorderColor; + } + + PhysicalDeviceTransformFeedbackFeaturesEXT supportedFeaturesTransformFeedback = new PhysicalDeviceTransformFeedbackFeaturesEXT() + { + SType = StructureType.PhysicalDeviceTransformFeedbackFeaturesExt, + PNext = features2.PNext + }; + + if (supportedExtensions.Contains(ExtTransformFeedback.ExtensionName)) + { + features2.PNext = &supportedFeaturesTransformFeedback; } PhysicalDeviceRobustness2FeaturesEXT supportedFeaturesRobustness2 = new PhysicalDeviceRobustness2FeaturesEXT() @@ -408,41 +427,48 @@ namespace Ryujinx.Graphics.Vulkan var features = new PhysicalDeviceFeatures() { DepthBiasClamp = true, - DepthClamp = true, - DualSrcBlend = true, + DepthClamp = supportedFeatures.DepthClamp, + DualSrcBlend = supportedFeatures.DualSrcBlend, FragmentStoresAndAtomics = true, GeometryShader = supportedFeatures.GeometryShader, ImageCubeArray = true, IndependentBlend = true, LogicOp = supportedFeatures.LogicOp, - MultiViewport = true, + MultiViewport = supportedFeatures.MultiViewport, PipelineStatisticsQuery = supportedFeatures.PipelineStatisticsQuery, SamplerAnisotropy = true, ShaderClipDistance = true, ShaderFloat64 = supportedFeatures.ShaderFloat64, - ShaderImageGatherExtended = true, + ShaderImageGatherExtended = supportedFeatures.ShaderImageGatherExtended, ShaderStorageImageMultisample = supportedFeatures.ShaderStorageImageMultisample, // ShaderStorageImageReadWithoutFormat = true, // ShaderStorageImageWriteWithoutFormat = true, - TessellationShader = true, + TessellationShader = supportedFeatures.TessellationShader, VertexPipelineStoresAndAtomics = true, RobustBufferAccess = useRobustBufferAccess }; void* pExtendedFeatures = null; - var featuresTransformFeedback = new PhysicalDeviceTransformFeedbackFeaturesEXT() - { - SType = StructureType.PhysicalDeviceTransformFeedbackFeaturesExt, - PNext = pExtendedFeatures, - TransformFeedback = true - }; + PhysicalDeviceTransformFeedbackFeaturesEXT featuresTransformFeedback; - pExtendedFeatures = &featuresTransformFeedback; + if (supportedExtensions.Contains(ExtTransformFeedback.ExtensionName)) + { + featuresTransformFeedback = new PhysicalDeviceTransformFeedbackFeaturesEXT() + { + SType = StructureType.PhysicalDeviceTransformFeedbackFeaturesExt, + PNext = pExtendedFeatures, + TransformFeedback = supportedFeaturesTransformFeedback.TransformFeedback + }; + + pExtendedFeatures = &featuresTransformFeedback; + } + + PhysicalDeviceRobustness2FeaturesEXT featuresRobustness2; if (supportedExtensions.Contains("VK_EXT_robustness2")) { - var featuresRobustness2 = new PhysicalDeviceRobustness2FeaturesEXT() + featuresRobustness2 = new PhysicalDeviceRobustness2FeaturesEXT() { SType = StructureType.PhysicalDeviceRobustness2FeaturesExt, PNext = pExtendedFeatures, @@ -465,7 +491,7 @@ namespace Ryujinx.Graphics.Vulkan { SType = StructureType.PhysicalDeviceVulkan11Features, PNext = pExtendedFeatures, - ShaderDrawParameters = true + ShaderDrawParameters = supportedFeaturesVk11.ShaderDrawParameters }; pExtendedFeatures = &featuresVk11; @@ -526,8 +552,8 @@ namespace Ryujinx.Graphics.Vulkan PhysicalDeviceCustomBorderColorFeaturesEXT featuresCustomBorderColor; if (supportedExtensions.Contains("VK_EXT_custom_border_color") && - featuresCustomBorderColorSupported.CustomBorderColors && - featuresCustomBorderColorSupported.CustomBorderColorWithoutFormat) + supportedFeaturesCustomBorderColor.CustomBorderColors && + supportedFeaturesCustomBorderColor.CustomBorderColorWithoutFormat) { featuresCustomBorderColor = new PhysicalDeviceCustomBorderColorFeaturesEXT() { diff --git a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs index f1922efed0..029ad4b967 100644 --- a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs +++ b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs @@ -590,7 +590,11 @@ namespace Ryujinx.Graphics.Vulkan IsAmdWindows = Vendor == Vendor.Amd && RuntimeInformation.IsOSPlatform(OSPlatform.Windows); IsIntelWindows = Vendor == Vendor.Intel && RuntimeInformation.IsOSPlatform(OSPlatform.Windows); - IsTBDR = IsMoltenVk || Vendor == Vendor.Qualcomm || Vendor == Vendor.ARM || Vendor == Vendor.ImgTec; + IsTBDR = IsMoltenVk || + Vendor == Vendor.Qualcomm || + Vendor == Vendor.ARM || + Vendor == Vendor.Broadcom || + Vendor == Vendor.ImgTec; GpuVendor = vendorName; GpuRenderer = Marshal.PtrToStringAnsi((IntPtr)properties.DeviceName); diff --git a/Ryujinx.Graphics.Vulkan/Window.cs b/Ryujinx.Graphics.Vulkan/Window.cs index d37dd7e969..27ebb0de67 100644 --- a/Ryujinx.Graphics.Vulkan/Window.cs +++ b/Ryujinx.Graphics.Vulkan/Window.cs @@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Vulkan ImageSharingMode = SharingMode.Exclusive, ImageArrayLayers = 1, PreTransform = capabilities.CurrentTransform, - CompositeAlpha = CompositeAlphaFlagsKHR.OpaqueBitKhr, + CompositeAlpha = ChooseCompositeAlpha(capabilities.SupportedCompositeAlpha), PresentMode = ChooseSwapPresentMode(presentModes, _vsyncEnabled), Clipped = true, OldSwapchain = oldSwapchain @@ -182,6 +182,22 @@ namespace Ryujinx.Graphics.Vulkan return availableFormats[0]; } + private static CompositeAlphaFlagsKHR ChooseCompositeAlpha(CompositeAlphaFlagsKHR supportedFlags) + { + if (supportedFlags.HasFlag(CompositeAlphaFlagsKHR.OpaqueBitKhr)) + { + return CompositeAlphaFlagsKHR.OpaqueBitKhr; + } + else if (supportedFlags.HasFlag(CompositeAlphaFlagsKHR.PreMultipliedBitKhr)) + { + return CompositeAlphaFlagsKHR.PreMultipliedBitKhr; + } + else + { + return CompositeAlphaFlagsKHR.InheritBitKhr; + } + } + private static PresentModeKHR ChooseSwapPresentMode(PresentModeKHR[] availablePresentModes, bool vsyncEnabled) { if (!vsyncEnabled && availablePresentModes.Contains(PresentModeKHR.ImmediateKhr)) @@ -192,10 +208,6 @@ namespace Ryujinx.Graphics.Vulkan { return PresentModeKHR.MailboxKhr; } - else if (availablePresentModes.Contains(PresentModeKHR.FifoKhr)) - { - return PresentModeKHR.FifoKhr; - } else { return PresentModeKHR.FifoKhr;