diff --git a/Directory.Packages.props b/Directory.Packages.props
index d04e237e0..fc27404c2 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -39,9 +39,9 @@
-
-
-
+
+
+
@@ -49,4 +49,4 @@
-
+
\ No newline at end of file
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 5ae36a4b0..f7332a545 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -886,7 +886,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();
}
@@ -986,7 +994,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetLogicOpState(bool enable, LogicalOp op)
{
- if (_supportExtDynamic2 && Gd.ExtendedLogicOp)
+ if (Gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp)
{
DynamicState.SetLogicOp(op.Convert());
}
@@ -995,21 +1003,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 4678ef763..b1b4fd92c 100644
--- a/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
+++ b/src/Ryujinx.Graphics.Vulkan/PipelineState.cs
@@ -407,6 +407,7 @@ namespace Ryujinx.Graphics.Vulkan
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
bool supportsExtDynamicState2 = gd.Capabilities.SupportsExtendedDynamicState2;
+ bool supportsExtDynamicState3 = gd.Capabilities.SupportsExtendedDynamicState3;
fixed (VertexInputAttributeDescription* pVertexAttributeDescriptions = &Internal.VertexAttributeDescriptions[0])
@@ -468,16 +469,24 @@ namespace Ryujinx.Graphics.Vulkan
var tessellationState = new PipelineTessellationStateCreateInfo
{
SType = StructureType.PipelineTessellationStateCreateInfo,
- PatchControlPoints = PatchControlPoints,
};
+ if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2PatchControlPoints)
+ {
+ tessellationState.PatchControlPoints = PatchControlPoints;
+ }
+
var rasterizationState = new PipelineRasterizationStateCreateInfo
{
SType = StructureType.PipelineRasterizationStateCreateInfo,
- DepthClampEnable = DepthClampEnable,
PolygonMode = PolygonMode,
};
+ if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3DepthClampEnable)
+ {
+ rasterizationState.DepthClampEnable = DepthClampEnable;
+ }
+
if (isMoltenVk)
{
rasterizationState.LineWidth = 1.0f;
@@ -523,10 +532,18 @@ namespace Ryujinx.Graphics.Vulkan
SampleShadingEnable = false,
RasterizationSamples = TextureStorage.ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, SamplesCount),
MinSampleShading = 1,
- AlphaToCoverageEnable = AlphaToCoverageEnable,
- AlphaToOneEnable = AlphaToOneEnable,
};
+ if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToCoverageEnable)
+ {
+ multisampleState.AlphaToCoverageEnable = AlphaToCoverageEnable;
+ }
+
+ if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3AlphaToOneEnable)
+ {
+ multisampleState.AlphaToOneEnable = AlphaToOneEnable;
+ }
+
var depthStencilState = new PipelineDepthStencilStateCreateInfo
{
SType = StructureType.PipelineDepthStencilStateCreateInfo,
@@ -541,19 +558,13 @@ namespace Ryujinx.Graphics.Vulkan
StencilFrontFailOp,
StencilFrontPassOp,
StencilFrontDepthFailOp,
- StencilFrontCompareOp,
- null,
- null,
- null);
+ StencilFrontCompareOp);
var stencilBack = new StencilOpState(
StencilBackFailOp,
StencilBackPassOp,
StencilBackDepthFailOp,
- StencilBackCompareOp,
- null,
- null,
- null);
+ StencilBackCompareOp);
depthStencilState.Front = stencilFront;
depthStencilState.Back = stencilBack;
@@ -587,16 +598,20 @@ namespace Ryujinx.Graphics.Vulkan
var colorBlendState = new PipelineColorBlendStateCreateInfo
{
SType = StructureType.PipelineColorBlendStateCreateInfo,
- LogicOpEnable = LogicOpEnable,
AttachmentCount = ColorBlendAttachmentStateCount,
PAttachments = pColorBlendAttachmentState,
};
- if (!(supportsExtDynamicState2 && gd.ExtendedLogicOp))
+ if (!gd.ExtendedDynamicState2Features.ExtendedDynamicState2LogicOp)
{
colorBlendState.LogicOp = LogicOp;
}
+ if (!gd.ExtendedDynamicState3Features.ExtendedDynamicState3LogicOpEnable)
+ {
+ colorBlendState.LogicOpEnable = LogicOpEnable;
+ }
+
PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState;
if (!AdvancedBlendSrcPreMultiplied ||
@@ -624,13 +639,37 @@ namespace Ryujinx.Graphics.Vulkan
if (supportsExtDynamicState)
{
- additionalDynamicStatesCount += isMoltenVk ? 11 : 12;
+ additionalDynamicStatesCount += isMoltenVk ? 10 : 11;
}
if (supportsExtDynamicState2)
{
additionalDynamicStatesCount += 2;
- if (gd.ExtendedLogicOp)
+ 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++;
}
@@ -676,10 +715,34 @@ namespace Ryujinx.Graphics.Vulkan
dynamicStates[currentIndex++] = DynamicState.DepthBiasEnableExt;
dynamicStates[currentIndex++] = DynamicState.RasterizerDiscardEnableExt;
- if (gd.ExtendedLogicOp)
+ 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
@@ -689,6 +752,7 @@ namespace Ryujinx.Graphics.Vulkan
PDynamicStates = dynamicStates,
};
+
var pipelineCreateInfo = new GraphicsPipelineCreateInfo
{
SType = StructureType.GraphicsPipelineCreateInfo,
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 8829c038b..b0dcce2e2 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))
{