aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Vulkan')
-rw-r--r--Ryujinx.Graphics.Vulkan/EnumConversion.cs65
-rw-r--r--Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs12
-rw-r--r--Ryujinx.Graphics.Vulkan/PipelineBase.cs54
-rw-r--r--Ryujinx.Graphics.Vulkan/PipelineState.cs42
-rw-r--r--Ryujinx.Graphics.Vulkan/VulkanInitialization.cs1
-rw-r--r--Ryujinx.Graphics.Vulkan/VulkanRenderer.cs26
6 files changed, 192 insertions, 8 deletions
diff --git a/Ryujinx.Graphics.Vulkan/EnumConversion.cs b/Ryujinx.Graphics.Vulkan/EnumConversion.cs
index 0164ef85..6c273b05 100644
--- a/Ryujinx.Graphics.Vulkan/EnumConversion.cs
+++ b/Ryujinx.Graphics.Vulkan/EnumConversion.cs
@@ -79,6 +79,60 @@ namespace Ryujinx.Graphics.Vulkan
};
}
+ public static Silk.NET.Vulkan.BlendOp Convert(this GAL.AdvancedBlendOp op)
+ {
+ return op switch
+ {
+ GAL.AdvancedBlendOp.Zero => Silk.NET.Vulkan.BlendOp.ZeroExt,
+ GAL.AdvancedBlendOp.Src => Silk.NET.Vulkan.BlendOp.SrcExt,
+ GAL.AdvancedBlendOp.Dst => Silk.NET.Vulkan.BlendOp.DstExt,
+ GAL.AdvancedBlendOp.SrcOver => Silk.NET.Vulkan.BlendOp.SrcOverExt,
+ GAL.AdvancedBlendOp.DstOver => Silk.NET.Vulkan.BlendOp.DstOverExt,
+ GAL.AdvancedBlendOp.SrcIn => Silk.NET.Vulkan.BlendOp.SrcInExt,
+ GAL.AdvancedBlendOp.DstIn => Silk.NET.Vulkan.BlendOp.DstInExt,
+ GAL.AdvancedBlendOp.SrcOut => Silk.NET.Vulkan.BlendOp.SrcOutExt,
+ GAL.AdvancedBlendOp.DstOut => Silk.NET.Vulkan.BlendOp.DstOutExt,
+ GAL.AdvancedBlendOp.SrcAtop => Silk.NET.Vulkan.BlendOp.SrcAtopExt,
+ GAL.AdvancedBlendOp.DstAtop => Silk.NET.Vulkan.BlendOp.DstAtopExt,
+ GAL.AdvancedBlendOp.Xor => Silk.NET.Vulkan.BlendOp.XorExt,
+ GAL.AdvancedBlendOp.Plus => Silk.NET.Vulkan.BlendOp.PlusExt,
+ GAL.AdvancedBlendOp.PlusClamped => Silk.NET.Vulkan.BlendOp.PlusClampedExt,
+ GAL.AdvancedBlendOp.PlusClampedAlpha => Silk.NET.Vulkan.BlendOp.PlusClampedAlphaExt,
+ GAL.AdvancedBlendOp.PlusDarker => Silk.NET.Vulkan.BlendOp.PlusDarkerExt,
+ GAL.AdvancedBlendOp.Multiply => Silk.NET.Vulkan.BlendOp.MultiplyExt,
+ GAL.AdvancedBlendOp.Screen => Silk.NET.Vulkan.BlendOp.ScreenExt,
+ GAL.AdvancedBlendOp.Overlay => Silk.NET.Vulkan.BlendOp.OverlayExt,
+ GAL.AdvancedBlendOp.Darken => Silk.NET.Vulkan.BlendOp.DarkenExt,
+ GAL.AdvancedBlendOp.Lighten => Silk.NET.Vulkan.BlendOp.LightenExt,
+ GAL.AdvancedBlendOp.ColorDodge => Silk.NET.Vulkan.BlendOp.ColordodgeExt,
+ GAL.AdvancedBlendOp.ColorBurn => Silk.NET.Vulkan.BlendOp.ColorburnExt,
+ GAL.AdvancedBlendOp.HardLight => Silk.NET.Vulkan.BlendOp.HardlightExt,
+ GAL.AdvancedBlendOp.SoftLight => Silk.NET.Vulkan.BlendOp.SoftlightExt,
+ GAL.AdvancedBlendOp.Difference => Silk.NET.Vulkan.BlendOp.DifferenceExt,
+ GAL.AdvancedBlendOp.Minus => Silk.NET.Vulkan.BlendOp.MinusExt,
+ GAL.AdvancedBlendOp.MinusClamped => Silk.NET.Vulkan.BlendOp.MinusClampedExt,
+ GAL.AdvancedBlendOp.Exclusion => Silk.NET.Vulkan.BlendOp.ExclusionExt,
+ GAL.AdvancedBlendOp.Contrast => Silk.NET.Vulkan.BlendOp.ContrastExt,
+ GAL.AdvancedBlendOp.Invert => Silk.NET.Vulkan.BlendOp.InvertExt,
+ GAL.AdvancedBlendOp.InvertRGB => Silk.NET.Vulkan.BlendOp.InvertRgbExt,
+ GAL.AdvancedBlendOp.InvertOvg => Silk.NET.Vulkan.BlendOp.InvertOvgExt,
+ GAL.AdvancedBlendOp.LinearDodge => Silk.NET.Vulkan.BlendOp.LineardodgeExt,
+ GAL.AdvancedBlendOp.LinearBurn => Silk.NET.Vulkan.BlendOp.LinearburnExt,
+ GAL.AdvancedBlendOp.VividLight => Silk.NET.Vulkan.BlendOp.VividlightExt,
+ GAL.AdvancedBlendOp.LinearLight => Silk.NET.Vulkan.BlendOp.LinearlightExt,
+ GAL.AdvancedBlendOp.PinLight => Silk.NET.Vulkan.BlendOp.PinlightExt,
+ GAL.AdvancedBlendOp.HardMix => Silk.NET.Vulkan.BlendOp.HardmixExt,
+ GAL.AdvancedBlendOp.Red => Silk.NET.Vulkan.BlendOp.RedExt,
+ GAL.AdvancedBlendOp.Green => Silk.NET.Vulkan.BlendOp.GreenExt,
+ GAL.AdvancedBlendOp.Blue => Silk.NET.Vulkan.BlendOp.BlueExt,
+ GAL.AdvancedBlendOp.HslHue => Silk.NET.Vulkan.BlendOp.HslHueExt,
+ GAL.AdvancedBlendOp.HslSaturation => Silk.NET.Vulkan.BlendOp.HslSaturationExt,
+ GAL.AdvancedBlendOp.HslColor => Silk.NET.Vulkan.BlendOp.HslColorExt,
+ GAL.AdvancedBlendOp.HslLuminosity => Silk.NET.Vulkan.BlendOp.HslLuminosityExt,
+ _ => LogInvalidAndReturn(op, nameof(GAL.AdvancedBlendOp), Silk.NET.Vulkan.BlendOp.Add)
+ };
+ }
+
public static Silk.NET.Vulkan.BlendOp Convert(this GAL.BlendOp op)
{
return op switch
@@ -92,6 +146,17 @@ namespace Ryujinx.Graphics.Vulkan
};
}
+ public static Silk.NET.Vulkan.BlendOverlapEXT Convert(this GAL.AdvancedBlendOverlap overlap)
+ {
+ return overlap switch
+ {
+ GAL.AdvancedBlendOverlap.Uncorrelated => Silk.NET.Vulkan.BlendOverlapEXT.UncorrelatedExt,
+ GAL.AdvancedBlendOverlap.Disjoint => Silk.NET.Vulkan.BlendOverlapEXT.DisjointExt,
+ GAL.AdvancedBlendOverlap.Conjoint => Silk.NET.Vulkan.BlendOverlapEXT.ConjointExt,
+ _ => LogInvalidAndReturn(overlap, nameof(GAL.AdvancedBlendOverlap), Silk.NET.Vulkan.BlendOverlapEXT.UncorrelatedExt)
+ };
+ }
+
public static Silk.NET.Vulkan.CompareOp Convert(this GAL.CompareOp op)
{
return op switch
diff --git a/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs b/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
index 1ed2b0cc..4512d375 100644
--- a/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
+++ b/Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs
@@ -18,6 +18,10 @@ namespace Ryujinx.Graphics.Vulkan
{
public readonly bool SupportsIndexTypeUint8;
public readonly bool SupportsCustomBorderColor;
+ public readonly bool SupportsBlendEquationAdvanced;
+ public readonly bool SupportsBlendEquationAdvancedCorrelatedOverlap;
+ public readonly bool SupportsBlendEquationAdvancedNonPreMultipliedSrcColor;
+ public readonly bool SupportsBlendEquationAdvancedNonPreMultipliedDstColor;
public readonly bool SupportsIndirectParameters;
public readonly bool SupportsFragmentShaderInterlock;
public readonly bool SupportsGeometryShaderPassthrough;
@@ -44,6 +48,10 @@ namespace Ryujinx.Graphics.Vulkan
public HardwareCapabilities(
bool supportsIndexTypeUint8,
bool supportsCustomBorderColor,
+ bool supportsBlendEquationAdvanced,
+ bool supportsBlendEquationAdvancedCorrelatedOverlap,
+ bool supportsBlendEquationAdvancedNonPreMultipliedSrcColor,
+ bool supportsBlendEquationAdvancedNonPreMultipliedDstColor,
bool supportsIndirectParameters,
bool supportsFragmentShaderInterlock,
bool supportsGeometryShaderPassthrough,
@@ -69,6 +77,10 @@ namespace Ryujinx.Graphics.Vulkan
{
SupportsIndexTypeUint8 = supportsIndexTypeUint8;
SupportsCustomBorderColor = supportsCustomBorderColor;
+ SupportsBlendEquationAdvanced = supportsBlendEquationAdvanced;
+ SupportsBlendEquationAdvancedCorrelatedOverlap = supportsBlendEquationAdvancedCorrelatedOverlap;
+ SupportsBlendEquationAdvancedNonPreMultipliedSrcColor = supportsBlendEquationAdvancedNonPreMultipliedSrcColor;
+ SupportsBlendEquationAdvancedNonPreMultipliedDstColor = supportsBlendEquationAdvancedNonPreMultipliedDstColor;
SupportsIndirectParameters = supportsIndirectParameters;
SupportsFragmentShaderInterlock = supportsFragmentShaderInterlock;
SupportsGeometryShaderPassthrough = supportsGeometryShaderPassthrough;
diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs
index 8ed39ee2..f779305d 100644
--- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -112,11 +112,9 @@ namespace Ryujinx.Graphics.Vulkan
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
new Span<Vector4<float>>(_renderScale).Fill(defaultScale);
- _newState.Initialize();
- _newState.LineWidth = 1f;
- _newState.SamplesCount = 1;
+ _storedBlend = new PipelineColorBlendAttachmentState[Constants.MaxRenderTargets];
- _storedBlend = new PipelineColorBlendAttachmentState[8];
+ _newState.Initialize();
}
public void Initialize()
@@ -676,6 +674,49 @@ namespace Ryujinx.Graphics.Vulkan
// to avoid creating one version of the shader per reference value used.
}
+ public void SetBlendState(AdvancedBlendDescriptor blend)
+ {
+ for (int index = 0; index < Constants.MaxRenderTargets; index++)
+ {
+ ref var vkBlend = ref _newState.Internal.ColorBlendAttachmentState[index];
+
+ if (index == 0)
+ {
+ var blendOp = blend.Op.Convert();
+
+ vkBlend = new PipelineColorBlendAttachmentState(
+ blendEnable: true,
+ colorBlendOp: blendOp,
+ alphaBlendOp: blendOp,
+ colorWriteMask: vkBlend.ColorWriteMask);
+
+ if (Gd.Capabilities.SupportsBlendEquationAdvancedNonPreMultipliedSrcColor)
+ {
+ _newState.AdvancedBlendSrcPreMultiplied = blend.SrcPreMultiplied;
+ }
+
+ if (Gd.Capabilities.SupportsBlendEquationAdvancedCorrelatedOverlap)
+ {
+ _newState.AdvancedBlendOverlap = blend.Overlap.Convert();
+ }
+ }
+ else
+ {
+ vkBlend = new PipelineColorBlendAttachmentState(
+ colorWriteMask: vkBlend.ColorWriteMask);
+ }
+
+ if (vkBlend.ColorWriteMask == 0)
+ {
+ _storedBlend[index] = vkBlend;
+
+ vkBlend = new PipelineColorBlendAttachmentState();
+ }
+ }
+
+ SignalStateChange();
+ }
+
public void SetBlendState(int index, BlendDescriptor blend)
{
ref var vkBlend = ref _newState.Internal.ColorBlendAttachmentState[index];
@@ -709,6 +750,11 @@ namespace Ryujinx.Graphics.Vulkan
blend.BlendConstant.Blue,
blend.BlendConstant.Alpha);
+ // Reset advanced blend state back defaults to the cache to help the pipeline cache.
+ _newState.AdvancedBlendSrcPreMultiplied = true;
+ _newState.AdvancedBlendDstPreMultiplied = true;
+ _newState.AdvancedBlendOverlap = BlendOverlapEXT.UncorrelatedExt;
+
SignalStateChange();
}
diff --git a/Ryujinx.Graphics.Vulkan/PipelineState.cs b/Ryujinx.Graphics.Vulkan/PipelineState.cs
index 00b154a0..0d549476 100644
--- a/Ryujinx.Graphics.Vulkan/PipelineState.cs
+++ b/Ryujinx.Graphics.Vulkan/PipelineState.cs
@@ -285,6 +285,24 @@ namespace Ryujinx.Graphics.Vulkan
set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFD) | ((value ? 1UL : 0UL) << 1);
}
+ public bool AdvancedBlendSrcPreMultiplied
+ {
+ get => ((Internal.Id9 >> 2) & 0x1) != 0UL;
+ set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFFB) | ((value ? 1UL : 0UL) << 2);
+ }
+
+ public bool AdvancedBlendDstPreMultiplied
+ {
+ get => ((Internal.Id9 >> 3) & 0x1) != 0UL;
+ set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFF7) | ((value ? 1UL : 0UL) << 3);
+ }
+
+ public BlendOverlapEXT AdvancedBlendOverlap
+ {
+ get => (BlendOverlapEXT)((Internal.Id9 >> 4) & 0x3);
+ set => Internal.Id9 = (Internal.Id9 & 0xFFFFFFFFFFFFFFCF) | ((ulong)value << 4);
+ }
+
public NativeArray<PipelineShaderStageCreateInfo> Stages;
public NativeArray<PipelineShaderStageRequiredSubgroupSizeCreateInfoEXT> StageRequiredSubgroupSizes;
public PipelineLayout PipelineLayout;
@@ -303,6 +321,13 @@ namespace Ryujinx.Graphics.Vulkan
RequiredSubgroupSize = RequiredSubgroupSize
};
}
+
+ AdvancedBlendSrcPreMultiplied = true;
+ AdvancedBlendDstPreMultiplied = true;
+ AdvancedBlendOverlap = BlendOverlapEXT.UncorrelatedExt;
+
+ LineWidth = 1f;
+ SamplesCount = 1;
}
public unsafe Auto<DisposablePipeline> CreateComputePipeline(
@@ -486,6 +511,23 @@ namespace Ryujinx.Graphics.Vulkan
PAttachments = pColorBlendAttachmentState
};
+ PipelineColorBlendAdvancedStateCreateInfoEXT colorBlendAdvancedState;
+
+ if (!AdvancedBlendSrcPreMultiplied ||
+ !AdvancedBlendDstPreMultiplied ||
+ AdvancedBlendOverlap != BlendOverlapEXT.UncorrelatedExt)
+ {
+ colorBlendAdvancedState = new PipelineColorBlendAdvancedStateCreateInfoEXT()
+ {
+ SType = StructureType.PipelineColorBlendAdvancedStateCreateInfoExt,
+ SrcPremultiplied = AdvancedBlendSrcPreMultiplied,
+ DstPremultiplied = AdvancedBlendDstPreMultiplied,
+ BlendOverlap = AdvancedBlendOverlap
+ };
+
+ colorBlendState.PNext = &colorBlendAdvancedState;
+ }
+
bool supportsExtDynamicState = gd.Capabilities.SupportsExtendedDynamicState;
int dynamicStatesCount = supportsExtDynamicState ? 9 : 8;
diff --git a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
index 4401f032..353b219a 100644
--- a/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
+++ b/Ryujinx.Graphics.Vulkan/VulkanInitialization.cs
@@ -27,6 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
ExtTransformFeedback.ExtensionName,
KhrDrawIndirectCount.ExtensionName,
KhrPushDescriptor.ExtensionName,
+ "VK_EXT_blend_operation_advanced",
"VK_EXT_custom_border_color",
"VK_EXT_descriptor_indexing", // Enabling this works around an issue with disposed buffer bindings on RADV.
"VK_EXT_fragment_shader_interlock",
diff --git a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
index a7b4b41a..4c7c731b 100644
--- a/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
+++ b/Ryujinx.Graphics.Vulkan/VulkanRenderer.cs
@@ -149,6 +149,19 @@ namespace Ryujinx.Graphics.Vulkan
SType = StructureType.PhysicalDeviceProperties2
};
+ PhysicalDeviceBlendOperationAdvancedPropertiesEXT propertiesBlendOperationAdvanced = new PhysicalDeviceBlendOperationAdvancedPropertiesEXT()
+ {
+ SType = StructureType.PhysicalDeviceBlendOperationAdvancedPropertiesExt
+ };
+
+ bool supportsBlendOperationAdvanced = supportedExtensions.Contains("VK_EXT_blend_operation_advanced");
+
+ if (supportsBlendOperationAdvanced)
+ {
+ propertiesBlendOperationAdvanced.PNext = properties2.PNext;
+ properties2.PNext = &propertiesBlendOperationAdvanced;
+ }
+
PhysicalDeviceSubgroupSizeControlPropertiesEXT propertiesSubgroupSizeControl = new PhysicalDeviceSubgroupSizeControlPropertiesEXT()
{
SType = StructureType.PhysicalDeviceSubgroupSizeControlPropertiesExt
@@ -246,9 +259,9 @@ namespace Ryujinx.Graphics.Vulkan
portabilityFlags |= featuresPortabilitySubset.SamplerMipLodBias ? 0 : PortabilitySubsetFlags.NoLodBias;
}
- bool customBorderColorSupported = supportedExtensions.Contains("VK_EXT_custom_border_color") &&
- featuresCustomBorderColor.CustomBorderColors &&
- featuresCustomBorderColor.CustomBorderColorWithoutFormat;
+ bool supportsCustomBorderColor = supportedExtensions.Contains("VK_EXT_custom_border_color") &&
+ featuresCustomBorderColor.CustomBorderColors &&
+ featuresCustomBorderColor.CustomBorderColorWithoutFormat;
ref var properties = ref properties2.Properties;
@@ -259,7 +272,11 @@ namespace Ryujinx.Graphics.Vulkan
Capabilities = new HardwareCapabilities(
supportedExtensions.Contains("VK_EXT_index_type_uint8"),
- customBorderColorSupported,
+ supportsCustomBorderColor,
+ supportsBlendOperationAdvanced,
+ propertiesBlendOperationAdvanced.AdvancedBlendCorrelatedOverlap,
+ propertiesBlendOperationAdvanced.AdvancedBlendNonPremultipliedSrcColor,
+ propertiesBlendOperationAdvanced.AdvancedBlendNonPremultipliedDstColor,
supportedExtensions.Contains(KhrDrawIndirectCount.ExtensionName),
supportedExtensions.Contains("VK_EXT_fragment_shader_interlock"),
supportedExtensions.Contains("VK_NV_geometry_shader_passthrough"),
@@ -526,6 +543,7 @@ namespace Ryujinx.Graphics.Vulkan
supportsR4G4B4A4Format: supportsR4G4B4A4Format,
supportsSnormBufferTextureFormat: true,
supports5BitComponentFormat: supports5BitComponentFormat,
+ supportsBlendEquationAdvanced: Capabilities.SupportsBlendEquationAdvanced,
supportsFragmentShaderInterlock: Capabilities.SupportsFragmentShaderInterlock,
supportsFragmentShaderOrderingIntel: false,
supportsGeometryShaderPassthrough: Capabilities.SupportsGeometryShaderPassthrough,