diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/video_core/engines/shader_bytecode.h | 10 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 55 |
2 files changed, 43 insertions, 22 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index f356f9a03..8c8d65769 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h @@ -1095,11 +1095,13 @@ public: KIL, SSY, SYNC, + BRK, DEPBAR, BFE_C, BFE_R, BFE_IMM, BRA, + PBK, LD_A, LD_C, ST_A, @@ -1239,7 +1241,7 @@ public: /// conditionally executed). static bool IsPredicatedInstruction(Id opcode) { // TODO(Subv): Add the rest of unpredicated instructions. - return opcode != Id::SSY; + return opcode != Id::SSY && opcode != Id::PBK; } class Matcher { @@ -1335,9 +1337,11 @@ private: #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) INST("111000110011----", Id::KIL, Type::Flow, "KIL"), INST("111000101001----", Id::SSY, Type::Flow, "SSY"), + INST("111000101010----", Id::PBK, Type::Flow, "PBK"), INST("111000100100----", Id::BRA, Type::Flow, "BRA"), + INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"), + INST("111000110100---", Id::BRK, Type::Flow, "BRK"), INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"), - INST("1111000011111---", Id::SYNC, Type::Synch, "SYNC"), INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"), @@ -1463,4 +1467,4 @@ private: } }; -} // namespace Tegra::Shader +} // namespace Tegra::Shader
\ No newline at end of file diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index ca063d90d..db52841f3 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp @@ -165,10 +165,11 @@ private: const ExitMethod jmp = Scan(target, end, labels); return exit_method = ParallelExit(no_jmp, jmp); } - case OpCode::Id::SSY: { - // The SSY instruction uses a similar encoding as the BRA instruction. + case OpCode::Id::SSY: + case OpCode::Id::PBK: { + // The SSY and PBK use a similar encoding as the BRA instruction. ASSERT_MSG(instr.bra.constant_buffer == 0, - "Constant buffer SSY is not supported"); + "Constant buffer branching is not supported"); const u32 target = offset + instr.bra.GetBranchTarget(); labels.insert(target); // Continue scanning for an exit method. @@ -1153,27 +1154,27 @@ private: } /* - * Emits code to push the input target address to the SSY address stack, incrementing the stack + * Emits code to push the input target address to the flow address stack, incrementing the stack * top. */ - void EmitPushToSSYStack(u32 target) { + void EmitPushToFlowStack(u32 target) { shader.AddLine('{'); ++shader.scope; - shader.AddLine("ssy_stack[ssy_stack_top] = " + std::to_string(target) + "u;"); - shader.AddLine("ssy_stack_top++;"); + shader.AddLine("flow_stack[flow_stack_top] = " + std::to_string(target) + "u;"); + shader.AddLine("flow_stack_top++;"); --shader.scope; shader.AddLine('}'); } /* - * Emits code to pop an address from the SSY address stack, setting the jump address to the + * Emits code to pop an address from the flow address stack, setting the jump address to the * popped address and decrementing the stack top. */ - void EmitPopFromSSYStack() { + void EmitPopFromFlowStack() { shader.AddLine('{'); ++shader.scope; - shader.AddLine("ssy_stack_top--;"); - shader.AddLine("jmp_to = ssy_stack[ssy_stack_top];"); + shader.AddLine("flow_stack_top--;"); + shader.AddLine("jmp_to = flow_stack[flow_stack_top];"); shader.AddLine("break;"); --shader.scope; shader.AddLine('}'); @@ -2933,16 +2934,32 @@ private: // The SSY opcode tells the GPU where to re-converge divergent execution paths, it // 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"); + ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer flow is not supported"); const u32 target = offset + instr.bra.GetBranchTarget(); - EmitPushToSSYStack(target); + EmitPushToFlowStack(target); + break; + } + case OpCode::Id::PBK: { + // PBK pushes to a stack the address where BRK will jump to. This shares stack with + // SSY but using SYNC on a PBK address will kill the shader execution. We don't + // emulate this because it's very unlikely a driver will emit such invalid shader. + ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer PBK is not supported"); + + const u32 target = offset + instr.bra.GetBranchTarget(); + EmitPushToFlowStack(target); break; } 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); - EmitPopFromSSYStack(); + EmitPopFromFlowStack(); + break; + } + case OpCode::Id::BRK: { + // The BRK opcode jumps to the address previously set by the PBK opcode + ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); + EmitPopFromFlowStack(); break; } case OpCode::Id::DEPBAR: { @@ -3096,11 +3113,11 @@ private: labels.insert(subroutine.begin); shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;"); - // TODO(Subv): Figure out the actual depth of the SSY stack, for now it seems - // unlikely that shaders will use 20 nested SSYs. - constexpr u32 SSY_STACK_SIZE = 20; - shader.AddLine("uint ssy_stack[" + std::to_string(SSY_STACK_SIZE) + "];"); - shader.AddLine("uint ssy_stack_top = 0u;"); + // TODO(Subv): Figure out the actual depth of the flow stack, for now it seems + // unlikely that shaders will use 20 nested SSYs and PBKs. + constexpr u32 FLOW_STACK_SIZE = 20; + shader.AddLine("uint flow_stack[" + std::to_string(FLOW_STACK_SIZE) + "];"); + shader.AddLine("uint flow_stack_top = 0u;"); shader.AddLine("while (true) {"); ++shader.scope; |