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 d3095089c..ac50bb622 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -1213,11 +1213,13 @@ public: | |||
| 1213 | KIL, | 1213 | KIL, |
| 1214 | SSY, | 1214 | SSY, |
| 1215 | SYNC, | 1215 | SYNC, |
| 1216 | BRK, | ||
| 1216 | DEPBAR, | 1217 | DEPBAR, |
| 1217 | BFE_C, | 1218 | BFE_C, |
| 1218 | BFE_R, | 1219 | BFE_R, |
| 1219 | BFE_IMM, | 1220 | BFE_IMM, |
| 1220 | BRA, | 1221 | BRA, |
| 1222 | PBK, | ||
| 1221 | LD_A, | 1223 | LD_A, |
| 1222 | LD_C, | 1224 | LD_C, |
| 1223 | ST_A, | 1225 | ST_A, |
| @@ -1374,7 +1376,7 @@ public: | |||
| 1374 | /// conditionally executed). | 1376 | /// conditionally executed). |
| 1375 | static bool IsPredicatedInstruction(Id opcode) { | 1377 | static bool IsPredicatedInstruction(Id opcode) { |
| 1376 | // TODO(Subv): Add the rest of unpredicated instructions. | 1378 | // TODO(Subv): Add the rest of unpredicated instructions. |
| 1377 | return opcode != Id::SSY; | 1379 | return opcode != Id::SSY && opcode != Id::PBK; |
| 1378 | } | 1380 | } |
| 1379 | 1381 | ||
| 1380 | class Matcher { | 1382 | class Matcher { |
| @@ -1470,9 +1472,11 @@ private: | |||
| 1470 | #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) | 1472 | #define INST(bitstring, op, type, name) Detail::GetMatcher(bitstring, op, type, name) |
| 1471 | INST("111000110011----", Id::KIL, Type::Flow, "KIL"), | 1473 | INST("111000110011----", Id::KIL, Type::Flow, "KIL"), |
| 1472 | INST("111000101001----", Id::SSY, Type::Flow, "SSY"), | 1474 | INST("111000101001----", Id::SSY, Type::Flow, "SSY"), |
| 1475 | INST("111000101010----", Id::PBK, Type::Flow, "PBK"), | ||
| 1473 | INST("111000100100----", Id::BRA, Type::Flow, "BRA"), | 1476 | INST("111000100100----", Id::BRA, Type::Flow, "BRA"), |
| 1477 | INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"), | ||
| 1478 | INST("111000110100---", Id::BRK, Type::Flow, "BRK"), | ||
| 1474 | INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"), | 1479 | INST("1111000011110---", Id::DEPBAR, Type::Synch, "DEPBAR"), |
| 1475 | INST("1111000011111---", Id::SYNC, Type::Synch, "SYNC"), | ||
| 1476 | INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), | 1480 | INST("1110111111011---", Id::LD_A, Type::Memory, "LD_A"), |
| 1477 | INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), | 1481 | INST("1110111110010---", Id::LD_C, Type::Memory, "LD_C"), |
| 1478 | INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"), | 1482 | INST("1110111111110---", Id::ST_A, Type::Memory, "ST_A"), |
| @@ -1610,4 +1614,4 @@ private: | |||
| 1610 | } | 1614 | } |
| 1611 | }; | 1615 | }; |
| 1612 | 1616 | ||
| 1613 | } // namespace Tegra::Shader | 1617 | } // 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 a3daef014..d36f190b7 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -163,10 +163,11 @@ private: | |||
| 163 | const ExitMethod jmp = Scan(target, end, labels); | 163 | const ExitMethod jmp = Scan(target, end, labels); |
| 164 | return exit_method = ParallelExit(no_jmp, jmp); | 164 | return exit_method = ParallelExit(no_jmp, jmp); |
| 165 | } | 165 | } |
| 166 | case OpCode::Id::SSY: { | 166 | case OpCode::Id::SSY: |
| 167 | // The SSY instruction uses a similar encoding as the BRA instruction. | 167 | case OpCode::Id::PBK: { |
| 168 | // The SSY and PBK use a similar encoding as the BRA instruction. | ||
| 168 | ASSERT_MSG(instr.bra.constant_buffer == 0, | 169 | ASSERT_MSG(instr.bra.constant_buffer == 0, |
| 169 | "Constant buffer SSY is not supported"); | 170 | "Constant buffer branching is not supported"); |
| 170 | const u32 target = offset + instr.bra.GetBranchTarget(); | 171 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 171 | labels.insert(target); | 172 | labels.insert(target); |
| 172 | // Continue scanning for an exit method. | 173 | // Continue scanning for an exit method. |
| @@ -1233,27 +1234,27 @@ private: | |||
| 1233 | } | 1234 | } |
| 1234 | 1235 | ||
| 1235 | /* | 1236 | /* |
| 1236 | * Emits code to push the input target address to the SSY address stack, incrementing the stack | 1237 | * Emits code to push the input target address to the flow address stack, incrementing the stack |
| 1237 | * top. | 1238 | * top. |
| 1238 | */ | 1239 | */ |
| 1239 | void EmitPushToSSYStack(u32 target) { | 1240 | void EmitPushToFlowStack(u32 target) { |
| 1240 | shader.AddLine('{'); | 1241 | shader.AddLine('{'); |
| 1241 | ++shader.scope; | 1242 | ++shader.scope; |
| 1242 | shader.AddLine("ssy_stack[ssy_stack_top] = " + std::to_string(target) + "u;"); | 1243 | shader.AddLine("flow_stack[flow_stack_top] = " + std::to_string(target) + "u;"); |
| 1243 | shader.AddLine("ssy_stack_top++;"); | 1244 | shader.AddLine("flow_stack_top++;"); |
| 1244 | --shader.scope; | 1245 | --shader.scope; |
| 1245 | shader.AddLine('}'); | 1246 | shader.AddLine('}'); |
| 1246 | } | 1247 | } |
| 1247 | 1248 | ||
| 1248 | /* | 1249 | /* |
| 1249 | * Emits code to pop an address from the SSY address stack, setting the jump address to the | 1250 | * Emits code to pop an address from the flow address stack, setting the jump address to the |
| 1250 | * popped address and decrementing the stack top. | 1251 | * popped address and decrementing the stack top. |
| 1251 | */ | 1252 | */ |
| 1252 | void EmitPopFromSSYStack() { | 1253 | void EmitPopFromFlowStack() { |
| 1253 | shader.AddLine('{'); | 1254 | shader.AddLine('{'); |
| 1254 | ++shader.scope; | 1255 | ++shader.scope; |
| 1255 | shader.AddLine("ssy_stack_top--;"); | 1256 | shader.AddLine("flow_stack_top--;"); |
| 1256 | shader.AddLine("jmp_to = ssy_stack[ssy_stack_top];"); | 1257 | shader.AddLine("jmp_to = flow_stack[flow_stack_top];"); |
| 1257 | shader.AddLine("break;"); | 1258 | shader.AddLine("break;"); |
| 1258 | --shader.scope; | 1259 | --shader.scope; |
| 1259 | shader.AddLine('}'); | 1260 | shader.AddLine('}'); |
| @@ -3265,16 +3266,32 @@ private: | |||
| 3265 | // The SSY opcode tells the GPU where to re-converge divergent execution paths, it | 3266 | // The SSY opcode tells the GPU where to re-converge divergent execution paths, it |
| 3266 | // sets the target of the jump that the SYNC instruction will make. The SSY opcode | 3267 | // sets the target of the jump that the SYNC instruction will make. The SSY opcode |
| 3267 | // has a similar structure to the BRA opcode. | 3268 | // has a similar structure to the BRA opcode. |
| 3268 | ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported"); | 3269 | ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer flow is not supported"); |
| 3269 | 3270 | ||
| 3270 | const u32 target = offset + instr.bra.GetBranchTarget(); | 3271 | const u32 target = offset + instr.bra.GetBranchTarget(); |
| 3271 | EmitPushToSSYStack(target); | 3272 | EmitPushToFlowStack(target); |
| 3273 | break; | ||
| 3274 | } | ||
| 3275 | case OpCode::Id::PBK: { | ||
| 3276 | // PBK pushes to a stack the address where BRK will jump to. This shares stack with | ||
| 3277 | // SSY but using SYNC on a PBK address will kill the shader execution. We don't | ||
| 3278 | // emulate this because it's very unlikely a driver will emit such invalid shader. | ||
| 3279 | ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer PBK is not supported"); | ||
| 3280 | |||
| 3281 | const u32 target = offset + instr.bra.GetBranchTarget(); | ||
| 3282 | EmitPushToFlowStack(target); | ||
| 3272 | break; | 3283 | break; |
| 3273 | } | 3284 | } |
| 3274 | case OpCode::Id::SYNC: { | 3285 | case OpCode::Id::SYNC: { |
| 3275 | // The SYNC opcode jumps to the address previously set by the SSY opcode | 3286 | // The SYNC opcode jumps to the address previously set by the SSY opcode |
| 3276 | ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); | 3287 | ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); |
| 3277 | EmitPopFromSSYStack(); | 3288 | EmitPopFromFlowStack(); |
| 3289 | break; | ||
| 3290 | } | ||
| 3291 | case OpCode::Id::BRK: { | ||
| 3292 | // The BRK opcode jumps to the address previously set by the PBK opcode | ||
| 3293 | ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); | ||
| 3294 | EmitPopFromFlowStack(); | ||
| 3278 | break; | 3295 | break; |
| 3279 | } | 3296 | } |
| 3280 | case OpCode::Id::DEPBAR: { | 3297 | case OpCode::Id::DEPBAR: { |
| @@ -3428,11 +3445,11 @@ private: | |||
| 3428 | labels.insert(subroutine.begin); | 3445 | labels.insert(subroutine.begin); |
| 3429 | shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;"); | 3446 | shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;"); |
| 3430 | 3447 | ||
| 3431 | // TODO(Subv): Figure out the actual depth of the SSY stack, for now it seems | 3448 | // TODO(Subv): Figure out the actual depth of the flow stack, for now it seems |
| 3432 | // unlikely that shaders will use 20 nested SSYs. | 3449 | // unlikely that shaders will use 20 nested SSYs and PBKs. |
| 3433 | constexpr u32 SSY_STACK_SIZE = 20; | 3450 | constexpr u32 FLOW_STACK_SIZE = 20; |
| 3434 | shader.AddLine("uint ssy_stack[" + std::to_string(SSY_STACK_SIZE) + "];"); | 3451 | shader.AddLine("uint flow_stack[" + std::to_string(FLOW_STACK_SIZE) + "];"); |
| 3435 | shader.AddLine("uint ssy_stack_top = 0u;"); | 3452 | shader.AddLine("uint flow_stack_top = 0u;"); |
| 3436 | 3453 | ||
| 3437 | shader.AddLine("while (true) {"); | 3454 | shader.AddLine("while (true) {"); |
| 3438 | ++shader.scope; | 3455 | ++shader.scope; |