vulkan: Respect VK_KHR_portability_subset vertex stride alignment (#4419)

* vulkan: Respect VK_KHR_portability_subset vertex stride alignment

We were hardcoding alignment to 4, but by specs it can be any values that
is a power of 2.

This also enable VK_KHR_portability_subset if present as per specs
requirements.

* address gdkchan's comment

* Make NeedsVertexBufferAlignment internal
This commit is contained in:
Mary 2023-02-15 09:41:48 +01:00 committed by GitHub
parent 32450d45de
commit 17078ad929
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 24 additions and 16 deletions

View File

@ -8,11 +8,10 @@ namespace Ryujinx.Graphics.Vulkan
{ {
None = 0, None = 0,
VertexBufferAlignment4B = 1, NoTriangleFans = 1,
NoTriangleFans = 1 << 1, NoPointMode = 1 << 1,
NoPointMode = 1 << 2, No3DImageView = 1 << 2,
No3DImageView = 1 << 3, NoLodBias = 1 << 3
NoLodBias = 1 << 4
} }
readonly struct HardwareCapabilities readonly struct HardwareCapabilities
@ -40,6 +39,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly ShaderStageFlags RequiredSubgroupSizeStages; public readonly ShaderStageFlags RequiredSubgroupSizeStages;
public readonly SampleCountFlags SupportedSampleCounts; public readonly SampleCountFlags SupportedSampleCounts;
public readonly PortabilitySubsetFlags PortabilitySubset; public readonly PortabilitySubsetFlags PortabilitySubset;
public readonly uint VertexBufferAlignment;
public HardwareCapabilities( public HardwareCapabilities(
bool supportsIndexTypeUint8, bool supportsIndexTypeUint8,
@ -64,7 +64,8 @@ namespace Ryujinx.Graphics.Vulkan
uint maxSubgroupSize, uint maxSubgroupSize,
ShaderStageFlags requiredSubgroupSizeStages, ShaderStageFlags requiredSubgroupSizeStages,
SampleCountFlags supportedSampleCounts, SampleCountFlags supportedSampleCounts,
PortabilitySubsetFlags portabilitySubset) PortabilitySubsetFlags portabilitySubset,
uint vertexBufferAlignment)
{ {
SupportsIndexTypeUint8 = supportsIndexTypeUint8; SupportsIndexTypeUint8 = supportsIndexTypeUint8;
SupportsCustomBorderColor = supportsCustomBorderColor; SupportsCustomBorderColor = supportsCustomBorderColor;
@ -89,6 +90,7 @@ namespace Ryujinx.Graphics.Vulkan
RequiredSubgroupSizeStages = requiredSubgroupSizeStages; RequiredSubgroupSizeStages = requiredSubgroupSizeStages;
SupportedSampleCounts = supportedSampleCounts; SupportedSampleCounts = supportedSampleCounts;
PortabilitySubset = portabilitySubset; PortabilitySubset = portabilitySubset;
VertexBufferAlignment = vertexBufferAlignment;
} }
} }
} }

View File

