mirror of
				https://git.h3cjp.net/H3cJP/citra.git
				synced 2025-10-31 06:55:03 +00:00 
			
		
		
		
	Merge pull request #1512 from ReinUsesLisp/brk
gl_shader_decompiler: Implement PBK and BRK
This commit is contained in:
		
						commit
						848a49112a
					
				|  | @ -1213,11 +1213,13 @@ public: | |||
|         KIL, | ||||
|         SSY, | ||||
|         SYNC, | ||||
|         BRK, | ||||
|         DEPBAR, | ||||
|         BFE_C, | ||||
|         BFE_R, | ||||
|         BFE_IMM, | ||||
|         BRA, | ||||
|         PBK, | ||||
|         LD_A, | ||||
|         LD_C, | ||||
|         ST_A, | ||||
|  | @ -1374,7 +1376,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 { | ||||
|  | @ -1470,9 +1472,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"), | ||||
|  | @ -1610,4 +1614,4 @@ private: | |||
|     } | ||||
| }; | ||||
| 
 | ||||
| } // namespace Tegra::Shader
 | ||||
| } // namespace Tegra::Shader
 | ||||
|  | @ -163,10 +163,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.
 | ||||
|  | @ -1233,27 +1234,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('}'); | ||||
|  | @ -3265,16 +3266,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: { | ||||
|  | @ -3428,11 +3445,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; | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue