From a718b60d06f5ad2219d5896c7739c29444560811 Mon Sep 17 00:00:00 2001
From: gdkchan <gab.dark.100@gmail.com>
Date: Tue, 24 Dec 2019 17:52:16 -0300
Subject: [PATCH] Fix exception on shader translator when adding goto temp
 variable

---
 .../StructuredIr/StructuredProgramContext.cs  | 20 +++++++++++++++++++
 1 file changed, 20 insertions(+)

diff --git a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
index 55958a12e..f2af84f3b 100644
--- a/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
+++ b/Ryujinx.Graphics.Shader/StructuredIr/StructuredProgramContext.cs
@@ -78,13 +78,19 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
 
             foreach (BasicBlock predecessor in block.Predecessors.OrderByDescending(x => x.Index))
             {
+                // If not a loop, break.
                 if (predecessor.Index < block.Index)
                 {
                     break;
                 }
 
+                // Check if we can create a do-while loop here (only possible if the loop end
+                // falls inside the current scope), if not add a goto instead.
                 if (predecessor.Index < _currEndIndex && !done)
                 {
+                    // Create do-while loop block. We must avoid inserting a goto at the end
+                    // of the loop later, when the tail block is processed. So we add the predecessor
+                    // to a list of loop tails to prevent it from being processed later.
                     Operation branchOp = (Operation)predecessor.GetLastOp();
 
                     NewBlock(AstBlockType.DoWhile, branchOp, predecessor.Index + 1);
@@ -95,6 +101,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
                 }
                 else
                 {
+                    // Failed to create loop. Since this block is the loop head, we reset the
+                    // goto condition variable here. The variable is always reset on the jump
+                    // target, and this block is the jump target for some loop.
                     AddGotoTempReset(block, GetGotoTempAsg(block.Index));
 
                     break;
@@ -129,6 +138,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
             {
                 AstAssignment gotoTempAsg = GetGotoTempAsg(block.Branch.Index);
 
+                // We use DoWhile type here, as the condition should be true for
+                // unconditional branches, or it should jump if the condition is true otherwise.
                 IAstNode cond = GetBranchCond(AstBlockType.DoWhile, branchOp);
 
                 AddNode(Assign(gotoTempAsg.Destination, cond));
@@ -161,6 +172,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
 
         private void AddGotoTempReset(BasicBlock block, AstAssignment gotoTempAsg)
         {
+            // If it was already added, we don't need to add it again.
+            if (gotoTempAsg.Parent != null)
+            {
+                return;
+            }
+
             AddNode(gotoTempAsg);
 
             // For block 0, we don't need to add the extra "reset" at the beginning,
@@ -200,6 +217,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
 
             if (branchOp.Inst == Instruction.Branch)
             {
+                // If the branch is not conditional, the condition is a constant.
+                // For if it's false (always jump over, if block never executed).
+                // For loops it's always true (always loop).
                 cond = Const(type == AstBlockType.If ? IrConsts.False : IrConsts.True);
             }
             else