aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Gal/Shader
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-04-13 15:12:58 -0300
committerGitHub <noreply@github.com>2018-04-13 15:12:58 -0300
commitc8c86a3854fb3c96e65eca6b59d6058270a21a17 (patch)
tree0f280e0b595d953ca081e493eda41d884fb34ef6 /Ryujinx.Graphics/Gal/Shader
parent262b5b80541d23ed248d5b4f2220a479a35d5969 (diff)
Fix for current framebuffer issues (#78)
[GPU] Fix some of the current framebuffer issues
Diffstat (limited to 'Ryujinx.Graphics/Gal/Shader')
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs2
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs21
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs4
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs5
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs366
5 files changed, 18 insertions, 380 deletions
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index e155e475..82dbff9f 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -81,7 +81,7 @@ namespace Ryujinx.Graphics.Gal.Shader
public GlslProgram Decompile(int[] Code, GalShaderType ShaderType)
{
- ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0, ShaderType);
+ ShaderIrBlock Block = ShaderDecoder.DecodeBasicBlock(Code, 0);
ShaderIrNode[] Nodes = Block.GetNodes();
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
index 6553cfcf..33f58231 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
@@ -74,11 +74,9 @@ namespace Ryujinx.Graphics.Gal.Shader
for (int Ch = 0; Ch < 4; Ch++)
{
- ShaderIrOperGpr Dst = (Ch >> 1) != 0
- ? GetOperGpr28(OpCode)
- : GetOperGpr0 (OpCode);
-
- Dst.Index += Ch & 1;
+ //Assign it to a temp because the destination registers
+ //may be used as texture coord input aswell.
+ ShaderIrOperGpr Dst = new ShaderIrOperGpr(0x100 + Ch);
ShaderIrMetaTex Meta = new ShaderIrMetaTex(Ch);
@@ -86,6 +84,19 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Op), OpCode));
}
+
+ for (int Ch = 0; Ch < 4; Ch++)
+ {
+ ShaderIrOperGpr Src = new ShaderIrOperGpr(0x100 + Ch);
+
+ ShaderIrOperGpr Dst = (Ch >> 1) != 0
+ ? GetOperGpr28(OpCode)
+ : GetOperGpr0 (OpCode);
+
+ Dst.Index += Ch & 1;
+
+ Block.AddNode(GetPredNode(new ShaderIrAsg(Dst, Src), OpCode));
+ }
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
index 7bebea62..e44d5b7d 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
@@ -2,7 +2,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{
static class ShaderDecoder
{
- public static ShaderIrBlock DecodeBasicBlock(int[] Code, int Offset, GalShaderType ShaderType)
+ public static ShaderIrBlock DecodeBasicBlock(int[] Code, int Offset)
{
ShaderIrBlock Block = new ShaderIrBlock();
@@ -37,8 +37,6 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
- Block.RunOptimizationPasses(ShaderType);
-
return Block;
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
index 1a96d3be..c920d9fa 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
@@ -16,11 +16,6 @@ namespace Ryujinx.Graphics.Gal.Shader
Nodes.Add(Node);
}
- public void RunOptimizationPasses(GalShaderType ShaderType)
- {
- ShaderOptExprProp.Optimize(Nodes, ShaderType);
- }
-
public ShaderIrNode[] GetNodes()
{
return Nodes.ToArray();
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs
deleted file mode 100644
index 9ce7cbe3..00000000
--- a/Ryujinx.Graphics/Gal/Shader/ShaderOptExprProp.cs
+++ /dev/null
@@ -1,366 +0,0 @@
-using System;
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics.Gal.Shader
-{
- static class ShaderOptExprProp
- {
- private struct UseSite
- {
- public ShaderIrNode Parent { get; private set; }
- public ShaderIrCond Cond { get; private set; }
-
- public int UseIndex { get; private set; }
-
- public int OperIndex { get; private set; }
-
- public UseSite(
- ShaderIrNode Parent,
- ShaderIrCond Cond,
- int UseIndex,
- int OperIndex)
- {
- this.Parent = Parent;
- this.Cond = Cond;
- this.UseIndex = UseIndex;
- this.OperIndex = OperIndex;
- }
- }
-
- private class RegUse
- {
- public ShaderIrAsg Asg { get; private set; }
-
- public int AsgIndex { get; private set; }
-
- public int LastSiteIndex { get; private set; }
-
- public ShaderIrCond Cond { get; private set; }
-
- private List<UseSite> Sites;
-
- public RegUse()
- {
- Sites = new List<UseSite>();
- }
-
- public void AddUseSite(UseSite Site)
- {
- if (LastSiteIndex < Site.UseIndex)
- {
- LastSiteIndex = Site.UseIndex;
- }
-
- Sites.Add(Site);
- }
-
- public bool TryPropagate()
- {
- //This happens when a untiliazied register is used,
- //this usually indicates a decoding error, but may also
- //be caused by bogus programs (?). In any case, we just
- //keep the unitialized access and avoid trying to propagate
- //the expression (since we can't propagate what doesn't yet exist).
- if (Asg == null)
- {
- return false;
- }
-
- if (Cond != null)
- {
- //If the assignment is conditional, we can only propagate
- //to the use sites that shares the same condition of the assignment.
- foreach (UseSite Site in Sites)
- {
- if (!IsSameCondition(Cond, Site.Cond))
- {
- return false;
- }
- }
- }
-
- if (Sites.Count > 0)
- {
- foreach (UseSite Site in Sites)
- {
- if (Site.Parent is ShaderIrCond Cond)
- {
- switch (Site.OperIndex)
- {
- case 0: Cond.Pred = Asg.Src; break;
- case 1: Cond.Child = Asg.Src; break;
-
- default: throw new InvalidOperationException();
- }
- }
- else if (Site.Parent is ShaderIrOp Op)
- {
- switch (Site.OperIndex)
- {
- case 0: Op.OperandA = Asg.Src; break;
- case 1: Op.OperandB = Asg.Src; break;
- case 2: Op.OperandC = Asg.Src; break;
-
- default: throw new InvalidOperationException();
- }
- }
- else if (Site.Parent is ShaderIrAsg SiteAsg)
- {
- SiteAsg.Src = Asg.Src;
- }
- else
- {
- throw new InvalidOperationException();
- }
- }
- }
-
- return true;
- }
-
- public void SetNewAsg(ShaderIrAsg Asg, int AsgIndex, ShaderIrCond Cond)
- {
- this.Asg = Asg;
- this.AsgIndex = AsgIndex;
- this.Cond = Cond;
-
- LastSiteIndex = 0;
-
- Sites.Clear();
- }
- }
-
- public static void Optimize(List<ShaderIrNode> Nodes, GalShaderType ShaderType)
- {
- Dictionary<int, RegUse> Uses = new Dictionary<int, RegUse>();
-
- RegUse GetUse(int Key)
- {
- RegUse Use;
-
- if (!Uses.TryGetValue(Key, out Use))
- {
- Use = new RegUse();
-
- Uses.Add(Key, Use);
- }
-
- return Use;
- }
-
- int GetGprKey(int GprIndex)
- {
- return GprIndex;
- }
-
- int GetPredKey(int PredIndex)
- {
- return PredIndex | 0x10000000;
- }
-
- RegUse GetGprUse(int GprIndex)
- {
- return GetUse(GetGprKey(GprIndex));
- }
-
- RegUse GetPredUse(int PredIndex)
- {
- return GetUse(GetPredKey(PredIndex));
- }
-
- void RemoveUse(RegUse Use)
- {
- if (!Nodes.Remove((ShaderIrNode)Use.Cond ?? Use.Asg))
- {
- throw new InvalidOperationException();
- }
- }
-
- void FindRegUses(
- List<(int, UseSite)> UseList,
- ShaderIrNode Parent,
- ShaderIrNode Node,
- ShaderIrCond CondNode,
- int UseIndex,
- int OperIndex = 0)
- {
- if (Node is ShaderIrAsg Asg)
- {
- FindRegUses(UseList, Asg, Asg.Src, CondNode, UseIndex);
- }
- else if (Node is ShaderIrCond Cond)
- {
- FindRegUses(UseList, Cond, Cond.Pred, CondNode, UseIndex, 0);
- FindRegUses(UseList, Cond, Cond.Child, CondNode, UseIndex, 1);
- }
- else if (Node is ShaderIrOp Op)
- {
- FindRegUses(UseList, Op, Op.OperandA, CondNode, UseIndex, 0);
- FindRegUses(UseList, Op, Op.OperandB, CondNode, UseIndex, 1);
- FindRegUses(UseList, Op, Op.OperandC, CondNode, UseIndex, 2);
- }
- else if (Node is ShaderIrOperGpr Gpr && !Gpr.IsConst)
- {
- UseList.Add((GetGprKey(Gpr.Index), new UseSite(Parent, CondNode, UseIndex, OperIndex)));
- }
- else if (Node is ShaderIrOperPred Pred)
- {
- UseList.Add((GetPredKey(Pred.Index), new UseSite(Parent, CondNode, UseIndex, OperIndex)));
- }
- }
-
- void TryAddRegUseSite(ShaderIrNode Node, ShaderIrCond CondNode, int UseIndex)
- {
- List<(int, UseSite)> UseList = new List<(int, UseSite)>();
-
- FindRegUses(UseList, null, Node, CondNode, UseIndex);
-
- foreach ((int Key, UseSite Site) in UseList)
- {
- GetUse(Key).AddUseSite(Site);
- }
- }
-
- bool TryPropagate(RegUse Use)
- {
- //We can only propagate if the registers that the expression depends
- //on weren't assigned after the original expression assignment
- //to a register took place. We traverse the expression tree to find
- //all registers being used, if any of those registers was assigned
- //after the assignment to be propagated, then we can't propagate.
- if (Use?.Asg == null)
- {
- return false;
- }
-
- List<(int, UseSite)> UseList = new List<(int, UseSite)>();
-
- if (Use.Cond != null)
- {
- FindRegUses(UseList, null, Use.Cond, null, 0);
- }
- else
- {
- FindRegUses(UseList, Use.Asg, Use.Asg.Src, null, 0);
- }
-
- foreach ((int Key, UseSite Site) in UseList)
- {
- //TODO: Build an assignment list inside RegUse,
- //and check if there is an assignment inside the
- //range of Use.AsgIndex and Use.LastSiteIndex,
- //and if that's the case, then we should return false.
- //The current method is too conservative.
- if (GetUse(Key).AsgIndex >= Use.AsgIndex)
- {
- return false;
- }
- }
-
- return Use.TryPropagate();
- }
-
- for (int Index = 0, IterCount = 0; Index < Nodes.Count; Index++, IterCount++)
- {
- ShaderIrNode Node = Nodes[Index];
-
- ShaderIrCond CondNode = null;
-
- if (Node is ShaderIrCond)
- {
- CondNode = (ShaderIrCond)Node;
- }
-
- TryAddRegUseSite(Node, CondNode, IterCount);;
-
- while (Node is ShaderIrCond Cond)
- {
- Node = Cond.Child;
- }
-
- if (!(Node is ShaderIrAsg Asg))
- {
- continue;
- }
-
- RegUse Use = null;
-
- if (Asg.Dst is ShaderIrOperGpr Gpr && !Gpr.IsConst)
- {
- Use = GetGprUse(Gpr.Index);
- }
- else if (Asg.Dst is ShaderIrOperPred Pred)
- {
- Use = GetPredUse(Pred.Index);
- }
-
- bool CanRemoveAsg = CondNode == null;
-
- CanRemoveAsg |= IsSameCondition(CondNode, Use?.Cond);
-
- if (CanRemoveAsg && TryPropagate(Use))
- {
- RemoveUse(Use);
-
- //Note: Only decrement if the removal was successful.
- //RemoveUse throws when this is not the case so we should be good.
- Index--;
- }
-
- //All nodes inside conditional nodes can't be propagated,
- //as we don't even know if they will be executed to begin with.
- Use?.SetNewAsg(Asg, IterCount, CondNode);
- }
-
- foreach (RegUse Use in Uses.Values)
- {
- //Gprs 0-3 are the color output on fragment shaders,
- //so we can't remove the last assignments to those registers.
- if (ShaderType == GalShaderType.Fragment)
- {
- if (Use.Asg?.Dst is ShaderIrOperGpr Gpr && Gpr.Index < 4)
- {
- continue;
- }
- }
-
- if (TryPropagate(Use))
- {
- RemoveUse(Use);
- }
- }
- }
-
- private static bool IsSameCondition(ShaderIrCond CondA, ShaderIrCond CondB)
- {
- if (CondA == null || CondB == null)
- {
- return CondA == CondB;
- }
-
- if (CondA.Not != CondB.Not)
- {
- return false;
- }
-
- if (CondA.Pred is ShaderIrOperPred PredA)
- {
- if (!(CondB.Pred is ShaderIrOperPred PredB))
- {
- return false;
- }
-
- if (PredA.Index != PredB.Index)
- {
- return false;
- }
- }
- else if (CondA.Pred != CondB.Pred)
- {
- return false;
- }
-
- return true;
- }
- }
-} \ No newline at end of file