aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan/VulkanRenderer.cs')
-rw-r--r--Ryujinx.Graphics.Vulkan/VulkanRenderer.cs96
1 files changed, 90 insertions, 6 deletions
diff --git a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index 5c77cb00..f1922efe 100644
--- a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -3,6 +3,7 @@ using Ryujinx.Common.Logging;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader;
using Ryujinx.Graphics.Shader.Translation;
+using Ryujinx.Graphics.Vulkan.MoltenVK;
using Ryujinx.Graphics.Vulkan.Queries;
using Silk.NET.Vulkan;
using Silk.NET.Vulkan.Extensions.EXT;
@@ -77,6 +78,8 @@ namespace Ryujinx.Graphics.Vulkan
internal bool IsAmdWindows { get; private set; }
internal bool IsIntelWindows { get; private set; }
internal bool IsAmdGcn { get; private set; }
+ internal bool IsMoltenVk { get; private set; }
+ internal bool IsTBDR { get; private set; }
public string GpuVendor { get; private set; }
public string GpuRenderer { get; private set; }
public string GpuVersion { get; private set; }
@@ -93,6 +96,14 @@ namespace Ryujinx.Graphics.Vulkan
Shaders = new HashSet<ShaderCollection>();
Textures = new HashSet<ITexture>();
Samplers = new HashSet<SamplerHolder>();
+
+ if (OperatingSystem.IsMacOS())
+ {
+ MVKInitialization.Initialize();
+
+ // Any device running on MacOS is using MoltenVK, even Intel and AMD vendors.
+ IsMoltenVk = true;
+ }
}
private unsafe void LoadFeatures(string[] supportedExtensions, uint maxQueueCount, uint queueFamilyIndex)
@@ -161,7 +172,10 @@ namespace Ryujinx.Graphics.Vulkan
properties2.PNext = &propertiesTransformFeedback;
}
- Api.GetPhysicalDeviceProperties2(_physicalDevice, &properties2);
+ PhysicalDevicePortabilitySubsetPropertiesKHR propertiesPortabilitySubset = new PhysicalDevicePortabilitySubsetPropertiesKHR()
+ {
+ SType = StructureType.PhysicalDevicePortabilitySubsetPropertiesKhr
+ };
PhysicalDeviceFeatures2 features2 = new PhysicalDeviceFeatures2()
{
@@ -183,6 +197,11 @@ namespace Ryujinx.Graphics.Vulkan
SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt
};
+ PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new PhysicalDevicePortabilitySubsetFeaturesKHR()
+ {
+ SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr
+ };
+
if (supportedExtensions.Contains("VK_EXT_robustness2"))
{
features2.PNext = &featuresRobustness2;
@@ -200,8 +219,31 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &featuresCustomBorderColor;
}
+ bool usePortability = supportedExtensions.Contains("VK_KHR_portability_subset");
+
+ if (usePortability)
+ {
+ propertiesPortabilitySubset.PNext = properties2.PNext;
+ properties2.PNext = &propertiesPortabilitySubset;
+
+ featuresPortabilitySubset.PNext = features2.PNext;
+ features2.PNext = &featuresPortabilitySubset;
+ }
+
+ Api.GetPhysicalDeviceProperties2(_physicalDevice, &properties2);
Api.GetPhysicalDeviceFeatures2(_physicalDevice, &features2);
+ var portabilityFlags = PortabilitySubsetFlags.None;
+
+ if (usePortability)
+ {
+ portabilityFlags |= propertiesPortabilitySubset.MinVertexInputBindingStrideAlignment > 1 ? PortabilitySubsetFlags.VertexBufferAlignment4B : 0;
+ portabilityFlags |= featuresPortabilitySubset.TriangleFans ? 0 : PortabilitySubsetFlags.NoTriangleFans;
+ portabilityFlags |= featuresPortabilitySubset.PointPolygons ? 0 : PortabilitySubsetFlags.NoPointMode;
+ portabilityFlags |= featuresPortabilitySubset.ImageView2DOn3DImage ? 0 : PortabilitySubsetFlags.No3DImageView;
+ portabilityFlags |= featuresPortabilitySubset.SamplerMipLodBias ? 0 : PortabilitySubsetFlags.NoLodBias;
+ }
+
bool customBorderColorSupported = supportedExtensions.Contains("VK_EXT_custom_border_color") &&
featuresCustomBorderColor.CustomBorderColors &&
featuresCustomBorderColor.CustomBorderColorWithoutFormat;
@@ -224,7 +266,7 @@ namespace Ryujinx.Graphics.Vulkan
supportedExtensions.Contains(ExtConditionalRendering.ExtensionName),
supportedExtensions.Contains(ExtExtendedDynamicState.ExtensionName),
features2.Features.MultiViewport,
- featuresRobustness2.NullDescriptor,
+ featuresRobustness2.NullDescriptor || IsMoltenVk,
supportedExtensions.Contains(KhrPushDescriptor.ExtensionName),
supportsTransformFeedback,
propertiesTransformFeedback.TransformFeedbackQueries,
@@ -232,7 +274,8 @@ namespace Ryujinx.Graphics.Vulkan
propertiesSubgroupSizeControl.MinSubgroupSize,
propertiesSubgroupSizeControl.MaxSubgroupSize,
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
- supportedSampleCounts);
+ supportedSampleCounts,
+ portabilityFlags);
MemoryAllocator = new MemoryAllocator(Api, _device, properties.Limits.MaxMemoryAllocationCount);
@@ -413,6 +456,36 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsR4G4B4A4Format = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags,
GAL.Format.R4G4B4A4Unorm);
+ bool supportsAstcFormats = FormatCapabilities.OptimalFormatsSupport(compressedFormatFeatureFlags,
+ GAL.Format.Astc4x4Unorm,
+ GAL.Format.Astc5x4Unorm,
+ GAL.Format.Astc5x5Unorm,
+ GAL.Format.Astc6x5Unorm,
+ GAL.Format.Astc6x6Unorm,
+ GAL.Format.Astc8x5Unorm,
+ GAL.Format.Astc8x6Unorm,
+ GAL.Format.Astc8x8Unorm,
+ GAL.Format.Astc10x5Unorm,
+ GAL.Format.Astc10x6Unorm,
+ GAL.Format.Astc10x8Unorm,
+ GAL.Format.Astc10x10Unorm,
+ GAL.Format.Astc12x10Unorm,
+ GAL.Format.Astc12x12Unorm,
+ GAL.Format.Astc4x4Srgb,
+ GAL.Format.Astc5x4Srgb,
+ GAL.Format.Astc5x5Srgb,
+ GAL.Format.Astc6x5Srgb,
+ GAL.Format.Astc6x6Srgb,
+ GAL.Format.Astc8x5Srgb,
+ GAL.Format.Astc8x6Srgb,
+ GAL.Format.Astc8x8Srgb,
+ GAL.Format.Astc10x5Srgb,
+ GAL.Format.Astc10x6Srgb,
+ GAL.Format.Astc10x8Srgb,
+ GAL.Format.Astc10x10Srgb,
+ GAL.Format.Astc12x10Srgb,
+ GAL.Format.Astc12x12Srgb);
+
PhysicalDeviceVulkan12Features featuresVk12 = new PhysicalDeviceVulkan12Features()
{
SType = StructureType.PhysicalDeviceVulkan12Features
@@ -434,7 +507,9 @@ namespace Ryujinx.Graphics.Vulkan
GpuVendor,
hasFrontFacingBug: IsIntelWindows,
hasVectorIndexingBug: Vendor == Vendor.Qualcomm,
- supportsAstcCompression: features2.Features.TextureCompressionAstcLdr,
+ needsFragmentOutputSpecialization: IsMoltenVk,
+ reduceShaderPrecision: IsMoltenVk,
+ supportsAstcCompression: features2.Features.TextureCompressionAstcLdr && supportsAstcFormats,
supportsBc123Compression: supportsBc123CompressionFormat,
supportsBc45Compression: supportsBc45CompressionFormat,
supportsBc67Compression: supportsBc67CompressionFormat,
@@ -515,12 +590,13 @@ 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;
GpuVendor = vendorName;
GpuRenderer = Marshal.PtrToStringAnsi((IntPtr)properties.DeviceName);
GpuVersion = $"Vulkan v{ParseStandardVulkanVersion(properties.ApiVersion)}, Driver v{ParseDriverVersion(ref properties)}";
- IsAmdGcn = Vendor == Vendor.Amd && VendorUtils.AmdGcnRegex().IsMatch(GpuRenderer);
+ IsAmdGcn = !IsMoltenVk && Vendor == Vendor.Amd && VendorUtils.AmdGcnRegex().IsMatch(GpuRenderer);
Logger.Notice.Print(LogClass.Gpu, $"{GpuVendor} {GpuRenderer} ({GpuVersion})");
}
@@ -531,6 +607,7 @@ namespace Ryujinx.Graphics.Vulkan
{
GAL.PrimitiveTopology.Quads => GAL.PrimitiveTopology.Triangles,
GAL.PrimitiveTopology.QuadStrip => GAL.PrimitiveTopology.TriangleStrip,
+ GAL.PrimitiveTopology.TriangleFan => Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.NoTriangleFans) ? GAL.PrimitiveTopology.Triangles : topology,
_ => topology
};
}
@@ -540,6 +617,7 @@ namespace Ryujinx.Graphics.Vulkan
return topology switch
{
GAL.PrimitiveTopology.Quads => true,
+ GAL.PrimitiveTopology.TriangleFan => Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.NoTriangleFans),
_ => false
};
}
@@ -553,7 +631,13 @@ namespace Ryujinx.Graphics.Vulkan
public bool NeedsVertexBufferAlignment(int attrScalarAlignment, out int alignment)
{
- if (Vendor != Vendor.Nvidia)
+ if (Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.VertexBufferAlignment4B))
+ {
+ alignment = 4;
+
+ return true;
+ }
+ else if (Vendor != Vendor.Nvidia)
{
// Vulkan requires that vertex attributes are globally aligned by their component size,
// so buffer strides that don't divide by the largest scalar element are invalid.