summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-06-24 21:25:38 -0400
committerGravatar FernandoS272019-07-09 08:14:37 -0400
commit8a6fc529a968e007f01464abadd32f9b5eb0a26c (patch)
tree189d2d4189d9e87d933eddab5260b472e6838588 /src
parentshader_ir: Remove the old scanner. (diff)
downloadyuzu-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.h16
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp9
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp9
-rw-r--r--src/video_core/shader/control_flow.cpp3
-rw-r--r--src/video_core/shader/decode/other.cpp42
-rw-r--r--src/video_core/shader/node.h1
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