diff options
Diffstat (limited to 'src/video_core')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 43 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 72 |
2 files changed, 112 insertions, 3 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index b0da805db..fb639a417 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -109,6 +109,8 @@ union OpCode { | |||
| 109 | 109 | ||
| 110 | FSETP_R = 0x5BB, | 110 | FSETP_R = 0x5BB, |
| 111 | FSETP_C = 0x4BB, | 111 | FSETP_C = 0x4BB, |
| 112 | FSETP_IMM = 0x36B, | ||
| 113 | FSETP_NEG_IMM = 0x37B, | ||
| 112 | EXIT = 0xE30, | 114 | EXIT = 0xE30, |
| 113 | KIL = 0xE33, | 115 | KIL = 0xE33, |
| 114 | 116 | ||
| @@ -124,6 +126,7 @@ union OpCode { | |||
| 124 | Ffma, | 126 | Ffma, |
| 125 | Flow, | 127 | Flow, |
| 126 | Memory, | 128 | Memory, |
| 129 | FloatPredicate, | ||
| 127 | Unknown, | 130 | Unknown, |
| 128 | }; | 131 | }; |
| 129 | 132 | ||
| @@ -164,6 +167,9 @@ union OpCode { | |||
| 164 | case Id::FSETP_C: | 167 | case Id::FSETP_C: |
| 165 | case Id::KIL: | 168 | case Id::KIL: |
| 166 | return op4; | 169 | return op4; |
| 170 | case Id::FSETP_IMM: | ||
| 171 | case Id::FSETP_NEG_IMM: | ||
| 172 | return Id::FSETP_IMM; | ||
| 167 | } | 173 | } |
| 168 | 174 | ||
| 169 | switch (op5) { | 175 | switch (op5) { |
| @@ -241,8 +247,9 @@ union OpCode { | |||
| 241 | info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"}; | 247 | info_table[Id::FMUL_C] = {Type::Arithmetic, "fmul_c"}; |
| 242 | info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"}; | 248 | info_table[Id::FMUL_IMM] = {Type::Arithmetic, "fmul_imm"}; |
| 243 | info_table[Id::FMUL32_IMM] = {Type::Arithmetic, "fmul32_imm"}; | 249 | info_table[Id::FMUL32_IMM] = {Type::Arithmetic, "fmul32_imm"}; |
| 244 | info_table[Id::FSETP_C] = {Type::Arithmetic, "fsetp_c"}; | 250 | info_table[Id::FSETP_C] = {Type::FloatPredicate, "fsetp_c"}; |
| 245 | info_table[Id::FSETP_R] = {Type::Arithmetic, "fsetp_r"}; | 251 | info_table[Id::FSETP_R] = {Type::FloatPredicate, "fsetp_r"}; |
| 252 | info_table[Id::FSETP_IMM] = {Type::FloatPredicate, "fsetp_imm"}; | ||
| 246 | info_table[Id::EXIT] = {Type::Trivial, "exit"}; | 253 | info_table[Id::EXIT] = {Type::Trivial, "exit"}; |
| 247 | info_table[Id::IPA] = {Type::Trivial, "ipa"}; | 254 | info_table[Id::IPA] = {Type::Trivial, "ipa"}; |
| 248 | info_table[Id::KIL] = {Type::Flow, "kil"}; | 255 | info_table[Id::KIL] = {Type::Flow, "kil"}; |
| @@ -286,7 +293,23 @@ namespace Shader { | |||
| 286 | 293 | ||
| 287 | enum class Pred : u64 { | 294 | enum class Pred : u64 { |
| 288 | UnusedIndex = 0x7, | 295 | UnusedIndex = 0x7, |
| 289 | NeverExecute = 0xf, | 296 | NeverExecute = 0xF, |
| 297 | }; | ||
| 298 | |||
| 299 | enum class PredCondition : u64 { | ||
| 300 | LessThan = 1, | ||
| 301 | Equal = 2, | ||
| 302 | LessEqual = 3, | ||
| 303 | GreaterThan = 4, | ||
| 304 | NotEqual = 5, | ||
| 305 | GreaterEqual = 6, | ||
| 306 | // TODO(Subv): Other condition types | ||
| 307 | }; | ||
| 308 | |||
| 309 | enum class PredOperation : u64 { | ||
| 310 | And = 0, | ||
| 311 | Or = 1, | ||
| 312 | Xor = 2, | ||
| 290 | }; | 313 | }; |
| 291 | 314 | ||
| 292 | enum class SubOp : u64 { | 315 | enum class SubOp : u64 { |
| @@ -346,6 +369,20 @@ union Instruction { | |||
| 346 | BitField<49, 1, u64> negate_c; | 369 | BitField<49, 1, u64> negate_c; |
| 347 | } ffma; | 370 | } ffma; |
| 348 | 371 | ||
| 372 | union { | ||
| 373 | BitField<0, 3, u64> pred0; | ||
| 374 | BitField<3, 3, u64> pred3; | ||
| 375 | BitField<7, 1, u64> abs_a; | ||
| 376 | BitField<39, 3, u64> pred39; | ||
| 377 | BitField<42, 1, u64> neg_pred; | ||
| 378 | BitField<43, 1, u64> neg_a; | ||
| 379 | BitField<44, 1, u64> abs_b; | ||
| 380 | BitField<45, 2, PredOperation> op; | ||
| 381 | BitField<47, 1, u64> ftz; | ||
| 382 | BitField<48, 4, PredCondition> cond; | ||
| 383 | BitField<56, 1, u64> neg_b; | ||
| 384 | } fsetp; | ||
| 385 | |||
| 349 | BitField<61, 1, u64> is_b_imm; | 386 | BitField<61, 1, u64> is_b_imm; |
| 350 | BitField<60, 1, u64> is_b_gpr; | 387 | BitField<60, 1, u64> is_b_gpr; |
| 351 | BitField<59, 1, u64> is_c_gpr; | 388 | BitField<59, 1, u64> is_c_gpr; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 6db0b7d39..2e0203a68 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -279,6 +279,21 @@ private: | |||
| 279 | } | 279 | } |
| 280 | 280 | ||
| 281 | /* | 281 | /* |
| 282 | * Writes code that assigns a predicate boolean variable. | ||
| 283 | * @param pred The id of the predicate to write to. | ||
| 284 | * @param value The expression value to assign to the predicate. | ||
| 285 | */ | ||
| 286 | void SetPredicate(u64 pred, const std::string& value) { | ||
| 287 | using Tegra::Shader::Pred; | ||
| 288 | // Can't assign to the constant predicate. | ||
| 289 | ASSERT(pred != static_cast<u64>(Pred::UnusedIndex)); | ||
| 290 | |||
| 291 | std::string variable = 'p' + std::to_string(pred); | ||
| 292 | shader.AddLine(variable + " = " + value + ';'); | ||
| 293 | declr_predicates.insert(std::move(variable)); | ||
| 294 | } | ||
| 295 | |||
| 296 | /* | ||
| 282 | * Returns whether the instruction at the specified offset is a 'sched' instruction. | 297 | * Returns whether the instruction at the specified offset is a 'sched' instruction. |
| 283 | * Sched instructions always appear before a sequence of 3 instructions. | 298 | * Sched instructions always appear before a sequence of 3 instructions. |
| 284 | */ | 299 | */ |
| @@ -468,7 +483,57 @@ private: | |||
| 468 | } | 483 | } |
| 469 | break; | 484 | break; |
| 470 | } | 485 | } |
| 486 | case OpCode::Type::FloatPredicate: { | ||
| 487 | std::string op_a = instr.fsetp.neg_a ? "-" : ""; | ||
| 488 | op_a += GetRegister(instr.gpr8); | ||
| 489 | |||
| 490 | if (instr.fsetp.abs_a) { | ||
| 491 | op_a = "abs(" + op_a + ')'; | ||
| 492 | } | ||
| 493 | |||
| 494 | std::string op_b{}; | ||
| 495 | |||
| 496 | if (instr.is_b_imm) { | ||
| 497 | if (instr.fsetp.neg_b) { | ||
| 498 | // Only the immediate version of fsetp has a neg_b bit. | ||
| 499 | op_b += '-'; | ||
| 500 | } | ||
| 501 | op_b += '(' + GetImmediate19(instr) + ')'; | ||
| 502 | } else { | ||
| 503 | if (instr.is_b_gpr) { | ||
| 504 | op_b += GetRegister(instr.gpr20); | ||
| 505 | } else { | ||
| 506 | op_b += GetUniform(instr.uniform); | ||
| 507 | } | ||
| 508 | } | ||
| 509 | |||
| 510 | if (instr.fsetp.abs_b) { | ||
| 511 | op_b = "abs(" + op_b + ')'; | ||
| 512 | } | ||
| 471 | 513 | ||
| 514 | using Tegra::Shader::Pred; | ||
| 515 | ASSERT_MSG(instr.fsetp.pred0 == static_cast<u64>(Pred::UnusedIndex) && | ||
| 516 | instr.fsetp.pred39 == static_cast<u64>(Pred::UnusedIndex), | ||
| 517 | "Compound predicates are not implemented"); | ||
| 518 | |||
| 519 | // We can't use the constant predicate as destination. | ||
| 520 | ASSERT(instr.fsetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); | ||
| 521 | |||
| 522 | using Tegra::Shader::PredCondition; | ||
| 523 | switch (instr.fsetp.cond) { | ||
| 524 | case PredCondition::LessThan: | ||
| 525 | SetPredicate(instr.fsetp.pred3, '(' + op_a + ") < (" + op_b + ')'); | ||
| 526 | break; | ||
| 527 | case PredCondition::Equal: | ||
| 528 | SetPredicate(instr.fsetp.pred3, '(' + op_a + ") == (" + op_b + ')'); | ||
| 529 | break; | ||
| 530 | default: | ||
| 531 | NGLOG_CRITICAL(HW_GPU, "Unhandled predicate condition: {} (a: {}, b: {})", | ||
| 532 | static_cast<unsigned>(instr.fsetp.cond.Value()), op_a, op_b); | ||
| 533 | UNREACHABLE(); | ||
| 534 | } | ||
| 535 | break; | ||
| 536 | } | ||
| 472 | default: { | 537 | default: { |
| 473 | switch (instr.opcode.EffectiveOpCode()) { | 538 | switch (instr.opcode.EffectiveOpCode()) { |
| 474 | case OpCode::Id::EXIT: { | 539 | case OpCode::Id::EXIT: { |
| @@ -623,6 +688,12 @@ private: | |||
| 623 | declarations.AddNewLine(); | 688 | declarations.AddNewLine(); |
| 624 | ++const_buffer_layout; | 689 | ++const_buffer_layout; |
| 625 | } | 690 | } |
| 691 | |||
| 692 | declarations.AddNewLine(); | ||
| 693 | for (const auto& pred : declr_predicates) { | ||
| 694 | declarations.AddLine("bool " + pred + " = false;"); | ||
| 695 | } | ||
| 696 | declarations.AddNewLine(); | ||
| 626 | } | 697 | } |
| 627 | 698 | ||
| 628 | private: | 699 | private: |
| @@ -636,6 +707,7 @@ private: | |||
| 636 | 707 | ||
| 637 | // Declarations | 708 | // Declarations |
| 638 | std::set<std::string> declr_register; | 709 | std::set<std::string> declr_register; |
| 710 | std::set<std::string> declr_predicates; | ||
| 639 | std::set<Attribute::Index> declr_input_attribute; | 711 | std::set<Attribute::Index> declr_input_attribute; |
| 640 | std::set<Attribute::Index> declr_output_attribute; | 712 | std::set<Attribute::Index> declr_output_attribute; |
| 641 | std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers; | 713 | std::array<ConstBufferEntry, Maxwell3D::Regs::MaxConstBuffers> declr_const_buffers; |