diff options
| author | 2019-06-24 21:25:38 -0400 | |
|---|---|---|
| committer | 2019-07-09 08:14:37 -0400 | |
| commit | 8a6fc529a968e007f01464abadd32f9b5eb0a26c (patch) | |
| tree | 189d2d4189d9e87d933eddab5260b472e6838588 /src | |
| parent | shader_ir: Remove the old scanner. (diff) | |
| download | yuzu-8a6fc529a968e007f01464abadd32f9b5eb0a26c.tar.gz yuzu-8a6fc529a968e007f01464abadd32f9b5eb0a26c.tar.xz yuzu-8a6fc529a968e007f01464abadd32f9b5eb0a26c.zip | |
shader_ir: Implement BRX & BRA.CC
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 16 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 9 | ||||
| -rw-r--r-- | src/video_core/shader/control_flow.cpp | 3 | ||||
| -rw-r--r-- | src/video_core/shader/decode/other.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/shader/node.h | 1 |
6 files changed, 76 insertions, 4 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 404d4f5aa..c3055602b 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -1368,6 +1368,20 @@ union Instruction { | |||
| 1368 | } bra; | 1368 | } bra; |
| 1369 | 1369 | ||
| 1370 | union { | 1370 | union { |
| 1371 | BitField<20, 24, u64> target; | ||
| 1372 | BitField<5, 1, u64> constant_buffer; | ||
| 1373 | |||
| 1374 | s32 GetBranchExtend() const { | ||
| 1375 | // Sign extend the branch target offset | ||
| 1376 | u32 mask = 1U << (24 - 1); | ||
| 1377 | u32 value = static_cast<u32>(target); | ||
| 1378 | // The branch offset is relative to the next instruction and is stored in bytes, so | ||
| 1379 | // divide it by the size of an instruction and add 1 to it. | ||
| 1380 | return static_cast<s32>((value ^ mask) - mask) / sizeof(Instruction) + 1; | ||
| 1381 | } | ||
| 1382 | } brx; | ||
| 1383 | |||
| 1384 | union { | ||
| 1371 | BitField<39, 1, u64> emit; // EmitVertex | 1385 | BitField<39, 1, u64> emit; // EmitVertex |
| 1372 | BitField<40, 1, u64> cut; // EndPrimitive | 1386 | BitField<40, 1, u64> cut; // EndPrimitive |
| 1373 | } out; | 1387 | } out; |
| @@ -1464,6 +1478,7 @@ public: | |||
| 1464 | BFE_IMM, | 1478 | BFE_IMM, |
| 1465 | BFI_IMM_R, | 1479 | BFI_IMM_R, |
| 1466 | BRA, | 1480 | BRA, |
| 1481 | BRX, | ||
| 1467 | PBK, | 1482 | PBK, |
| 1468 | LD_A, | 1483 | LD_A, |
| 1469 | LD_L, | 1484 | LD_L, |
| @@ -1738,6 +1753,7 @@ private: | |||
| 1738 | INST("111000101001----", Id::SSY, Type::Flow, "SSY"), | 1753 | INST("111000101001----", Id::SSY, Type::Flow, "SSY"), |
| 1739 | INST("111000101010----", Id::PBK, Type::Flow, "PBK"), | 1754 | INST("111000101010----", Id::PBK, Type::Flow, "PBK"), |
| 1740 | INST("111000100100----", Id::BRA, Type::Flow, "BRA"), | 1755 | INST("111000100100----", Id::BRA, Type::Flow, "BRA"), |
| 1756 | INST("111000100101----", Id::BRX, Type::Flow, "BRX"), | ||
| 1741 | INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"), | 1757 | INST("1111000011111---", Id::SYNC, Type::Flow, "SYNC"), |
| 1742 | INST("111000110100---", Id::BRK, Type::Flow, "BRK"), | 1758 | INST("111000110100---", Id::BRK, Type::Flow, "BRK"), |
| 1743 | INST("111000110000----", Id::EXIT, Type::Flow, "EXIT"), | 1759 | INST("111000110000----", Id::EXIT, Type::Flow, "EXIT"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 5f2f1510c..cedfe30b1 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -1555,6 +1555,14 @@ private: | |||
| 1555 | return {}; | 1555 | return {}; |
| 1556 | } | 1556 | } |
| 1557 | 1557 | ||
| 1558 | std::string BranchIndirect(Operation operation) { | ||
| 1559 | const std::string op_a = VisitOperand(operation, 0, Type::Uint); | ||
| 1560 | |||
| 1561 | code.AddLine("jmp_to = {};", op_a); | ||
| 1562 | code.AddLine("break;"); | ||
| 1563 | return {}; | ||
| 1564 | } | ||
| 1565 | |||
| 1558 | std::string PushFlowStack(Operation operation) { | 1566 | std::string PushFlowStack(Operation operation) { |
| 1559 | const auto stack = std::get<MetaStackClass>(operation.GetMeta()); | 1567 | const auto stack = std::get<MetaStackClass>(operation.GetMeta()); |
| 1560 | const auto target = std::get_if<ImmediateNode>(&*operation[0]); | 1568 | const auto target = std::get_if<ImmediateNode>(&*operation[0]); |
| @@ -1789,6 +1797,7 @@ private: | |||
| 1789 | &GLSLDecompiler::ImageStore, | 1797 | &GLSLDecompiler::ImageStore, |
| 1790 | 1798 | ||
| 1791 | &GLSLDecompiler::Branch, | 1799 | &GLSLDecompiler::Branch, |
| 1800 | &GLSLDecompiler::BranchIndirect, | ||
| 1792 | &GLSLDecompiler::PushFlowStack, | 1801 | &GLSLDecompiler::PushFlowStack, |
| 1793 | &GLSLDecompiler::PopFlowStack, | 1802 | &GLSLDecompiler::PopFlowStack, |
| 1794 | &GLSLDecompiler::Exit, | 1803 | &GLSLDecompiler::Exit, |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 97ce214b1..1bb04607b 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -949,6 +949,14 @@ private: | |||
| 949 | return {}; | 949 | return {}; |
| 950 | } | 950 | } |
| 951 | 951 | ||
| 952 | Id BranchIndirect(Operation operation) { | ||
| 953 | const Id op_a = VisitOperand<Type::Uint>(operation, 0); | ||
| 954 | |||
| 955 | Emit(OpStore(jmp_to, op_a)); | ||
| 956 | BranchingOp([&]() { Emit(OpBranch(continue_label)); }); | ||
| 957 | return {}; | ||
| 958 | } | ||
| 959 | |||
| 952 | Id PushFlowStack(Operation operation) { | 960 | Id PushFlowStack(Operation operation) { |
| 953 | const auto target = std::get_if<ImmediateNode>(&*operation[0]); | 961 | const auto target = std::get_if<ImmediateNode>(&*operation[0]); |
| 954 | ASSERT(target); | 962 | ASSERT(target); |
| @@ -1334,6 +1342,7 @@ private: | |||
| 1334 | &SPIRVDecompiler::ImageStore, | 1342 | &SPIRVDecompiler::ImageStore, |
| 1335 | 1343 | ||
| 1336 | &SPIRVDecompiler::Branch, | 1344 | &SPIRVDecompiler::Branch, |
| 1345 | &SPIRVDecompiler::BranchIndirect, | ||
| 1337 | &SPIRVDecompiler::PushFlowStack, | 1346 | &SPIRVDecompiler::PushFlowStack, |
| 1338 | &SPIRVDecompiler::PopFlowStack, | 1347 | &SPIRVDecompiler::PopFlowStack, |
| 1339 | &SPIRVDecompiler::Exit, | 1348 | &SPIRVDecompiler::Exit, |
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp index fcf22c7f2..a9de8f814 100644 --- a/src/video_core/shader/control_flow.cpp +++ b/src/video_core/shader/control_flow.cpp | |||
| @@ -284,6 +284,9 @@ ParseResult ParseCode(CFGRebuildState& state, u32 address, ParseInfo& parse_info | |||
| 284 | state.pbk_labels.emplace(offset, target); | 284 | state.pbk_labels.emplace(offset, target); |
| 285 | break; | 285 | break; |
| 286 | } | 286 | } |
| 287 | case OpCode::Id::BRX: { | ||
| 288 | return ParseResult::AbnormalFlow; | ||
| 289 | } | ||
| 287 | default: | 290 | default: |
| 288 | break; | 291 | break; |
| 289 | } | 292 | } |
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp index d46a8ab82..ed3c63781 100644 --- a/src/video_core/shader/decode/other.cpp +++ b/src/video_core/shader/decode/other.cpp | |||
| @@ -91,11 +91,45 @@ u32 ShaderIR::DecodeOther(NodeBlock& bb, u32 pc) { | |||
| 91 | break; | 91 | break; |
| 92 | } | 92 | } |
| 93 | case OpCode::Id::BRA: { | 93 | case OpCode::Id::BRA: { |
| 94 | UNIMPLEMENTED_IF_MSG(instr.bra.constant_buffer != 0, | 94 | Node branch; |
| 95 | "BRA with constant buffers are not implemented"); | 95 | if (instr.bra.constant_buffer == 0) { |
| 96 | const u32 target = pc + instr.bra.GetBranchTarget(); | ||
| 97 | branch = Operation(OperationCode::Branch, Immediate(target)); | ||
| 98 | } else { | ||
| 99 | const u32 target = pc + 1; | ||
| 100 | const Node op_a = GetConstBuffer(instr.cbuf36.index, instr.cbuf36.GetOffset()); | ||
| 101 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, | ||
| 102 | true, PRECISE, op_a, Immediate(3)); | ||
| 103 | const Node operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 104 | branch = Operation(OperationCode::BranchIndirect, convert); | ||
| 105 | } | ||
| 96 | 106 | ||
| 97 | const u32 target = pc + instr.bra.GetBranchTarget(); | 107 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 98 | const Node branch = Operation(OperationCode::Branch, Immediate(target)); | 108 | if (cc != Tegra::Shader::ConditionCode::T) { |
| 109 | bb.push_back(Conditional(GetConditionCode(cc), {branch})); | ||
| 110 | } else { | ||
| 111 | bb.push_back(branch); | ||
| 112 | } | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | case OpCode::Id::BRX: { | ||
| 116 | Node operand; | ||
| 117 | if (instr.brx.constant_buffer != 0) { | ||
| 118 | const s32 target = pc + 1; | ||
| 119 | const Node index = GetRegister(instr.gpr8); | ||
| 120 | const Node op_a = | ||
| 121 | GetConstBufferIndirect(instr.cbuf36.index, instr.cbuf36.GetOffset() + 0, index); | ||
| 122 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, | ||
| 123 | true, PRECISE, op_a, Immediate(3)); | ||
| 124 | operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 125 | } else { | ||
| 126 | const s32 target = pc + instr.brx.GetBranchExtend(); | ||
| 127 | const Node op_a = GetRegister(instr.gpr8); | ||
| 128 | const Node convert = SignedOperation(OperationCode::IArithmeticShiftRight, | ||
| 129 | true, PRECISE, op_a, Immediate(3)); | ||
| 130 | operand = Operation(OperationCode::IAdd, PRECISE, convert, Immediate(target)); | ||
| 131 | } | ||
| 132 | const Node branch = Operation(OperationCode::BranchIndirect, operand); | ||
| 99 | 133 | ||
| 100 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; | 134 | const Tegra::Shader::ConditionCode cc = instr.flow_condition_code; |
| 101 | if (cc != Tegra::Shader::ConditionCode::T) { | 135 | if (cc != Tegra::Shader::ConditionCode::T) { |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index 0ac83fcf0..e468758a6 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -149,6 +149,7 @@ enum class OperationCode { | |||
| 149 | ImageStore, /// (MetaImage, float[N] coords) -> void | 149 | ImageStore, /// (MetaImage, float[N] coords) -> void |
| 150 | 150 | ||
| 151 | Branch, /// (uint branch_target) -> void | 151 | Branch, /// (uint branch_target) -> void |
| 152 | BranchIndirect,/// (uint branch_target) -> void | ||
| 152 | PushFlowStack, /// (uint branch_target) -> void | 153 | PushFlowStack, /// (uint branch_target) -> void |
| 153 | PopFlowStack, /// () -> void | 154 | PopFlowStack, /// () -> void |
| 154 | Exit, /// () -> void | 155 | Exit, /// () -> void |