aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2022-07-05 19:58:36 -0300
committerGitHub <noreply@github.com>2022-07-05 19:58:36 -0300
commitb46b63e06a36845175f68331edb5ddeeb34de27b (patch)
tree1ca8adf9541d1f68e420feb853a612413d690725 /Ryujinx.Graphics.Shader
parent594246ea4727c9377b1c916934d9b257a1b5d0d0 (diff)
Add support for alpha to coverage dithering (#3069)
* Add support for alpha to coverage dithering * Shader cache version bump * Fix wrong alpha register * Ensure support buffer is cleared * New shader specialization based approach
Diffstat (limited to 'Ryujinx.Graphics.Shader')
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs2
-rw-r--r--Ryujinx.Graphics.Shader/IGpuAccessor.cs9
-rw-r--r--Ryujinx.Graphics.Shader/Translation/EmitterContext.cs31
3 files changed, 41 insertions, 1 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index 59a7ccdc..54578b79 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -615,7 +615,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
private static void DeclareSupportUniformBlock(CodeGenContext context, ShaderStage stage, int scaleElements)
{
- bool needsSupportBlock = stage == ShaderStage.Fragment ||
+ bool needsSupportBlock = stage == ShaderStage.Fragment ||
(context.Config.LastInVertexPipeline && context.Config.GpuAccessor.QueryViewportTransformDisable());
if (!needsSupportBlock && scaleElements == 0)
diff --git a/Ryujinx.Graphics.Shader/IGpuAccessor.cs b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
index 42f210a5..878c7180 100644
--- a/Ryujinx.Graphics.Shader/IGpuAccessor.cs
+++ b/Ryujinx.Graphics.Shader/IGpuAccessor.cs
@@ -35,6 +35,15 @@ namespace Ryujinx.Graphics.Shader
ReadOnlySpan<ulong> GetCode(ulong address, int minimumSize);
/// <summary>
+ /// Queries whenever the alpha-to-coverage dithering feature is enabled.
+ /// </summary>
+ /// <returns>True if the feature is enabled, false otherwise</returns>
+ bool QueryAlphaToCoverageDitherEnable()
+ {
+ return false;
+ }
+
+ /// <summary>
/// Queries the binding number of a constant buffer.
/// </summary>
/// <param name="index">Constant buffer index</param>
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index ba3b551d..332b3e02 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -205,6 +205,8 @@ namespace Ryujinx.Graphics.Shader.Translation
}
else if (Config.Stage == ShaderStage.Fragment)
{
+ GenerateAlphaToCoverageDitherDiscard();
+
if (Config.OmapDepth)
{
Operand dest = Attribute(AttributeConsts.FragmentOutputDepth);
@@ -266,6 +268,35 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
+ private void GenerateAlphaToCoverageDitherDiscard()
+ {
+ // If the feature is disabled, or alpha is not written, then we're done.
+ if (!Config.GpuAccessor.QueryAlphaToCoverageDitherEnable() || (Config.OmapTargets & 8) == 0)
+ {
+ return;
+ }
+
+ // 11 11 11 10 10 10 10 00
+ // 11 01 01 01 01 00 00 00
+ Operand ditherMask = Const(unchecked((int)0xfbb99110u));
+
+ Operand x = this.BitwiseAnd(this.FP32ConvertToU32(Attribute(AttributeConsts.PositionX)), Const(1));
+ Operand y = this.BitwiseAnd(this.FP32ConvertToU32(Attribute(AttributeConsts.PositionY)), Const(1));
+ Operand xy = this.BitwiseOr(x, this.ShiftLeft(y, Const(1)));
+
+ Operand alpha = Register(3, RegisterType.Gpr);
+ Operand scaledAlpha = this.FPMultiply(this.FPSaturate(alpha), ConstF(8));
+ Operand quantizedAlpha = this.IMinimumU32(this.FP32ConvertToU32(scaledAlpha), Const(7));
+ Operand shift = this.BitwiseOr(this.ShiftLeft(quantizedAlpha, Const(2)), xy);
+ Operand opaque = this.BitwiseAnd(this.ShiftRightU32(ditherMask, shift), Const(1));
+
+ Operand a2cDitherEndLabel = Label();
+
+ this.BranchIfTrue(a2cDitherEndLabel, opaque);
+ this.Discard();
+ this.MarkLabel(a2cDitherEndLabel);
+ }
+
public Operation[] GetOperations()
{
return _operations.ToArray();