diff --git a/Directory.Packages.props b/Directory.Packages.props
index a93247547..e73701629 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -39,9 +39,9 @@
-
-
-
+
+
+
diff --git a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
index 952867642..07c7e2618 100644
--- a/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
+++ b/src/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
@@ -32,6 +32,7 @@ namespace Ryujinx.Graphics.Vulkan
public readonly bool SupportsConditionalRendering;
public readonly bool SupportsExtendedDynamicState;
public readonly bool SupportsExtendedDynamicState2;
+ public readonly bool SupportsExtendedDynamicState3;
public readonly bool SupportsMultiView;
public readonly bool SupportsNullDescriptors;
public readonly bool SupportsPushDescriptors;
@@ -72,6 +73,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsConditionalRendering,
bool supportsExtendedDynamicState,
bool supportsExtendedDynamicState2,
+ bool supportsExtendedDynamicState3,
bool supportsMultiView,
bool supportsNullDescriptors,
bool supportsPushDescriptors,
@@ -111,6 +113,7 @@ namespace Ryujinx.Graphics.Vulkan
SupportsConditionalRendering = supportsConditionalRendering;
SupportsExtendedDynamicState = supportsExtendedDynamicState;
SupportsExtendedDynamicState2 = supportsExtendedDynamicState2;
+ SupportsExtendedDynamicState3 = supportsExtendedDynamicState3;
SupportsMultiView = supportsMultiView;
SupportsNullDescriptors = supportsNullDescriptors;
SupportsPushDescriptors = supportsPushDescriptors;
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
index bf22a120a..5024fdd4e 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -884,7 +884,15 @@ namespace Ryujinx.Graphics.Vulkan
public void SetDepthClamp(bool clamp)
{
- _newState.DepthClampEnable = clamp;
+ if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable)
+ {
+ DynamicState.SetDepthClampEnable(clamp);
+ }
+ else
+ {
+ _newState.DepthClampEnable = clamp;
+ }
+
SignalStateChange();
}
@@ -989,7 +997,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetLogicOpState(bool enable, LogicalOp op)
{
- if (_supportExtDynamic2 && Gd.ExtendedLogicOp)
+ if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp)
{
DynamicState.SetLogicOp(op.Convert());
}
@@ -998,21 +1006,53 @@ namespace Ryujinx.Graphics.Vulkan
_newState.LogicOp = op.Convert();
}
- _newState.LogicOpEnable = enable;
+ if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable)
+ {
+ DynamicState.SetLogicOpEnable(enable);
+
+ }
+ else
+ {
+ _newState.LogicOpEnable = enable;
+ }
SignalStateChange();
}
public void SetMultisampleState(MultisampleDescriptor multisample)
{
- _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable;
- _newState.AlphaToOneEnable = multisample.AlphaToOneEnable;
+ if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable)
+ {
+ DynamicState.SetAlphaToCoverEnable(multisample.AlphaToCoverageEnable);
+ }
+ else
+ {
+ _newState.AlphaToCoverageEnable = multisample.AlphaToCoverageEnable;
+ }
+
+ if (Gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable)
+ {
+ DynamicState.SetAlphaToOneEnable(multisample.AlphaToOneEnable);
+ }
+ else
+ {
+ _newState.AlphaToOneEnable = multisample.AlphaToOneEnable;
+ }
+
SignalStateChange();
}
public void SetPatchParameters(int vertices, ReadOnlySpan defaultOuterLevel, ReadOnlySpan defaultInnerLevel)
{
- _newState.PatchControlPoints = (uint)vertices;
+ if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints)
+ {
+ DynamicState.SetPatchControlPoints((uint)vertices);
+ }
+ else
+ {
+ _newState.PatchControlPoints = (uint)vertices;
+ }
+
SignalStateChange();
// TODO: Default levels (likely needs emulation on shaders?)
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs
index 783f2bf71..90d75724a 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineDynamicState.cs
@@ -52,6 +52,15 @@ namespace Ryujinx.Graphics.Vulkan
private LogicOp _logicOp;
+ private uint _patchControlPoints;
+
+ private bool _logicOpEnable;
+
+ private bool _depthClampEnable;
+
+ private bool _alphaToCoverEnable;
+ private bool _alphaToOneEnable;
+
[Flags]
private enum DirtyFlags
{
@@ -69,9 +78,14 @@ namespace Ryujinx.Graphics.Vulkan
LineWidth = 1 << 10,
RasterDiscard = 1 << 11,
LogicOp = 1 << 12,
+ DepthClampEnable = 1 << 13,
+ LogicOpEnalbe = 1 << 14,
+ AlphaToCover = 1 << 15,
+ AlphaToOne = 1 << 16,
+ PatchControlPoints = 1 << 17,
Standard = Blend | DepthBias | Scissor | Stencil | Viewport | LineWidth,
Extended = CullMode | FrontFace | DepthTestBool | DepthTestCompareOp | StencilTestEnable,
- Extended2 = RasterDiscard | LogicOp,
+ Extended2 = RasterDiscard | LogicOp | PatchControlPoints,
}
private DirtyFlags _dirty;
@@ -219,6 +233,41 @@ namespace Ryujinx.Graphics.Vulkan
_dirty |= DirtyFlags.LogicOp;
}
+ public void SetPatchControlPoints(uint points)
+ {
+ _patchControlPoints = points;
+
+ _dirty |= DirtyFlags.PatchControlPoints;
+ }
+
+ public void SetLogicOpEnable(bool logicOpEnable)
+ {
+ _logicOpEnable = logicOpEnable;
+
+ _dirty |= DirtyFlags.LogicOpEnalbe;
+ }
+
+ public void SetDepthClampEnable(bool depthClampEnable)
+ {
+ _depthClampEnable = depthClampEnable;
+
+ _dirty |= DirtyFlags.DepthClampEnable;
+ }
+
+ public void SetAlphaToCoverEnable(bool alphaToCoverEnable)
+ {
+ _alphaToCoverEnable = alphaToCoverEnable;
+
+ _dirty |= DirtyFlags.AlphaToCover;
+ }
+
+ public void SetAlphaToOneEnable(bool alphaToOneEnable)
+ {
+ _alphaToOneEnable = alphaToOneEnable;
+
+ _dirty |= DirtyFlags.AlphaToOne;
+ }
+
public void ForceAllDirty(VulkanRenderer gd)
{
_dirty = DirtyFlags.Standard;
@@ -238,10 +287,35 @@ namespace Ryujinx.Graphics.Vulkan
_dirty &= ~DirtyFlags.LineWidth;
}
- if (!gd.ExtendedLogicOp)
+ if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp)
{
_dirty &= ~DirtyFlags.LogicOp;
}
+
+ if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints)
+ {
+ _dirty &= ~DirtyFlags.LogicOp;
+ }
+
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable)
+ {
+ _dirty = DirtyFlags.AlphaToCover;
+ }
+
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable)
+ {
+ _dirty = DirtyFlags.AlphaToOne;
+ }
+
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable)
+ {
+ _dirty = DirtyFlags.DepthClampEnable;
+ }
+
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable)
+ {
+ _dirty = DirtyFlags.LogicOpEnalbe;
+ }
}
public void ReplayIfDirty(VulkanRenderer gd, CommandBuffer commandBuffer)
@@ -306,11 +380,36 @@ namespace Ryujinx.Graphics.Vulkan
RecordRasterizationDiscard(gd, commandBuffer);
}
- if (_dirty.HasFlag(DirtyFlags.RasterDiscard))
+ if (_dirty.HasFlag(DirtyFlags.LogicOp))
{
RecordLogicOp(gd, commandBuffer);
}
+ if (_dirty.HasFlag(DirtyFlags.PatchControlPoints))
+ {
+ RecordPatchControlPoints(gd, commandBuffer);
+ }
+
+ if (_dirty.HasFlag(DirtyFlags.LogicOpEnalbe))
+ {
+ RecordLogicOpEnable(gd, commandBuffer);
+ }
+
+ if (_dirty.HasFlag(DirtyFlags.DepthClampEnable))
+ {
+ RecordDepthClampEnable(gd, commandBuffer);
+ }
+
+ if (_dirty.HasFlag(DirtyFlags.AlphaToCover))
+ {
+ RecordAlphaToCoverEnable(gd, commandBuffer);
+ }
+
+ if (_dirty.HasFlag(DirtyFlags.AlphaToOne))
+ {
+ RecordAlphaToOneEnable(gd, commandBuffer);
+ }
+
_dirty = DirtyFlags.None;
}
@@ -421,6 +520,31 @@ namespace Ryujinx.Graphics.Vulkan
gd.ExtendedDynamicState2Api.CmdSetLogicOp(commandBuffer, _logicOp);
}
+ private readonly void RecordLogicOpEnable(VulkanRenderer gd, CommandBuffer commandBuffer)
+ {
+ gd.ExtendedDynamicState3Api.CmdSetLogicOpEnable(commandBuffer, _logicOpEnable);
+ }
+
+ private readonly void RecordDepthClampEnable(VulkanRenderer gd, CommandBuffer commandBuffer)
+ {
+ gd.ExtendedDynamicState3Api.CmdSetDepthClampEnable(commandBuffer, _depthClampEnable);
+ }
+
+ private readonly void RecordAlphaToCoverEnable(VulkanRenderer gd, CommandBuffer commandBuffer)
+ {
+ gd.ExtendedDynamicState3Api.CmdSetAlphaToCoverageEnable(commandBuffer, _alphaToCoverEnable);
+ }
+
+ private readonly void RecordAlphaToOneEnable(VulkanRenderer gd, CommandBuffer commandBuffer)
+ {
+ gd.ExtendedDynamicState3Api.CmdSetAlphaToOneEnable(commandBuffer, _alphaToOneEnable);
+ }
+
+ private readonly void RecordPatchControlPoints(VulkanRenderer gd, CommandBuffer commandBuffer)
+ {
+ gd.ExtendedDynamicState2Api.CmdSetPatchControlPoints(commandBuffer, _patchControlPoints);
+ }
+
private readonly void RecordLineWidth(Vk api, CommandBuffer commandBuffer)
{
if (!OperatingSystem.IsMacOS())
diff --git a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
index 7c6f6a83f..e4fe002d9 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
@@ -404,7 +404,7 @@ namespace Ryujinx.Graphics.Vulkan
{
UpdateVertexAttributeDescriptions(gd);
}
-
+
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2;
@@ -457,7 +457,7 @@ namespace Ryujinx.Graphics.Vulkan
{
primitiveRestartEnable = true;
}
-
+
var inputAssemblyState = new PipelineInputAssemblyStateCreateInfo
{
SType = StructureType.PipelineInputAssemblyStateCreateInfo,
@@ -494,12 +494,12 @@ namespace Ryujinx.Graphics.Vulkan
rasterizationState.DepthBiasEnable = DepthBiasEnable;
rasterizationState.RasterizerDiscardEnable = RasterizerDiscardEnable;
}
-
+
var viewportState = new PipelineViewportStateCreateInfo
{
SType = StructureType.PipelineViewportStateCreateInfo,
};
-
+
if (!supportsExtDynamicState)
{
viewportState.ViewportCount = ViewportsCount;
@@ -534,7 +534,7 @@ namespace Ryujinx.Graphics.Vulkan
MinDepthBounds = MinDepthBounds,
MaxDepthBounds = MaxDepthBounds,
};
-
+
if (!supportsExtDynamicState)
{
var stencilFront = new StencilOpState(
@@ -613,9 +613,54 @@ namespace Ryujinx.Graphics.Vulkan
colorBlendState.PNext = &colorBlendAdvancedState;
}
-
- int dynamicStatesCount = supportsExtDynamicState ? (isMoltenVk ? 18 : 19) : (isMoltenVk ? 7 : 8);
+ int baseDynamicStatesCount = 7;
+ int additionalDynamicStatesCount = 0;
+
+ if (!isMoltenVk)
+ {
+ baseDynamicStatesCount++;
+ }
+
+ if (supportsExtDynamicState)
+ {
+ additionalDynamicStatesCount += isMoltenVk ? 10 : 11;
+ }
+
+ if (supportsExtDynamicState2)
+ {
+ additionalDynamicStatesCount += 2;
+ if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp)
+ {
+ additionalDynamicStatesCount++;
+ }
+ if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints)
+ {
+ additionalDynamicStatesCount++;
+ }
+ }
+
+ if (supportsExtDynamicState3)
+ {
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable)
+ {
+ additionalDynamicStatesCount++;
+ }
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable)
+ {
+ additionalDynamicStatesCount++;
+ }
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable)
+ {
+ additionalDynamicStatesCount++;
+ }
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable)
+ {
+ additionalDynamicStatesCount++;
+ }
+ }
+
+ int dynamicStatesCount = baseDynamicStatesCount + additionalDynamicStatesCount;
DynamicState* dynamicStates = stackalloc DynamicState[dynamicStatesCount];
dynamicStates[0] = DynamicState.Viewport;
@@ -625,33 +670,64 @@ namespace Ryujinx.Graphics.Vulkan
dynamicStates[4] = DynamicState.StencilWriteMask;
dynamicStates[5] = DynamicState.StencilReference;
dynamicStates[6] = DynamicState.BlendConstants;
-
- if(!isMoltenVk)
+
+ int currentIndex = 7;
+
+ if (!isMoltenVk)
{
- dynamicStates[7] = DynamicState.LineWidth;
+ dynamicStates[currentIndex++] = DynamicState.LineWidth;
}
-
+
if (supportsExtDynamicState)
{
- int index = (isMoltenVk ? 7 : 8);
- if (!isMoltenVk) {
- dynamicStates[index++] = DynamicState.VertexInputBindingStrideExt;
+ if (!isMoltenVk)
+ {
+ dynamicStates[currentIndex++] = DynamicState.VertexInputBindingStrideExt;
}
- dynamicStates[index++] = DynamicState.CullModeExt;
- dynamicStates[index++] = DynamicState.FrontFaceExt;
- dynamicStates[index++] = DynamicState.DepthTestEnableExt;
- dynamicStates[index++] = DynamicState.DepthWriteEnableExt;
- dynamicStates[index++] = DynamicState.DepthCompareOpExt;
- dynamicStates[index++] = DynamicState.StencilTestEnableExt;
- dynamicStates[index++] = DynamicState.ViewportWithCountExt;
- dynamicStates[index++] = DynamicState.ScissorWithCountExt;
- dynamicStates[index] = DynamicState.StencilOpExt;
+ dynamicStates[currentIndex++] = DynamicState.CullModeExt;
+ dynamicStates[currentIndex++] = DynamicState.FrontFaceExt;
+ dynamicStates[currentIndex++] = DynamicState.DepthTestEnableExt;
+ dynamicStates[currentIndex++] = DynamicState.DepthWriteEnableExt;
+ dynamicStates[currentIndex++] = DynamicState.DepthCompareOpExt;
+ dynamicStates[currentIndex++] = DynamicState.StencilTestEnableExt;
+ dynamicStates[currentIndex++] = DynamicState.ViewportWithCountExt;
+ dynamicStates[currentIndex++] = DynamicState.ScissorWithCountExt;
+ dynamicStates[currentIndex++] = DynamicState.StencilOpExt;
}
if (supportsExtDynamicState2)
{
- dynamicStates[16] = DynamicState.DepthBiasEnableExt;
- dynamicStates[17] = DynamicState.RasterizerDiscardEnableExt;
+ dynamicStates[currentIndex++] = DynamicState.DepthBiasEnableExt;
+ dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt;
+
+ if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp)
+ {
+ dynamicStates[currentIndex++] = DynamicState.LogicOpExt;
+ }
+ if (gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints)
+ {
+ dynamicStates[currentIndex++] = DynamicState.PatchControlPointsExt;
+ }
+ }
+
+ if (supportsExtDynamicState3)
+ {
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable)
+ {
+ dynamicStates[currentIndex++] = DynamicState.DepthClampEnableExt;
+ }
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable)
+ {
+ dynamicStates[currentIndex++] = DynamicState.LogicOpEnableExt;
+ }
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable)
+ {
+ dynamicStates[currentIndex++] = DynamicState.AlphaToCoverageEnableExt;
+ }
+ if (gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable)
+ {
+ dynamicStates[currentIndex++] = DynamicState.AlphaToOneEnableExt;
+ }
}
var pipelineDynamicStateCreateInfo = new PipelineDynamicStateCreateInfo
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
index 6b4ca1d3d..4a1aa2b0b 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
@@ -263,7 +263,7 @@ namespace Ryujinx.Graphics.Vulkan
return InvalidIndex;
}
- internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out bool extendedLogicOp)
+ internal static Device CreateDevice(Vk api, VulkanPhysicalDevice physicalDevice, uint queueFamilyIndex, uint queueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features, out PhysicalDeviceExtendedDynamicState3FeaturesEXT extendedDynamicState3Features)
{
if (queueCount > QueuesCount)
{
@@ -322,6 +322,17 @@ namespace Ryujinx.Graphics.Vulkan
features2.PNext = &supportedFeaturesExtExtendedDynamicState2;
}
+ PhysicalDeviceExtendedDynamicState3FeaturesEXT supportedFeaturesExtExtendedDynamicState3 = new()
+ {
+ SType = StructureType.PhysicalDeviceExtendedDynamicState3FeaturesExt,
+ PNext = features2.PNext,
+ };
+
+ if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName))
+ {
+ features2.PNext = &supportedFeaturesExtExtendedDynamicState3;
+ }
+
PhysicalDevicePrimitiveTopologyListRestartFeaturesEXT supportedFeaturesPrimitiveTopologyListRestart = new()
{
SType = StructureType.PhysicalDevicePrimitiveTopologyListRestartFeaturesExt,
@@ -451,18 +462,45 @@ namespace Ryujinx.Graphics.Vulkan
pExtendedFeatures = &featuresExtendedDynamicState;
- var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT()
+ if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName))
{
- SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
- PNext = pExtendedFeatures,
- ExtendedDynamicState2 = physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName),
- ExtendedDynamicState2LogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp,
- ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2PatchControlPoints,
- };
+ var featuresExtendedDynamicState2 = new PhysicalDeviceExtendedDynamicState2FeaturesEXT()
+ {
+ SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
+ PNext = pExtendedFeatures,
+ ExtendedDynamicState2 =
+ physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName),
+ ExtendedDynamicState2LogicOp =
+ supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp,
+ ExtendedDynamicState2PatchControlPoints = supportedFeaturesExtExtendedDynamicState2
+ .ExtendedDynamicState2PatchControlPoints,
+ };
- extendedLogicOp = supportedFeaturesExtExtendedDynamicState2.ExtendedDynamicState2LogicOp;
+ pExtendedFeatures = &featuresExtendedDynamicState2;
+ }
- pExtendedFeatures = &featuresExtendedDynamicState2;
+ extendedDynamicState2Features = supportedFeaturesExtExtendedDynamicState2;
+
+
+ if (physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName))
+ {
+ var featuresExtendedDynamicState3 = new PhysicalDeviceExtendedDynamicState3FeaturesEXT()
+ {
+ SType = StructureType.PhysicalDeviceExtendedDynamicState3FeaturesExt,
+ PNext = pExtendedFeatures,
+ ExtendedDynamicState3LogicOpEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3LogicOpEnable,
+ ExtendedDynamicState3AlphaToCoverageEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToCoverageEnable,
+ ExtendedDynamicState3AlphaToOneEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3AlphaToOneEnable,
+ ExtendedDynamicState3DepthClampEnable = supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable,
+ };
+
+ pExtendedFeatures = &featuresExtendedDynamicState3;
+ }
+
+ //Seems to be a error in Silk.Net bidings investigate further later
+ supportedFeaturesExtExtendedDynamicState3.ExtendedDynamicState3DepthClampEnable = false;
+
+ extendedDynamicState3Features = supportedFeaturesExtExtendedDynamicState3;
var featuresVk11 = new PhysicalDeviceVulkan11Features
{
diff --git a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index 1807711d6..69d075951 100644
--- a/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/src/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -36,6 +36,7 @@ namespace Ryujinx.Graphics.Vulkan
internal ExtConditionalRendering ConditionalRenderingApi { get; private set; }
internal ExtExtendedDynamicState ExtendedDynamicStateApi { get; private set; }
internal ExtExtendedDynamicState2 ExtendedDynamicState2Api { get; private set; }
+ internal ExtExtendedDynamicState3 ExtendedDynamicState3Api { get; private set; }
internal KhrPushDescriptor PushDescriptorApi { get; private set; }
internal ExtTransformFeedback TransformFeedbackApi { get; private set; }
@@ -99,7 +100,10 @@ namespace Ryujinx.Graphics.Vulkan
public bool PreferThreading => true;
- public bool ExtendedLogicOp;
+ public PhysicalDeviceExtendedDynamicState2FeaturesEXT ExtendedDynamicState2Features;
+
+ public PhysicalDeviceExtendedDynamicState3FeaturesEXT ExtendedDynamicState3Features;
+
public event EventHandler ScreenCaptured;
@@ -141,6 +145,11 @@ namespace Ryujinx.Graphics.Vulkan
ExtendedDynamicState2Api = extendedDynamicState2Api;
}
+ if (Api.TryGetDeviceExtension(_instance.Instance, _device, out ExtExtendedDynamicState3 extendedDynamicState3Api))
+ {
+ ExtendedDynamicState3Api = extendedDynamicState3Api;
+ }
+
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrPushDescriptor pushDescriptorApi))
{
PushDescriptorApi = pushDescriptorApi;
@@ -392,6 +401,7 @@ namespace Ryujinx.Graphics.Vulkan
_physicalDevice.IsDeviceExtensionPresent(ExtConditionalRendering.ExtensionName),
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState.ExtensionName),
_physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState2.ExtensionName),
+ _physicalDevice.IsDeviceExtensionPresent(ExtExtendedDynamicState3.ExtensionName),
features2.Features.MultiViewport && !(IsMoltenVk && Vendor == Vendor.Amd), // Workaround for AMD on MoltenVK issue
featuresRobustness2.NullDescriptor || IsMoltenVk,
supportsPushDescriptors && !IsMoltenVk,
@@ -456,9 +466,10 @@ namespace Ryujinx.Graphics.Vulkan
var queueFamilyIndex = VulkanInitialization.FindSuitableQueueFamily(Api, _physicalDevice, _surface, out uint maxQueueCount);
- _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out bool extendedLogicOp);
+ _device = VulkanInitialization.CreateDevice(Api, _physicalDevice, queueFamilyIndex, maxQueueCount, out PhysicalDeviceExtendedDynamicState2FeaturesEXT extendedDynamicState2Features, out PhysicalDeviceExtendedDynamicState3FeaturesEXT extendedDynamicState3Features);
- ExtendedLogicOp = extendedLogicOp;
+ ExtendedDynamicState2Features = extendedDynamicState2Features;
+ ExtendedDynamicState3Features = extendedDynamicState3Features;
if (Api.TryGetDeviceExtension(_instance.Instance, _device, out KhrSwapchain swapchainApi))
{