diff options
Diffstat (limited to 'Ryujinx.Graphics.Vulkan')
-rw-r--r-- | Ryujinx.Graphics.Vulkan/EnumConversion.cs | 65 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/HardwareCapabilities.cs | 12 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineBase.cs | 54 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/PipelineState.cs | 42 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/VulkanInitialization.cs | 1 | ||||
-rw-r--r-- | Ryujinx.Graphics.Vulkan/VulkanRenderer.cs | 26 |
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, |