diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs index 46841d48a..84de8bd6e 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs @@ -57,6 +57,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv private readonly Dictionary _labels = new Dictionary(); + public Dictionary LoopTargets { get; set; } + public AstBlock CurrentBlock { get; private set; } public CodeGenContext(ShaderConfig config) : base(0x00010300) diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs index f5d9e70db..3375e8d64 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs @@ -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); diff --git a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs index 1a2157f24..67caa18e9 100644 --- a/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs +++ b/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs @@ -130,6 +130,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv var loopTargets = new Dictionary(); + 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)