aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-04-02 21:20:47 -0300
committerGitHub <noreply@github.com>2020-04-03 11:20:47 +1100
commite93ca84b14cc325364f1ccc45a6e8622978e959d (patch)
tree8e32b23e94e529ccf91b8e7d7613ce003d16e841
parent2365ddfc363e76ac1ac9d2e32ef9b36b85463431 (diff)
Better IPA shader instruction implementation (#1082)
* Fix varying interpolation on fragment shader * Some nits * Alignment
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs11
-rw-r--r--Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs2
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs22
-rw-r--r--Ryujinx.Graphics.Shader/IntermediateRepresentation/Operand.cs9
-rw-r--r--Ryujinx.Graphics.Shader/IntermediateRepresentation/OperandHelper.cs4
-rw-r--r--Ryujinx.Graphics.Shader/InterpolationQualifier.cs44
-rw-r--r--Ryujinx.Graphics.Shader/ShaderProgram.cs5
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/AstOperand.cs5
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs2
-rw-r--r--Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs4
-rw-r--r--Ryujinx.Graphics.Shader/Translation/EmitterContext.cs2
-rw-r--r--Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs10
-rw-r--r--Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs64
13 files changed, 96 insertions, 88 deletions
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
index fb58f84a..b1291906 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/Declarations.cs
@@ -365,11 +365,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
foreach (int attr in info.IAttributes.OrderBy(x => x))
{
- string iq = info.InterpolationQualifiers[attr].ToGlslQualifier();
+ string iq = string.Empty;
- if (iq != string.Empty)
+ if (context.Config.Stage == ShaderStage.Fragment)
{
- iq += " ";
+ iq = context.Config.ImapTypes[attr].GetFirstUsedType() switch
+ {
+ PixelImap.Constant => "flat ",
+ PixelImap.ScreenLinear => "noperspective ",
+ _ => string.Empty
+ };
}
context.AppendLine($"layout (location = {attr}) {iq}in vec4 {DefaultNames.IAttributePrefix}{attr}{suffix};");
diff --git a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
index 2de55b2d..8d092d4e 100644
--- a/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
+++ b/Ryujinx.Graphics.Shader/CodeGen/Glsl/OperandManager.cs
@@ -188,7 +188,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
case AttributeConsts.PositionX: return "gl_FragCoord.x";
case AttributeConsts.PositionY: return "gl_FragCoord.y";
case AttributeConsts.PositionZ: return "gl_FragCoord.z";
- case AttributeConsts.PositionW: return "1.0";
+ case AttributeConsts.PositionW: return "gl_FragCoord.w";
}
}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
index 1fddcc8c..7eb88883 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitMemory.cs
@@ -96,17 +96,27 @@ namespace Ryujinx.Graphics.Shader.Instructions
{
OpCodeIpa op = (OpCodeIpa)context.CurrOp;
- InterpolationQualifier iq = InterpolationQualifier.None;
+ Operand res = Attribute(op.AttributeOffset);
- switch (op.Mode)
+ if (op.AttributeOffset >= AttributeConsts.UserAttributeBase &&
+ op.AttributeOffset < AttributeConsts.UserAttributeEnd)
{
- case InterpolationMode.Constant: iq = InterpolationQualifier.Flat; break;
- case InterpolationMode.Pass: iq = InterpolationQualifier.NoPerspective; break;
+ int index = (op.AttributeOffset - AttributeConsts.UserAttributeBase) >> 4;
+
+ if (context.Config.ImapTypes[index].GetFirstUsedType() == PixelImap.Perspective)
+ {
+ res = context.FPMultiply(res, Attribute(AttributeConsts.PositionW));
+ }
}
+
+ if (op.Mode == InterpolationMode.Default)
+ {
+ Operand srcB = GetSrcB(context);
- Operand srcA = Attribute(op.AttributeOffset, iq);
+ res = context.FPMultiply(res, srcB);
+ }
- Operand res = context.FPSaturate(srcA, op.Saturate);
+ res = context.FPSaturate(res, op.Saturate);
context.Copy(GetDest(context), res);
}
diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Operand.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Operand.cs
index 567277a7..1df88a3d 100644
--- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/Operand.cs
+++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/Operand.cs
@@ -14,8 +14,6 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
public int Value { get; }
- public InterpolationQualifier Interpolation { get; }
-
public INode AsgOp { get; set; }
public HashSet<INode> UseOps { get; }
@@ -30,11 +28,10 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
Type = type;
}
- public Operand(OperandType type, int value, InterpolationQualifier iq = InterpolationQualifier.None) : this()
+ public Operand(OperandType type, int value) : this()
{
- Type = type;
- Value = value;
- Interpolation = iq;
+ Type = type;
+ Value = value;
}
public Operand(Register reg) : this()
diff --git a/Ryujinx.Graphics.Shader/IntermediateRepresentation/OperandHelper.cs b/Ryujinx.Graphics.Shader/IntermediateRepresentation/OperandHelper.cs
index 45c9ba1e..6765f8a4 100644
--- a/Ryujinx.Graphics.Shader/IntermediateRepresentation/OperandHelper.cs
+++ b/Ryujinx.Graphics.Shader/IntermediateRepresentation/OperandHelper.cs
@@ -5,9 +5,9 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
{
static class OperandHelper
{
- public static Operand Attribute(int value, InterpolationQualifier iq = InterpolationQualifier.None)
+ public static Operand Attribute(int value)
{
- return new Operand(OperandType.Attribute, value, iq);
+ return new Operand(OperandType.Attribute, value);
}
public static Operand Cbuf(int slot, int offset)
diff --git a/Ryujinx.Graphics.Shader/InterpolationQualifier.cs b/Ryujinx.Graphics.Shader/InterpolationQualifier.cs
deleted file mode 100644
index b7a0c1c9..00000000
--- a/Ryujinx.Graphics.Shader/InterpolationQualifier.cs
+++ /dev/null
@@ -1,44 +0,0 @@
-using System;
-
-namespace Ryujinx.Graphics.Shader
-{
- [Flags]
- enum InterpolationQualifier
- {
- None = 0,
-
- Flat = 1,
- NoPerspective = 2,
- Smooth = 3,
-
- Centroid = 1 << 16,
- Sample = 1 << 17,
-
- FlagsMask = Centroid | Sample
- }
-
- static class InterpolationQualifierExtensions
- {
- public static string ToGlslQualifier(this InterpolationQualifier iq)
- {
- string output = (iq & ~InterpolationQualifier.FlagsMask) switch
- {
- InterpolationQualifier.Flat => "flat",
- InterpolationQualifier.NoPerspective => "noperspective",
- InterpolationQualifier.Smooth => "smooth",
- _ => string.Empty
- };
-
- if ((iq & InterpolationQualifier.Centroid) != 0)
- {
- output = "centroid " + output;
- }
- else if ((iq & InterpolationQualifier.Sample) != 0)
- {
- output = "sample " + output;
- }
-
- return output;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/ShaderProgram.cs b/Ryujinx.Graphics.Shader/ShaderProgram.cs
index 4d0c6e5b..7a800d8c 100644
--- a/Ryujinx.Graphics.Shader/ShaderProgram.cs
+++ b/Ryujinx.Graphics.Shader/ShaderProgram.cs
@@ -24,10 +24,5 @@ namespace Ryujinx.Graphics.Shader
{
Code = line + Environment.NewLine + Code;
}
-
- public void Replace(string name, string value)
- {
- Code = Code.Replace(name, value);
- }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/AstOperand.cs b/Ryujinx.Graphics.Shader/StructuredIr/AstOperand.cs
index 25b09636..97ff3ca9 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/AstOperand.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/AstOperand.cs
@@ -12,8 +12,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
public VariableType VarType { get; set; }
- public InterpolationQualifier Interpolation { get; }
-
public int Value { get; }
public int CbufSlot { get; }
@@ -29,8 +27,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
public AstOperand(Operand operand) : this()
{
- Type = operand.Type;
- Interpolation = operand.Interpolation;
+ Type = operand.Type;
if (Type == OperandType.ConstantBuffer)
{
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
index f2af84f3..b7d5efbe 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
@@ -273,8 +273,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
if (TryGetUserAttributeIndex(operand, out int attrIndex))
{
Info.IAttributes.Add(attrIndex);
-
- Info.InterpolationQualifiers[attrIndex] = operand.Interpolation;
}
else if (operand.Type == OperandType.Attribute && operand.Value == AttributeConsts.InstanceId)
{
diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs
index 0ef4bde3..be79f00e 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramInfo.cs
@@ -14,8 +14,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
public HashSet<int> IAttributes { get; }
public HashSet<int> OAttributes { get; }
- public InterpolationQualifier[] InterpolationQualifiers { get; }
-
public bool UsesInstanceId { get; set; }
public HelperFunctionsMask HelperFunctionsMask { get; set; }
@@ -35,8 +33,6 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
IAttributes = new HashSet<int>();
OAttributes = new HashSet<int>();
- InterpolationQualifiers = new InterpolationQualifier[32];
-
Samplers = new HashSet<AstTextureOperation>();
Images = new HashSet<AstTextureOperation>();
}
diff --git a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
index 7111196b..8044f074 100644
--- a/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/EmitterContext.cs
@@ -76,7 +76,7 @@ namespace Ryujinx.Graphics.Shader.Translation
for (int attachment = 0; attachment < 8; attachment++)
{
- OutputMapTarget target = _config.OmapTargets[attachment];
+ OmapTarget target = _config.OmapTargets[attachment];
for (int component = 0; component < 4; component++)
{
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index e3708b41..60660847 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -12,9 +12,11 @@ namespace Ryujinx.Graphics.Shader.Translation
public int LocalMemorySize { get; }
- public OutputMapTarget[] OmapTargets { get; }
- public bool OmapSampleMask { get; }
- public bool OmapDepth { get; }
+ public ImapPixelType[] ImapTypes { get; }
+
+ public OmapTarget[] OmapTargets { get; }
+ public bool OmapSampleMask { get; }
+ public bool OmapDepth { get; }
public TranslationFlags Flags { get; }
@@ -26,6 +28,7 @@ namespace Ryujinx.Graphics.Shader.Translation
OutputTopology = OutputTopology.PointList;
MaxOutputVertices = 0;
LocalMemorySize = 0;
+ ImapTypes = null;
OmapTargets = null;
OmapSampleMask = false;
OmapDepth = false;
@@ -39,6 +42,7 @@ namespace Ryujinx.Graphics.Shader.Translation
OutputTopology = header.OutputTopology;
MaxOutputVertices = header.MaxOutputVertexCount;
LocalMemorySize = header.ShaderLocalMemoryLowSize + header.ShaderLocalMemoryHighSize;
+ ImapTypes = header.ImapTypes;
OmapTargets = header.OmapTargets;
OmapSampleMask = header.OmapSampleMask;
OmapDepth = header.OmapDepth;
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
index 42701fbd..a3b861c9 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderHeader.cs
@@ -4,7 +4,39 @@ using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Shader.Translation
{
- struct OutputMapTarget
+ enum PixelImap
+ {
+ Unused = 0,
+ Constant = 1,
+ Perspective = 2,
+ ScreenLinear = 3
+ }
+
+ struct ImapPixelType
+ {
+ public PixelImap X { get; }
+ public PixelImap Y { get; }
+ public PixelImap Z { get; }
+ public PixelImap W { get; }
+
+ public ImapPixelType(PixelImap x, PixelImap y, PixelImap z, PixelImap w)
+ {
+ X = x;
+ Y = y;
+ Z = z;
+ W = w;
+ }
+
+ public PixelImap GetFirstUsedType()
+ {
+ if (X != PixelImap.Unused) return X;
+ if (Y != PixelImap.Unused) return Y;
+ if (Z != PixelImap.Unused) return Z;
+ return W;
+ }
+ }
+
+ struct OmapTarget
{
public bool Red { get; }
public bool Green { get; }
@@ -13,7 +45,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public bool Enabled => Red || Green || Blue || Alpha;
- public OutputMapTarget(bool red, bool green, bool blue, bool alpha)
+ public OmapTarget(bool red, bool green, bool blue, bool alpha)
{
Red = red;
Green = green;
@@ -72,9 +104,11 @@ namespace Ryujinx.Graphics.Shader.Translation
public int StoreReqStart { get; }
public int StoreReqEnd { get; }
- public OutputMapTarget[] OmapTargets { get; }
- public bool OmapSampleMask { get; }
- public bool OmapDepth { get; }
+ public ImapPixelType[] ImapTypes { get; }
+
+ public OmapTarget[] OmapTargets { get; }
+ public bool OmapSampleMask { get; }
+ public bool OmapDepth { get; }
public ShaderHeader(ReadOnlySpan<byte> code)
{
@@ -127,14 +161,30 @@ namespace Ryujinx.Graphics.Shader.Translation
StoreReqStart = commonWord4.Extract(12, 8);
StoreReqEnd = commonWord4.Extract(24, 8);
+ ImapTypes = new ImapPixelType[32];
+
+ for (int i = 0; i < 8; i++)
+ {
+ for (int j = 0; j < 4; j++)
+ {
+ byte imap = (byte)(header[6 + i] >> (j * 8));
+
+ ImapTypes[i * 4 + j] = new ImapPixelType(
+ (PixelImap)((imap >> 0) & 3),
+ (PixelImap)((imap >> 2) & 3),
+ (PixelImap)((imap >> 4) & 3),
+ (PixelImap)((imap >> 6) & 3));
+ }
+ }
+
int type2OmapTarget = header[18];
int type2Omap = header[19];
- OmapTargets = new OutputMapTarget[8];
+ OmapTargets = new OmapTarget[8];
for (int offset = 0; offset < OmapTargets.Length * 4; offset += 4)
{
- OmapTargets[offset >> 2] = new OutputMapTarget(
+ OmapTargets[offset >> 2] = new OmapTarget(
type2OmapTarget.Extract(offset + 0),
type2OmapTarget.Extract(offset + 1),
type2OmapTarget.Extract(offset + 2),