Skip to content
Snippets Groups Projects
Commit 305a05f8 authored by Subv's avatar Subv
Browse files

GPU/Shaders: Implemented SSY and SYNC as a way to modify control flow during shader execution.

SSY sets the target label to jump to when the SYNC instruction is executed.
parent 4f081814
No related branches found
No related tags found
No related merge requests found
...@@ -141,6 +141,15 @@ private: ...@@ -141,6 +141,15 @@ private:
ExitMethod jmp = Scan(target, end, labels); ExitMethod jmp = Scan(target, end, labels);
return exit_method = ParallelExit(no_jmp, jmp); return exit_method = ParallelExit(no_jmp, jmp);
} }
case OpCode::Id::SSY: {
// The SSY instruction uses a similar encoding as the BRA instruction.
ASSERT_MSG(instr.bra.constant_buffer == 0,
"Constant buffer SSY is not supported");
u32 target = offset + instr.bra.GetBranchTarget();
labels.insert(target);
// Continue scanning for an exit method.
break;
}
} }
} }
} }
...@@ -1668,16 +1677,25 @@ private: ...@@ -1668,16 +1677,25 @@ private:
break; break;
} }
case OpCode::Id::SSY: { case OpCode::Id::SSY: {
// The SSY opcode tells the GPU where to re-converge divergent execution paths, we // The SSY opcode tells the GPU where to re-converge divergent execution paths, it
// can ignore this when generating GLSL code. // sets the target of the jump that the SYNC instruction will make. The SSY opcode
// has a similar structure to the BRA opcode.
ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported");
u32 target = offset + instr.bra.GetBranchTarget();
shader.AddLine("ssy_target = " + std::to_string(target) + "u;");
break; break;
} }
case OpCode::Id::SYNC: case OpCode::Id::SYNC: {
// The SYNC opcode jumps to the address previously set by the SSY opcode
ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
shader.AddLine("{ jmp_to = ssy_target; break; }");
break;
}
case OpCode::Id::DEPBAR: { case OpCode::Id::DEPBAR: {
// TODO(Subv): Find out if we actually have to care about these instructions or if // TODO(Subv): Find out if we actually have to care about this instruction or if
// the GLSL compiler takes care of that for us. // the GLSL compiler takes care of that for us.
LOG_WARNING(HW_GPU, "DEPBAR/SYNC instruction is stubbed"); LOG_WARNING(HW_GPU, "DEPBAR instruction is stubbed");
break; break;
} }
default: { default: {
...@@ -1742,6 +1760,7 @@ private: ...@@ -1742,6 +1760,7 @@ private:
} else { } else {
labels.insert(subroutine.begin); labels.insert(subroutine.begin);
shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;"); shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;");
shader.AddLine("uint ssy_target = 0u;");
shader.AddLine("while (true) {"); shader.AddLine("while (true) {");
++shader.scope; ++shader.scope;
...@@ -1757,7 +1776,7 @@ private: ...@@ -1757,7 +1776,7 @@ private:
u32 compile_end = CompileRange(label, next_label); u32 compile_end = CompileRange(label, next_label);
if (compile_end > next_label && compile_end != PROGRAM_END) { if (compile_end > next_label && compile_end != PROGRAM_END) {
// This happens only when there is a label inside a IF/LOOP block // This happens only when there is a label inside a IF/LOOP block
shader.AddLine("{ jmp_to = " + std::to_string(compile_end) + "u; break; }"); shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }");
labels.emplace(compile_end); labels.emplace(compile_end);
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment