SPIR-V: Implement LoopContinue IR instruction

This commit is contained in:
gdk 2022-02-13 23:00:20 -03:00 committed by riperiperi
parent aa0913838d
commit 3c949309e5
3 changed files with 21 additions and 0 deletions

View file

@ -57,6 +57,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private readonly Dictionary<AstBlock, BlockState> _labels = new Dictionary<AstBlock, BlockState>();
public Dictionary<AstBlock, (Instruction, Instruction)> LoopTargets { get; set; }
public AstBlock CurrentBlock { get; private set; }
public CodeGenContext(ShaderConfig config) : base(0x00010300)

View file

@ -95,6 +95,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Add(Instruction.LogicalNot, GenerateLogicalNot);
Add(Instruction.LogicalOr, GenerateLogicalOr);
Add(Instruction.LoopBreak, GenerateLoopBreak);
Add(Instruction.LoopContinue, GenerateLoopContinue);
Add(Instruction.Maximum, GenerateMaximum);
Add(Instruction.MaximumU32, GenerateMaximumU32);
Add(Instruction.MemoryBarrier, GenerateMemoryBarrier);
@ -963,6 +964,21 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
return OperationResult.Invalid;
}
private static OperationResult GenerateLoopContinue(CodeGenContext context, AstOperation operation)
{
AstBlock loopBlock = context.CurrentBlock;
while (loopBlock.Type != AstBlockType.DoWhile)
{
loopBlock = loopBlock.Parent;
}
(var loopTarget, var continueTarget) = context.LoopTargets[loopBlock];
context.Branch(continueTarget);
return OperationResult.Invalid;
}
private static OperationResult GenerateMaximum(CodeGenContext context, AstOperation operation)
{
return GenerateBinary(context, operation, context.GlslFMax, context.GlslSMax);

View file

@ -130,6 +130,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
var loopTargets = new Dictionary<AstBlock, (SpvInstruction, SpvInstruction)>();
context.LoopTargets = loopTargets;
visitor.BlockEntered += (sender, e) =>
{
AstBlock mergeBlock = e.Block.Parent;
@ -192,6 +194,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
bool lastIsCf = e.Block.Last is AstOperation lastOp &&
(lastOp.Inst == Instruction.Discard ||
lastOp.Inst == Instruction.LoopBreak ||
lastOp.Inst == Instruction.LoopContinue ||
lastOp.Inst == Instruction.Return);
if (!lastIsCf)