mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-11-18 15:16:39 +00:00
Fix exception on shader translator when adding goto temp variable
This commit is contained in:
parent
82957fa96b
commit
a718b60d06
1 changed files with 20 additions and 0 deletions
|
@ -78,13 +78,19 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
|
|
||||||
foreach (BasicBlock predecessor in block.Predecessors.OrderByDescending(x => x.Index))
|
foreach (BasicBlock predecessor in block.Predecessors.OrderByDescending(x => x.Index))
|
||||||
{
|
{
|
||||||
|
// If not a loop, break.
|
||||||
if (predecessor.Index < block.Index)
|
if (predecessor.Index < block.Index)
|
||||||
{
|
{
|
||||||
break;
|
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)
|
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();
|
Operation branchOp = (Operation)predecessor.GetLastOp();
|
||||||
|
|
||||||
NewBlock(AstBlockType.DoWhile, branchOp, predecessor.Index + 1);
|
NewBlock(AstBlockType.DoWhile, branchOp, predecessor.Index + 1);
|
||||||
|
@ -95,6 +101,9 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
}
|
}
|
||||||
else
|
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));
|
AddGotoTempReset(block, GetGotoTempAsg(block.Index));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -129,6 +138,8 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
{
|
{
|
||||||
AstAssignment gotoTempAsg = GetGotoTempAsg(block.Branch.Index);
|
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);
|
IAstNode cond = GetBranchCond(AstBlockType.DoWhile, branchOp);
|
||||||
|
|
||||||
AddNode(Assign(gotoTempAsg.Destination, cond));
|
AddNode(Assign(gotoTempAsg.Destination, cond));
|
||||||
|
@ -161,6 +172,12 @@ namespace Ryujinx.Graphics.Shader.StructuredIr
|
||||||
|
|
||||||
private void AddGotoTempReset(BasicBlock block, AstAssignment gotoTempAsg)
|
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);
|
AddNode(gotoTempAsg);
|
||||||
|
|
||||||
// For block 0, we don't need to add the extra "reset" at the beginning,
|
// 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 (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);
|
cond = Const(type == AstBlockType.If ? IrConsts.False : IrConsts.True);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in a new issue