Compare commits
6 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
832a5e8852 | ||
|
96d1f0da2d | ||
|
597388ecda | ||
|
1cf6d7b7bb | ||
|
7bc9d0cdad | ||
|
dc0dbc50ab |
@@ -11,4 +11,10 @@ if [ -f "$SCRIPT_DIR/Ryujinx.Headless.SDL2" ]; then
|
|||||||
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
RYUJINX_BIN="Ryujinx.Headless.SDL2"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
env DOTNET_EnableAlternateStackCheck=1 "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
COMMAND="env DOTNET_EnableAlternateStackCheck=1"
|
||||||
|
|
||||||
|
if command -v gamemoderun > /dev/null 2>&1; then
|
||||||
|
COMMAND="$COMMAND gamemoderun"
|
||||||
|
fi
|
||||||
|
|
||||||
|
$COMMAND "$SCRIPT_DIR/$RYUJINX_BIN" "$@"
|
||||||
|
@@ -45,7 +45,7 @@ namespace Ryujinx.Audio.Backends.SDL2
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_supportSurroundConfiguration = spec.channels == 6;
|
_supportSurroundConfiguration = spec.channels >= 6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39,6 +39,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
public readonly bool SupportsViewportMask;
|
public readonly bool SupportsViewportMask;
|
||||||
public readonly bool SupportsViewportSwizzle;
|
public readonly bool SupportsViewportSwizzle;
|
||||||
public readonly bool SupportsIndirectParameters;
|
public readonly bool SupportsIndirectParameters;
|
||||||
|
public readonly bool SupportsDepthClipControl;
|
||||||
|
|
||||||
public readonly uint MaximumUniformBuffersPerStage;
|
public readonly uint MaximumUniformBuffersPerStage;
|
||||||
public readonly uint MaximumStorageBuffersPerStage;
|
public readonly uint MaximumStorageBuffersPerStage;
|
||||||
@@ -85,6 +86,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
bool supportsViewportMask,
|
bool supportsViewportMask,
|
||||||
bool supportsViewportSwizzle,
|
bool supportsViewportSwizzle,
|
||||||
bool supportsIndirectParameters,
|
bool supportsIndirectParameters,
|
||||||
|
bool supportsDepthClipControl,
|
||||||
uint maximumUniformBuffersPerStage,
|
uint maximumUniformBuffersPerStage,
|
||||||
uint maximumStorageBuffersPerStage,
|
uint maximumStorageBuffersPerStage,
|
||||||
uint maximumTexturesPerStage,
|
uint maximumTexturesPerStage,
|
||||||
@@ -127,6 +129,7 @@ namespace Ryujinx.Graphics.GAL
|
|||||||
SupportsViewportMask = supportsViewportMask;
|
SupportsViewportMask = supportsViewportMask;
|
||||||
SupportsViewportSwizzle = supportsViewportSwizzle;
|
SupportsViewportSwizzle = supportsViewportSwizzle;
|
||||||
SupportsIndirectParameters = supportsIndirectParameters;
|
SupportsIndirectParameters = supportsIndirectParameters;
|
||||||
|
SupportsDepthClipControl = supportsDepthClipControl;
|
||||||
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
|
MaximumUniformBuffersPerStage = maximumUniformBuffersPerStage;
|
||||||
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
|
MaximumStorageBuffersPerStage = maximumStorageBuffersPerStage;
|
||||||
MaximumTexturesPerStage = maximumTexturesPerStage;
|
MaximumTexturesPerStage = maximumTexturesPerStage;
|
||||||
|
@@ -22,7 +22,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||||||
private const ushort FileFormatVersionMajor = 1;
|
private const ushort FileFormatVersionMajor = 1;
|
||||||
private const ushort FileFormatVersionMinor = 2;
|
private const ushort FileFormatVersionMinor = 2;
|
||||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||||
private const uint CodeGenVersion = 5110;
|
private const uint CodeGenVersion = 5027;
|
||||||
|
|
||||||
private const string SharedTocFileName = "shared.toc";
|
private const string SharedTocFileName = "shared.toc";
|
||||||
private const string SharedDataFileName = "shared.data";
|
private const string SharedDataFileName = "shared.data";
|
||||||
|
@@ -165,6 +165,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
|||||||
|
|
||||||
public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask;
|
public bool QueryHostSupportsViewportMask() => _context.Capabilities.SupportsViewportMask;
|
||||||
|
|
||||||
|
public bool QueryHostSupportsDepthClipControl() => _context.Capabilities.SupportsDepthClipControl;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts a packed Maxwell texture format to the shader translator texture format.
|
/// Converts a packed Maxwell texture format to the shader translator texture format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -163,6 +163,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||||||
supportsViewportMask: HwCapabilities.SupportsViewportArray2,
|
supportsViewportMask: HwCapabilities.SupportsViewportArray2,
|
||||||
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
|
supportsViewportSwizzle: HwCapabilities.SupportsViewportSwizzle,
|
||||||
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
|
supportsIndirectParameters: HwCapabilities.SupportsIndirectParameters,
|
||||||
|
supportsDepthClipControl: true,
|
||||||
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
|
maximumUniformBuffersPerStage: 13, // TODO: Avoid hardcoding those limits here and get from driver?
|
||||||
maximumStorageBuffersPerStage: 16,
|
maximumStorageBuffersPerStage: 16,
|
||||||
maximumTexturesPerStage: 32,
|
maximumTexturesPerStage: 32,
|
||||||
|
@@ -367,6 +367,15 @@ namespace Ryujinx.Graphics.Shader
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queries whether the host supports depth clip control.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the GPU and driver supports depth clip control, false otherwise</returns>
|
||||||
|
bool QueryHostSupportsDepthClipControl()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Queries the point size from the GPU state, used when it is not explicitly set on the shader.
|
/// Queries the point size from the GPU state, used when it is not explicitly set on the shader.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@@ -246,7 +246,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
this.Store(StorageKind.Output, IoVariable.Position, null, Const(1), this.FPFusedMultiplyAdd(y, yScale, negativeOne));
|
this.Store(StorageKind.Output, IoVariable.Position, null, Const(1), this.FPFusedMultiplyAdd(y, yScale, negativeOne));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.Options.TargetApi == TargetApi.Vulkan && Config.GpuAccessor.QueryTransformDepthMinusOneToOne())
|
if (Config.GpuAccessor.QueryTransformDepthMinusOneToOne() && !Config.GpuAccessor.QueryHostSupportsDepthClipControl())
|
||||||
{
|
{
|
||||||
Operand z = this.Load(StorageKind.Output, IoVariable.Position, null, Const(2));
|
Operand z = this.Load(StorageKind.Output, IoVariable.Position, null, Const(2));
|
||||||
Operand w = this.Load(StorageKind.Output, IoVariable.Position, null, Const(3));
|
Operand w = this.Load(StorageKind.Output, IoVariable.Position, null, Const(3));
|
||||||
@@ -283,7 +283,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||||||
oldYLocal = null;
|
oldYLocal = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Config.Options.TargetApi == TargetApi.Vulkan && Config.GpuAccessor.QueryTransformDepthMinusOneToOne())
|
if (Config.GpuAccessor.QueryTransformDepthMinusOneToOne() && !Config.GpuAccessor.QueryHostSupportsDepthClipControl())
|
||||||
{
|
{
|
||||||
oldZLocal = Local();
|
oldZLocal = Local();
|
||||||
this.Copy(oldZLocal, this.Load(StorageKind.Output, IoVariable.Position, null, Const(2)));
|
this.Copy(oldZLocal, this.Load(StorageKind.Output, IoVariable.Position, null, Const(2)));
|
||||||
|
@@ -65,6 +65,13 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
return (formatFeatureFlags & flags) == flags;
|
return (formatFeatureFlags & flags) == flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool BufferFormatSupports(FormatFeatureFlags flags, VkFormat format)
|
||||||
|
{
|
||||||
|
_api.GetPhysicalDeviceFormatProperties(_physicalDevice, format, out var fp);
|
||||||
|
|
||||||
|
return (fp.BufferFeatures & flags) == flags;
|
||||||
|
}
|
||||||
|
|
||||||
public bool OptimalFormatSupports(FormatFeatureFlags flags, GAL.Format format)
|
public bool OptimalFormatSupports(FormatFeatureFlags flags, GAL.Format format)
|
||||||
{
|
{
|
||||||
var formatFeatureFlags = _optimalTable[(int)format];
|
var formatFeatureFlags = _optimalTable[(int)format];
|
||||||
|
@@ -21,6 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public uint[] AttachmentSamples { get; }
|
public uint[] AttachmentSamples { get; }
|
||||||
public VkFormat[] AttachmentFormats { get; }
|
public VkFormat[] AttachmentFormats { get; }
|
||||||
public int[] AttachmentIndices { get; }
|
public int[] AttachmentIndices { get; }
|
||||||
|
public uint AttachmentIntegerFormatMask { get; }
|
||||||
|
|
||||||
public int AttachmentsCount { get; }
|
public int AttachmentsCount { get; }
|
||||||
public int MaxColorAttachmentIndex => AttachmentIndices.Length > 0 ? AttachmentIndices[AttachmentIndices.Length - 1] : -1;
|
public int MaxColorAttachmentIndex => AttachmentIndices.Length > 0 ? AttachmentIndices[AttachmentIndices.Length - 1] : -1;
|
||||||
@@ -74,6 +75,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
int bindIndex = 0;
|
int bindIndex = 0;
|
||||||
|
uint attachmentIntegerFormatMask = 0;
|
||||||
|
|
||||||
foreach (ITexture color in colors)
|
foreach (ITexture color in colors)
|
||||||
{
|
{
|
||||||
@@ -89,6 +91,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
AttachmentFormats[index] = texture.VkFormat;
|
AttachmentFormats[index] = texture.VkFormat;
|
||||||
AttachmentIndices[index] = bindIndex;
|
AttachmentIndices[index] = bindIndex;
|
||||||
|
|
||||||
|
if (texture.Info.Format.IsInteger())
|
||||||
|
{
|
||||||
|
attachmentIntegerFormatMask |= 1u << bindIndex;
|
||||||
|
}
|
||||||
|
|
||||||
width = Math.Min(width, (uint)texture.Width);
|
width = Math.Min(width, (uint)texture.Width);
|
||||||
height = Math.Min(height, (uint)texture.Height);
|
height = Math.Min(height, (uint)texture.Height);
|
||||||
layers = Math.Min(layers, (uint)texture.Layers);
|
layers = Math.Min(layers, (uint)texture.Layers);
|
||||||
@@ -102,6 +109,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
bindIndex++;
|
bindIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
|
||||||
|
|
||||||
if (depthStencil is TextureView dsTexture && dsTexture.Valid)
|
if (depthStencil is TextureView dsTexture && dsTexture.Valid)
|
||||||
{
|
{
|
||||||
_attachments[count - 1] = dsTexture.GetImageViewForAttachment();
|
_attachments[count - 1] = dsTexture.GetImageViewForAttachment();
|
||||||
|
@@ -43,6 +43,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public readonly bool SupportsGeometryShader;
|
public readonly bool SupportsGeometryShader;
|
||||||
public readonly bool SupportsViewportArray2;
|
public readonly bool SupportsViewportArray2;
|
||||||
public readonly bool SupportsHostImportedMemory;
|
public readonly bool SupportsHostImportedMemory;
|
||||||
|
public readonly bool SupportsDepthClipControl;
|
||||||
public readonly uint MinSubgroupSize;
|
public readonly uint MinSubgroupSize;
|
||||||
public readonly uint MaxSubgroupSize;
|
public readonly uint MaxSubgroupSize;
|
||||||
public readonly ShaderStageFlags RequiredSubgroupSizeStages;
|
public readonly ShaderStageFlags RequiredSubgroupSizeStages;
|
||||||
@@ -79,6 +80,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
bool supportsGeometryShader,
|
bool supportsGeometryShader,
|
||||||
bool supportsViewportArray2,
|
bool supportsViewportArray2,
|
||||||
bool supportsHostImportedMemory,
|
bool supportsHostImportedMemory,
|
||||||
|
bool supportsDepthClipControl,
|
||||||
uint minSubgroupSize,
|
uint minSubgroupSize,
|
||||||
uint maxSubgroupSize,
|
uint maxSubgroupSize,
|
||||||
ShaderStageFlags requiredSubgroupSizeStages,
|
ShaderStageFlags requiredSubgroupSizeStages,
|
||||||
@@ -114,6 +116,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SupportsGeometryShader = supportsGeometryShader;
|
SupportsGeometryShader = supportsGeometryShader;
|
||||||
SupportsViewportArray2 = supportsViewportArray2;
|
SupportsViewportArray2 = supportsViewportArray2;
|
||||||
SupportsHostImportedMemory = supportsHostImportedMemory;
|
SupportsHostImportedMemory = supportsHostImportedMemory;
|
||||||
|
SupportsDepthClipControl = supportsDepthClipControl;
|
||||||
MinSubgroupSize = minSubgroupSize;
|
MinSubgroupSize = minSubgroupSize;
|
||||||
MaxSubgroupSize = maxSubgroupSize;
|
MaxSubgroupSize = maxSubgroupSize;
|
||||||
RequiredSubgroupSizeStages = requiredSubgroupSizeStages;
|
RequiredSubgroupSizeStages = requiredSubgroupSizeStages;
|
||||||
|
@@ -80,6 +80,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
private PipelineColorBlendAttachmentState[] _storedBlend;
|
private PipelineColorBlendAttachmentState[] _storedBlend;
|
||||||
|
|
||||||
|
private ulong _drawCountSinceBarrier;
|
||||||
public ulong DrawCount { get; private set; }
|
public ulong DrawCount { get; private set; }
|
||||||
public bool RenderPassActive { get; private set; }
|
public bool RenderPassActive { get; private set; }
|
||||||
|
|
||||||
@@ -133,6 +134,18 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public unsafe void Barrier()
|
public unsafe void Barrier()
|
||||||
{
|
{
|
||||||
|
if (_drawCountSinceBarrier != DrawCount)
|
||||||
|
{
|
||||||
|
_drawCountSinceBarrier = DrawCount;
|
||||||
|
|
||||||
|
// Barriers apparently have no effect inside a render pass on MoltenVK.
|
||||||
|
// As a workaround, end the render pass.
|
||||||
|
if (Gd.IsMoltenVk)
|
||||||
|
{
|
||||||
|
EndRenderPass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MemoryBarrier memoryBarrier = new MemoryBarrier()
|
MemoryBarrier memoryBarrier = new MemoryBarrier()
|
||||||
{
|
{
|
||||||
SType = StructureType.MemoryBarrier,
|
SType = StructureType.MemoryBarrier,
|
||||||
@@ -551,7 +564,6 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
(uint)maxDrawCount,
|
(uint)maxDrawCount,
|
||||||
(uint)stride);
|
(uint)stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -813,8 +825,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
public void SetDepthMode(DepthMode mode)
|
public void SetDepthMode(DepthMode mode)
|
||||||
{
|
{
|
||||||
// Currently this is emulated on the shader, because Vulkan had no support for changing the depth mode.
|
bool oldMode = _newState.DepthMode;
|
||||||
// In the future, we may want to use the VK_EXT_depth_clip_control extension to change it here.
|
_newState.DepthMode = mode == DepthMode.MinusOneToOne;
|
||||||
|
if (_newState.DepthMode != oldMode)
|
||||||
|
{
|
||||||
|
SignalStateChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDepthTest(DepthTestDescriptor depthTest)
|
public void SetDepthTest(DepthTestDescriptor depthTest)
|
||||||
@@ -1471,6 +1487,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan();
|
var dstAttachmentFormats = _newState.Internal.AttachmentFormats.AsSpan();
|
||||||
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
|
FramebufferParams.AttachmentFormats.CopyTo(dstAttachmentFormats);
|
||||||
|
_newState.Internal.AttachmentIntegerFormatMask = FramebufferParams.AttachmentIntegerFormatMask;
|
||||||
|
|
||||||
for (int i = FramebufferParams.AttachmentFormats.Length; i < dstAttachmentFormats.Length; i++)
|
for (int i = FramebufferParams.AttachmentFormats.Length; i < dstAttachmentFormats.Length; i++)
|
||||||
{
|
{
|
||||||
|
@@ -294,6 +294,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
int attachmentCount = 0;
|
int attachmentCount = 0;
|
||||||
int maxColorAttachmentIndex = -1;
|
int maxColorAttachmentIndex = -1;
|
||||||
|
uint attachmentIntegerFormatMask = 0;
|
||||||
|
|
||||||
for (int i = 0; i < Constants.MaxRenderTargets; i++)
|
for (int i = 0; i < Constants.MaxRenderTargets; i++)
|
||||||
{
|
{
|
||||||
@@ -301,6 +302,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
{
|
{
|
||||||
pipeline.Internal.AttachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.AttachmentFormats[i]);
|
pipeline.Internal.AttachmentFormats[attachmentCount++] = gd.FormatCapabilities.ConvertToVkFormat(state.AttachmentFormats[i]);
|
||||||
maxColorAttachmentIndex = i;
|
maxColorAttachmentIndex = i;
|
||||||
|
|
||||||
|
if (state.AttachmentFormats[i].IsInteger())
|
||||||
|
{
|
||||||
|
attachmentIntegerFormatMask |= 1u << i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -311,6 +317,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
pipeline.ColorBlendAttachmentStateCount = (uint)(maxColorAttachmentIndex + 1);
|
pipeline.ColorBlendAttachmentStateCount = (uint)(maxColorAttachmentIndex + 1);
|
||||||
pipeline.VertexAttributeDescriptionsCount = (uint)Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount);
|
pipeline.VertexAttributeDescriptionsCount = (uint)Math.Min(Constants.MaxVertexAttributes, state.VertexAttribCount);
|
||||||
|
pipeline.Internal.AttachmentIntegerFormatMask = attachmentIntegerFormatMask;
|
||||||
|
|
||||||
return pipeline;
|
return pipeline;
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using Ryujinx.Common.Memory;
|
using Ryujinx.Common.Memory;
|
||||||
using Silk.NET.Vulkan;
|
using Silk.NET.Vulkan;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Numerics;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Vulkan
|
namespace Ryujinx.Graphics.Vulkan
|
||||||
{
|
{
|
||||||
@@ -304,6 +305,12 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
|
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool DepthMode
|
||||||
|
{
|
||||||
|
get => ((Internal.Id9 >> 6) & 0x1) != 0UL;
|
||||||
|
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFBF) | ((value ? 1UL : 0UL) << 6);
|
||||||
|
}
|
||||||
|
|
||||||
public NativeArray<PipelineShaderStageCreateInfo> Stages;
|
public NativeArray<PipelineShaderStageCreateInfo> Stages;
|
||||||
public NativeArray<PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT> StageRequiredSubgroupSizes;
|
public NativeArray<PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT> StageRequiredSubgroupSizes;
|
||||||
public PipelineLayout PipelineLayout;
|
public PipelineLayout PipelineLayout;
|
||||||
@@ -331,6 +338,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
LineWidth = 1f;
|
LineWidth = 1f;
|
||||||
SamplesCount = 1;
|
SamplesCount = 1;
|
||||||
|
DepthMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe Auto<DisposablePipeline> CreateComputePipeline(
|
public unsafe Auto<DisposablePipeline> CreateComputePipeline(
|
||||||
@@ -407,7 +415,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
|
|
||||||
if (isMoltenVk)
|
if (isMoltenVk)
|
||||||
{
|
{
|
||||||
UpdateVertexAttributeDescriptions();
|
UpdateVertexAttributeDescriptions(gd);
|
||||||
}
|
}
|
||||||
|
|
||||||
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
|
||||||
@@ -482,6 +490,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
PScissors = pScissors
|
PScissors = pScissors
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (gd.Capabilities.SupportsDepthClipControl)
|
||||||
|
{
|
||||||
|
var viewportDepthClipControlState = new PipelineViewportDepthClipControlCreateInfoEXT()
|
||||||
|
{
|
||||||
|
SType = StructureType.PipelineViewportDepthClipControlCreateInfoExt,
|
||||||
|
NegativeOneToOne = DepthMode
|
||||||
|
};
|
||||||
|
|
||||||
|
viewportState.PNext = &viewportDepthClipControlState;
|
||||||
|
}
|
||||||
|
|
||||||
var multisampleState = new PipelineMultisampleStateCreateInfo
|
var multisampleState = new PipelineMultisampleStateCreateInfo
|
||||||
{
|
{
|
||||||
SType = StructureType.PipelineMultisampleStateCreateInfo,
|
SType = StructureType.PipelineMultisampleStateCreateInfo,
|
||||||
@@ -524,6 +543,27 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
MaxDepthBounds = MaxDepthBounds
|
MaxDepthBounds = MaxDepthBounds
|
||||||
};
|
};
|
||||||
|
|
||||||
|
uint blendEnables = 0;
|
||||||
|
|
||||||
|
if (gd.IsMoltenVk && Internal.AttachmentIntegerFormatMask != 0)
|
||||||
|
{
|
||||||
|
// Blend can't be enabled for integer formats, so let's make sure it is disabled.
|
||||||
|
uint attachmentIntegerFormatMask = Internal.AttachmentIntegerFormatMask;
|
||||||
|
|
||||||
|
while (attachmentIntegerFormatMask != 0)
|
||||||
|
{
|
||||||
|
int i = BitOperations.TrailingZeroCount(attachmentIntegerFormatMask);
|
||||||
|
|
||||||
|
if (Internal.ColorBlendAttachmentState[i].BlendEnable)
|
||||||
|
{
|
||||||
|
blendEnables |= 1u << i;
|
||||||
|
}
|
||||||
|
|
||||||
|
Internal.ColorBlendAttachmentState[i].BlendEnable = false;
|
||||||
|
attachmentIntegerFormatMask &= ~(1u << i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var colorBlendState = new PipelineColorBlendStateCreateInfo()
|
var colorBlendState = new PipelineColorBlendStateCreateInfo()
|
||||||
{
|
{
|
||||||
SType = StructureType.PipelineColorBlendStateCreateInfo,
|
SType = StructureType.PipelineColorBlendStateCreateInfo,
|
||||||
@@ -601,6 +641,15 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
};
|
};
|
||||||
|
|
||||||
gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle).ThrowOnError();
|
gd.Api.CreateGraphicsPipelines(device, cache, 1, &pipelineCreateInfo, null, &pipelineHandle).ThrowOnError();
|
||||||
|
|
||||||
|
// Restore previous blend enable values if we changed it.
|
||||||
|
while (blendEnables != 0)
|
||||||
|
{
|
||||||
|
int i = BitOperations.TrailingZeroCount(blendEnables);
|
||||||
|
|
||||||
|
Internal.ColorBlendAttachmentState[i].BlendEnable = true;
|
||||||
|
blendEnables &= ~(1u << i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
|
pipeline = new Auto<DisposablePipeline>(new DisposablePipeline(gd.Api, device, pipelineHandle));
|
||||||
@@ -623,7 +672,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateVertexAttributeDescriptions()
|
private void UpdateVertexAttributeDescriptions(VulkanRenderer gd)
|
||||||
{
|
{
|
||||||
// Vertex attributes exceeding the stride are invalid.
|
// Vertex attributes exceeding the stride are invalid.
|
||||||
// In metal, they cause glitches with the vertex shader fetching incorrect values.
|
// In metal, they cause glitches with the vertex shader fetching incorrect values.
|
||||||
@@ -633,30 +682,52 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
for (int index = 0; index < VertexAttributeDescriptionsCount; index++)
|
for (int index = 0; index < VertexAttributeDescriptionsCount; index++)
|
||||||
{
|
{
|
||||||
var attribute = Internal.VertexAttributeDescriptions[index];
|
var attribute = Internal.VertexAttributeDescriptions[index];
|
||||||
ref var vb = ref Internal.VertexBindingDescriptions[(int)attribute.Binding];
|
int vbIndex = GetVertexBufferIndex(attribute.Binding);
|
||||||
|
|
||||||
Format format = attribute.Format;
|
if (vbIndex >= 0)
|
||||||
|
|
||||||
while (vb.Stride != 0 && attribute.Offset + FormatTable.GetAttributeFormatSize(format) > vb.Stride)
|
|
||||||
{
|
{
|
||||||
Format newFormat = FormatTable.DropLastComponent(format);
|
ref var vb = ref Internal.VertexBindingDescriptions[vbIndex];
|
||||||
|
|
||||||
if (newFormat == format)
|
Format format = attribute.Format;
|
||||||
|
|
||||||
|
while (vb.Stride != 0 && attribute.Offset + FormatTable.GetAttributeFormatSize(format) > vb.Stride)
|
||||||
{
|
{
|
||||||
// That case means we failed to find a format that fits within the stride,
|
Format newFormat = FormatTable.DropLastComponent(format);
|
||||||
// so just restore the original format and give up.
|
|
||||||
format = attribute.Format;
|
if (newFormat == format)
|
||||||
break;
|
{
|
||||||
|
// That case means we failed to find a format that fits within the stride,
|
||||||
|
// so just restore the original format and give up.
|
||||||
|
format = attribute.Format;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
format = newFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
format = newFormat;
|
if (attribute.Format != format && gd.FormatCapabilities.BufferFormatSupports(FormatFeatureFlags.VertexBufferBit, format))
|
||||||
|
{
|
||||||
|
attribute.Format = format;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attribute.Format = format;
|
|
||||||
_vertexAttributeDescriptions2[index] = attribute;
|
_vertexAttributeDescriptions2[index] = attribute;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private int GetVertexBufferIndex(uint binding)
|
||||||
|
{
|
||||||
|
for (int index = 0; index < VertexBindingDescriptionsCount; index++)
|
||||||
|
{
|
||||||
|
if (Internal.VertexBindingDescriptions[index].Binding == binding)
|
||||||
|
{
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Stages.Dispose();
|
Stages.Dispose();
|
||||||
|
@@ -35,6 +35,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
public Array16<Rect2D> Scissors;
|
public Array16<Rect2D> Scissors;
|
||||||
public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
|
public Array8<PipelineColorBlendAttachmentState> ColorBlendAttachmentState;
|
||||||
public Array9<Format> AttachmentFormats;
|
public Array9<Format> AttachmentFormats;
|
||||||
|
public uint AttachmentIntegerFormatMask;
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
|
@@ -41,6 +41,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
"VK_EXT_subgroup_size_control",
|
"VK_EXT_subgroup_size_control",
|
||||||
"VK_NV_geometry_shader_passthrough",
|
"VK_NV_geometry_shader_passthrough",
|
||||||
"VK_NV_viewport_array2",
|
"VK_NV_viewport_array2",
|
||||||
|
"VK_EXT_depth_clip_control",
|
||||||
"VK_KHR_portability_subset" // As per spec, we should enable this if present.
|
"VK_KHR_portability_subset" // As per spec, we should enable this if present.
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -345,6 +346,17 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
features2.PNext = &supportedFeaturesRobustness2;
|
features2.PNext = &supportedFeaturesRobustness2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceDepthClipControlFeaturesEXT supportedFeaturesDepthClipControl = new PhysicalDeviceDepthClipControlFeaturesEXT()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
|
||||||
|
PNext = features2.PNext
|
||||||
|
};
|
||||||
|
|
||||||
|
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_depth_clip_control"))
|
||||||
|
{
|
||||||
|
features2.PNext = &supportedFeaturesDepthClipControl;
|
||||||
|
}
|
||||||
|
|
||||||
api.GetPhysicalDeviceFeatures2(physicalDevice.PhysicalDevice, &features2);
|
api.GetPhysicalDeviceFeatures2(physicalDevice.PhysicalDevice, &features2);
|
||||||
|
|
||||||
var supportedFeatures = features2.Features;
|
var supportedFeatures = features2.Features;
|
||||||
@@ -507,6 +519,21 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
pExtendedFeatures = &featuresCustomBorderColor;
|
pExtendedFeatures = &featuresCustomBorderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PhysicalDeviceDepthClipControlFeaturesEXT featuresDepthClipControl;
|
||||||
|
|
||||||
|
if (physicalDevice.IsDeviceExtensionPresent("VK_EXT_depth_clip_control") &&
|
||||||
|
supportedFeaturesDepthClipControl.DepthClipControl)
|
||||||
|
{
|
||||||
|
featuresDepthClipControl = new PhysicalDeviceDepthClipControlFeaturesEXT()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt,
|
||||||
|
PNext = pExtendedFeatures,
|
||||||
|
DepthClipControl = true
|
||||||
|
};
|
||||||
|
|
||||||
|
pExtendedFeatures = &featuresDepthClipControl;
|
||||||
|
}
|
||||||
|
|
||||||
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
|
var enabledExtensions = _requiredExtensions.Union(_desirableExtensions.Intersect(physicalDevice.DeviceExtensions)).ToArray();
|
||||||
|
|
||||||
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
|
IntPtr* ppEnabledExtensions = stackalloc IntPtr[enabledExtensions.Length];
|
||||||
|
@@ -216,6 +216,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt
|
SType = StructureType.PhysicalDeviceCustomBorderColorFeaturesExt
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PhysicalDeviceDepthClipControlFeaturesEXT featuresDepthClipControl = new PhysicalDeviceDepthClipControlFeaturesEXT()
|
||||||
|
{
|
||||||
|
SType = StructureType.PhysicalDeviceDepthClipControlFeaturesExt
|
||||||
|
};
|
||||||
|
|
||||||
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new PhysicalDevicePortabilitySubsetFeaturesKHR()
|
PhysicalDevicePortabilitySubsetFeaturesKHR featuresPortabilitySubset = new PhysicalDevicePortabilitySubsetFeaturesKHR()
|
||||||
{
|
{
|
||||||
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr
|
SType = StructureType.PhysicalDevicePortabilitySubsetFeaturesKhr
|
||||||
@@ -244,6 +249,14 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
features2.PNext = &featuresCustomBorderColor;
|
features2.PNext = &featuresCustomBorderColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool supportsDepthClipControl = _physicalDevice.IsDeviceExtensionPresent("VK_EXT_depth_clip_control");
|
||||||
|
|
||||||
|
if (supportsDepthClipControl)
|
||||||
|
{
|
||||||
|
featuresDepthClipControl.PNext = features2.PNext;
|
||||||
|
features2.PNext = &featuresDepthClipControl;
|
||||||
|
}
|
||||||
|
|
||||||
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
|
bool usePortability = _physicalDevice.IsDeviceExtensionPresent("VK_KHR_portability_subset");
|
||||||
|
|
||||||
if (usePortability)
|
if (usePortability)
|
||||||
@@ -310,6 +323,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
_physicalDevice.PhysicalDeviceFeatures.GeometryShader,
|
_physicalDevice.PhysicalDeviceFeatures.GeometryShader,
|
||||||
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
|
_physicalDevice.IsDeviceExtensionPresent("VK_NV_viewport_array2"),
|
||||||
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
|
_physicalDevice.IsDeviceExtensionPresent(ExtExternalMemoryHost.ExtensionName),
|
||||||
|
supportsDepthClipControl && featuresDepthClipControl.DepthClipControl,
|
||||||
propertiesSubgroupSizeControl.MinSubgroupSize,
|
propertiesSubgroupSizeControl.MinSubgroupSize,
|
||||||
propertiesSubgroupSizeControl.MaxSubgroupSize,
|
propertiesSubgroupSizeControl.MaxSubgroupSize,
|
||||||
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
|
propertiesSubgroupSizeControl.RequiredSubgroupSizeStages,
|
||||||
@@ -585,6 +599,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||||||
supportsViewportMask: Capabilities.SupportsViewportArray2,
|
supportsViewportMask: Capabilities.SupportsViewportArray2,
|
||||||
supportsViewportSwizzle: false,
|
supportsViewportSwizzle: false,
|
||||||
supportsIndirectParameters: true,
|
supportsIndirectParameters: true,
|
||||||
|
supportsDepthClipControl: Capabilities.SupportsDepthClipControl,
|
||||||
maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage,
|
maximumUniformBuffersPerStage: Constants.MaxUniformBuffersPerStage,
|
||||||
maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage,
|
maximumStorageBuffersPerStage: Constants.MaxStorageBuffersPerStage,
|
||||||
maximumTexturesPerStage: Constants.MaxTexturesPerStage,
|
maximumTexturesPerStage: Constants.MaxTexturesPerStage,
|
||||||
|
Reference in New Issue
Block a user