@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Shader;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
@ -1136,7 +1137,7 @@ namespace Ryujinx.Graphics.Vulkan
buffer.Dispose(); buffer.Dispose();
if (!Gd.Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.VertexBufferAlignment4B) && if (Gd.Capabilities.VertexBufferAlignment < 2 &&
(vertexBuffer.Stride % FormatExtensions.MaxBufferFormatScalarSize) == 0) (vertexBuffer.Stride % FormatExtensions.MaxBufferFormatScalarSize) == 0)
{ {
buffer = new VertexBufferState( buffer = new VertexBufferState(

View File

@ -1,4 +1,5 @@
using Ryujinx.Graphics.GAL; using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
using Silk.NET.Vulkan; using Silk.NET.Vulkan;
using System; using System;
@ -253,7 +254,7 @@ namespace Ryujinx.Graphics.Vulkan
if (gd.NeedsVertexBufferAlignment(vbScalarSizes[i], out int alignment)) if (gd.NeedsVertexBufferAlignment(vbScalarSizes[i], out int alignment))
{ {
alignedStride = (vertexBuffer.Stride + (alignment - 1)) & -alignment; alignedStride = BitUtils.AlignUp(vertexBuffer.Stride, alignment);
} }
// TODO: Support divisor > 1 // TODO: Support divisor > 1

View File

@ -36,7 +36,8 @@ namespace Ryujinx.Graphics.Vulkan
"VK_KHR_shader_float16_int8", "VK_KHR_shader_float16_int8",
"VK_EXT_shader_subgroup_ballot", "VK_EXT_shader_subgroup_ballot",
"VK_EXT_subgroup_size_control", "VK_EXT_subgroup_size_control",
"VK_NV_geometry_shader_passthrough" "VK_NV_geometry_shader_passthrough",
"VK_KHR_portability_subset", // By spec, we should enable this if present.
}; };
public static string[] RequiredExtensions { get; } = new string[] public static string[] RequiredExtensions { get; } = new string[]

View File

@ -234,10 +234,12 @@ namespace Ryujinx.Graphics.Vulkan
Api.GetPhysicalDeviceFeatures2(_physicalDevice, &features2); Api.GetPhysicalDeviceFeatures2(_physicalDevice, &features2);
var portabilityFlags = PortabilitySubsetFlags.None; var portabilityFlags = PortabilitySubsetFlags.None;
uint vertexBufferAlignment = 1;
if (usePortability) if (usePortability)
{ {
portabilityFlags |= propertiesPortabilitySubset.MinVertexInputBindingStrideAlignment > 1 ? PortabilitySubsetFlags.VertexBufferAlignment4B : 0; vertexBufferAlignment = propertiesPortabilitySubset.MinVertexInputBindingStrideAlignment;
portabilityFlags |= featuresPortabilitySubset.TriangleFans ? 0 : PortabilitySubsetFlags.NoTriangleFans; portabilityFlags |= featuresPortabilitySubset.TriangleFans ? 0 : PortabilitySubsetFlags.NoTriangleFans;
portabilityFlags |= featuresPortabilitySubset.PointPolygons ? 0 : PortabilitySubsetFlags.NoPointMode; portabilityFlags |= featuresPortabilitySubset.PointPolygons ? 0 : PortabilitySubsetFlags.NoPointMode;
portabilityFlags |= featuresPortabilitySubset.ImageView2DOn3DImage ? 0 : PortabilitySubsetFlags.No3DImageView; portabilityFlags |= featuresPortabilitySubset.ImageView2DOn3DImage ? 0 : PortabilitySubsetFlags.No3DImageView;
@ -278,7 +280,8 @@ namespace Ryujinx.Graphics.Vulkan
propertiesSubgroupSizeControl.MaxSubgroupSize, propertiesSubgroupSizeControl.MaxSubgroupSize,
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages, propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
supportedSampleCounts, supportedSampleCounts,
portabilityFlags); portabilityFlags,
vertexBufferAlignment);
MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device, properties.Limits.MaxMemoryAllocationCount); MemoryAllocator = new MemoryAllocator(Api, _physicalDevice, _device, properties.Limits.MaxMemoryAllocationCount);
@ -636,11 +639,11 @@ namespace Ryujinx.Graphics.Vulkan
PrintGpuInformation(); PrintGpuInformation();
} }
public bool NeedsVertexBufferAlignment(int attrScalarAlignment, out int alignment) internal bool NeedsVertexBufferAlignment(int attrScalarAlignment, out int alignment)
{ {
if (Capabilities.PortabilitySubset.HasFlag(PortabilitySubsetFlags.VertexBufferAlignment4B)) if (Capabilities.VertexBufferAlignment > 1)
{ {
alignment = 4; alignment = (int)Capabilities.VertexBufferAlignment;
return true; return true;
} }