diff options
| author | 2018-08-12 16:51:32 -0400 | |
|---|---|---|
| committer | 2018-08-12 18:30:24 -0400 | |
| commit | 534abf9d971824ea42e8ebd6e70369f545f8af58 (patch) | |
| tree | 3b3e604238d8f3c65c52249cd5af5e578b9f0f42 /src | |
| parent | Merge pull request #1025 from ogniK5377/bad-cast (diff) | |
| download | yuzu-534abf9d971824ea42e8ebd6e70369f545f8af58.tar.gz yuzu-534abf9d971824ea42e8ebd6e70369f545f8af58.tar.xz yuzu-534abf9d971824ea42e8ebd6e70369f545f8af58.zip | |
gl_shader_decompiler: Implement XMAD instruction.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 29 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 95 |
2 files changed, 120 insertions, 4 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 9f64b248b..2526ebf28 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -200,6 +200,14 @@ enum class IMinMaxExchange : u64 { | |||
| 200 | XHi = 3, | 200 | XHi = 3, |
| 201 | }; | 201 | }; |
| 202 | 202 | ||
| 203 | enum class XmadMode : u64 { | ||
| 204 | None = 0, | ||
| 205 | CLo = 1, | ||
| 206 | CHi = 2, | ||
| 207 | CSfu = 3, | ||
| 208 | CBcc = 4, | ||
| 209 | }; | ||
| 210 | |||
| 203 | enum class FlowCondition : u64 { | 211 | enum class FlowCondition : u64 { |
| 204 | Always = 0xF, | 212 | Always = 0xF, |
| 205 | Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for? | 213 | Fcsm_Tr = 0x1C, // TODO(bunnei): What is this used for? |
| @@ -457,6 +465,18 @@ union Instruction { | |||
| 457 | } bra; | 465 | } bra; |
| 458 | 466 | ||
| 459 | union { | 467 | union { |
| 468 | BitField<20, 16, u64> imm20_16; | ||
| 469 | BitField<36, 1, u64> product_shift_left; | ||
| 470 | BitField<37, 1, u64> merge_37; | ||
| 471 | BitField<48, 1, u64> sign_a; | ||
| 472 | BitField<49, 1, u64> sign_b; | ||
| 473 | BitField<50, 3, XmadMode> mode; | ||
| 474 | BitField<52, 1, u64> high_b; | ||
| 475 | BitField<53, 1, u64> high_a; | ||
| 476 | BitField<56, 1, u64> merge_56; | ||
| 477 | } xmad; | ||
| 478 | |||
| 479 | union { | ||
| 460 | BitField<20, 14, u64> offset; | 480 | BitField<20, 14, u64> offset; |
| 461 | BitField<34, 5, u64> index; | 481 | BitField<34, 5, u64> index; |
| 462 | } cbuf34; | 482 | } cbuf34; |
| @@ -593,6 +613,7 @@ public: | |||
| 593 | IntegerSetPredicate, | 613 | IntegerSetPredicate, |
| 594 | PredicateSetPredicate, | 614 | PredicateSetPredicate, |
| 595 | Conversion, | 615 | Conversion, |
| 616 | Xmad, | ||
| 596 | Unknown, | 617 | Unknown, |
| 597 | }; | 618 | }; |
| 598 | 619 | ||
| @@ -782,10 +803,10 @@ private: | |||
| 782 | INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"), | 803 | INST("010010110101----", Id::ISET_C, Type::IntegerSet, "ISET_C"), |
| 783 | INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"), | 804 | INST("0011011-0101----", Id::ISET_IMM, Type::IntegerSet, "ISET_IMM"), |
| 784 | INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), | 805 | INST("0101000010010---", Id::PSETP, Type::PredicateSetPredicate, "PSETP"), |
| 785 | INST("0011011-00------", Id::XMAD_IMM, Type::Arithmetic, "XMAD_IMM"), | 806 | INST("0011011-00------", Id::XMAD_IMM, Type::Xmad, "XMAD_IMM"), |
| 786 | INST("0100111---------", Id::XMAD_CR, Type::Arithmetic, "XMAD_CR"), | 807 | INST("0100111---------", Id::XMAD_CR, Type::Xmad, "XMAD_CR"), |
| 787 | INST("010100010-------", Id::XMAD_RC, Type::Arithmetic, "XMAD_RC"), | 808 | INST("010100010-------", Id::XMAD_RC, Type::Xmad, "XMAD_RC"), |
| 788 | INST("0101101100------", Id::XMAD_RR, Type::Arithmetic, "XMAD_RR"), | 809 | INST("0101101100------", Id::XMAD_RR, Type::Xmad, "XMAD_RR"), |
| 789 | }; | 810 | }; |
| 790 | #undef INST | 811 | #undef INST |
| 791 | std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) { | 812 | std::stable_sort(table.begin(), table.end(), [](const auto& a, const auto& b) { |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 7e038ac86..6834d7085 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -376,6 +376,8 @@ public: | |||
| 376 | return value; | 376 | return value; |
| 377 | } else if (type == GLSLRegister::Type::Integer) { | 377 | } else if (type == GLSLRegister::Type::Integer) { |
| 378 | return "floatBitsToInt(" + value + ')'; | 378 | return "floatBitsToInt(" + value + ')'; |
| 379 | } else if (type == GLSLRegister::Type::UnsignedInteger) { | ||
| 380 | return "floatBitsToUint(" + value + ')'; | ||
| 379 | } else { | 381 | } else { |
| 380 | UNREACHABLE(); | 382 | UNREACHABLE(); |
| 381 | } | 383 | } |
| @@ -1630,6 +1632,99 @@ private: | |||
| 1630 | } | 1632 | } |
| 1631 | break; | 1633 | break; |
| 1632 | } | 1634 | } |
| 1635 | case OpCode::Type::Xmad: { | ||
| 1636 | ASSERT_MSG(!instr.xmad.sign_a, "Unimplemented"); | ||
| 1637 | ASSERT_MSG(!instr.xmad.sign_b, "Unimplemented"); | ||
| 1638 | |||
| 1639 | std::string op_a{regs.GetRegisterAsInteger(instr.gpr8, 0, instr.xmad.sign_a)}; | ||
| 1640 | std::string op_b; | ||
| 1641 | std::string op_c; | ||
| 1642 | |||
| 1643 | // TODO(bunnei): Needs to be fixed once op_a or op_b is signed | ||
| 1644 | ASSERT_MSG(instr.xmad.sign_a == instr.xmad.sign_b, "Unimplemented"); | ||
| 1645 | const bool is_signed{instr.xmad.sign_a == 1}; | ||
| 1646 | |||
| 1647 | bool is_merge{}; | ||
| 1648 | switch (opcode->GetId()) { | ||
| 1649 | case OpCode::Id::XMAD_CR: { | ||
| 1650 | is_merge = instr.xmad.merge_56; | ||
| 1651 | op_b += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, | ||
| 1652 | instr.xmad.sign_b ? GLSLRegister::Type::Integer | ||
| 1653 | : GLSLRegister::Type::UnsignedInteger); | ||
| 1654 | op_c += regs.GetRegisterAsInteger(instr.gpr39, 0, is_signed); | ||
| 1655 | break; | ||
| 1656 | } | ||
| 1657 | case OpCode::Id::XMAD_RR: { | ||
| 1658 | is_merge = instr.xmad.merge_37; | ||
| 1659 | op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.xmad.sign_b); | ||
| 1660 | op_c += regs.GetRegisterAsInteger(instr.gpr39, 0, is_signed); | ||
| 1661 | break; | ||
| 1662 | } | ||
| 1663 | case OpCode::Id::XMAD_RC: { | ||
| 1664 | op_b += regs.GetRegisterAsInteger(instr.gpr39, 0, instr.xmad.sign_b); | ||
| 1665 | op_c += regs.GetUniform(instr.cbuf34.index, instr.cbuf34.offset, | ||
| 1666 | is_signed ? GLSLRegister::Type::Integer | ||
| 1667 | : GLSLRegister::Type::UnsignedInteger); | ||
| 1668 | break; | ||
| 1669 | } | ||
| 1670 | case OpCode::Id::XMAD_IMM: { | ||
| 1671 | is_merge = instr.xmad.merge_37; | ||
| 1672 | op_b += std::to_string(instr.xmad.imm20_16); | ||
| 1673 | op_c += regs.GetRegisterAsInteger(instr.gpr39, 0, is_signed); | ||
| 1674 | break; | ||
| 1675 | } | ||
| 1676 | default: { | ||
| 1677 | LOG_CRITICAL(HW_GPU, "Unhandled XMAD instruction: {}", opcode->GetName()); | ||
| 1678 | UNREACHABLE(); | ||
| 1679 | } | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | // TODO(bunnei): Ensure this is right with signed operands | ||
| 1683 | if (instr.xmad.high_a) { | ||
| 1684 | op_a = "((" + op_a + ") >> 16)"; | ||
| 1685 | } else { | ||
| 1686 | op_a = "((" + op_a + ") & 0xFFFF)"; | ||
| 1687 | } | ||
| 1688 | |||
| 1689 | std::string src2 = '(' + op_b + ')'; // Preserve original source 2 | ||
| 1690 | if (instr.xmad.high_b) { | ||
| 1691 | op_b = '(' + src2 + " >> 16)"; | ||
| 1692 | } else { | ||
| 1693 | op_b = '(' + src2 + " & 0xFFFF)"; | ||
| 1694 | } | ||
| 1695 | |||
| 1696 | std::string product = '(' + op_a + " * " + op_b + ')'; | ||
| 1697 | if (instr.xmad.product_shift_left) { | ||
| 1698 | product = '(' + product + " << 16)"; | ||
| 1699 | } | ||
| 1700 | |||
| 1701 | switch (instr.xmad.mode) { | ||
| 1702 | case Tegra::Shader::XmadMode::None: | ||
| 1703 | break; | ||
| 1704 | case Tegra::Shader::XmadMode::CLo: | ||
| 1705 | op_c = "((" + op_c + ") & 0xFFFF)"; | ||
| 1706 | break; | ||
| 1707 | case Tegra::Shader::XmadMode::CHi: | ||
| 1708 | op_c = "((" + op_c + ") >> 16)"; | ||
| 1709 | break; | ||
| 1710 | case Tegra::Shader::XmadMode::CBcc: | ||
| 1711 | op_c = "((" + op_c + ") + (" + src2 + "<< 16))"; | ||
| 1712 | break; | ||
| 1713 | default: { | ||
| 1714 | LOG_CRITICAL(HW_GPU, "Unhandled XMAD mode: {}", | ||
| 1715 | static_cast<u32>(instr.xmad.mode.Value())); | ||
| 1716 | UNREACHABLE(); | ||
| 1717 | } | ||
| 1718 | } | ||
| 1719 | |||
| 1720 | std::string sum{'(' + product + " + " + op_c + ')'}; | ||
| 1721 | if (is_merge) { | ||
| 1722 | sum = "((" + sum + " & 0xFFFF) | (" + src2 + "<< 16))"; | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | regs.SetRegisterToInteger(instr.gpr0, is_signed, 0, sum, 1, 1); | ||
| 1726 | break; | ||
| 1727 | } | ||
| 1633 | default: { | 1728 | default: { |
| 1634 | switch (opcode->GetId()) { | 1729 | switch (opcode->GetId()) { |
| 1635 | case OpCode::Id::EXIT: { | 1730 | case OpCode::Id::EXIT: { |