summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-09-23 11:15:09 -0400
committerGravatar FernandoS272019-10-25 09:01:29 -0400
commit2ef696c85a37917102a9f869775180ab225f0d56 (patch)
tree43f4cfa0571a910c80416bdb23f0b4099a609d14 /src
parentMerge pull request #3029 from jroweboy/revert (diff)
downloadyuzu-2ef696c85a37917102a9f869775180ab225f0d56.tar.gz
yuzu-2ef696c85a37917102a9f869775180ab225f0d56.tar.xz
yuzu-2ef696c85a37917102a9f869775180ab225f0d56.zip
Shader_IR: Implement BRX tracking.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/shader/control_flow.cpp113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index 9d21f45de..70f758642 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -124,6 +124,111 @@ enum class ParseResult : u32 {
124 AbnormalFlow, 124 AbnormalFlow,
125}; 125};
126 126
127struct BranchIndirectInfo {
128 u32 buffer{};
129 u32 offset{};
130 u32 entries{};
131 s32 relative_position{};
132};
133
134std::optional<BranchIndirectInfo> TrackBranchIndirectInfo(const CFGRebuildState& state,
135 u32 start_address, u32 current_position) {
136 const u32 shader_start = state.start;
137 u32 pos = current_position;
138 BranchIndirectInfo result{};
139 u64 track_register = 0;
140
141 // Step 0 Get BRX Info
142 const Instruction instr = {state.program_code[pos]};
143 const auto opcode = OpCode::Decode(instr);
144 if (opcode->get().GetId() != OpCode::Id::BRX) {
145 return {};
146 }
147 if (instr.brx.constant_buffer != 0) {
148 return {};
149 }
150 track_register = instr.gpr8.Value();
151 result.relative_position = instr.brx.GetBranchExtend();
152 pos--;
153 bool found_track = false;
154
155 // Step 1 Track LDC
156 while (pos >= shader_start) {
157 if (IsSchedInstruction(pos, shader_start)) {
158 pos--;
159 continue;
160 }
161 const Instruction instr = {state.program_code[pos]};
162 const auto opcode = OpCode::Decode(instr);
163 if (opcode->get().GetId() == OpCode::Id::LD_C) {
164 if (instr.gpr0.Value() == track_register &&
165 instr.ld_c.type.Value() == Tegra::Shader::UniformType::Single) {
166 result.buffer = instr.cbuf36.index;
167 result.offset = instr.cbuf36.GetOffset();
168 track_register = instr.gpr8.Value();
169 pos--;
170 found_track = true;
171 break;
172 }
173 }
174 pos--;
175 }
176
177 if (!found_track) {
178 return {};
179 }
180 found_track = false;
181
182 // Step 2 Track SHL
183 while (pos >= shader_start) {
184 if (IsSchedInstruction(pos, shader_start)) {
185 pos--;
186 continue;
187 }
188 const Instruction instr = {state.program_code[pos]};
189 const auto opcode = OpCode::Decode(instr);
190 if (opcode->get().GetId() == OpCode::Id::SHL_IMM) {
191 if (instr.gpr0.Value() == track_register) {
192 track_register = instr.gpr8.Value();
193 pos--;
194 found_track = true;
195 break;
196 }
197 }
198 pos--;
199 }
200
201 if (!found_track) {
202 return {};
203 }
204 found_track = false;
205
206 // Step 3 Track IMNMX
207 while (pos >= shader_start) {
208 if (IsSchedInstruction(pos, shader_start)) {
209 pos--;
210 continue;
211 }
212 const Instruction instr = {state.program_code[pos]};
213 const auto opcode = OpCode::Decode(instr);
214 if (opcode->get().GetId() == OpCode::Id::IMNMX_IMM) {
215 if (instr.gpr0.Value() == track_register) {
216 track_register = instr.gpr8.Value();
217 result.entries = instr.alu.GetSignedImm20_20();
218 pos--;
219 found_track = true;
220 break;
221 }
222 }
223 pos--;
224 }
225
226 if (!found_track) {
227 return {};
228 }
229 return {result};
230}
231
127std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { 232std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) {
128 u32 offset = static_cast<u32>(address); 233 u32 offset = static_cast<u32>(address);
129 const u32 end_address = static_cast<u32>(state.program_size / sizeof(Instruction)); 234 const u32 end_address = static_cast<u32>(state.program_size / sizeof(Instruction));
@@ -298,6 +403,14 @@ std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address)
298 break; 403 break;
299 } 404 }
300 case OpCode::Id::BRX: { 405 case OpCode::Id::BRX: {
406 auto tmp = TrackBranchIndirectInfo(state, address, offset);
407 if (tmp) {
408 auto result = *tmp;
409 LOG_CRITICAL(HW_GPU, "Track Successful, BRX: buffer:{}, offset:{}, entries:{}",
410 result.buffer, result.offset, result.entries);
411 } else {
412 LOG_CRITICAL(HW_GPU, "Track Unsuccesful");
413 }
301 return {ParseResult::AbnormalFlow, parse_info}; 414 return {ParseResult::AbnormalFlow, parse_info};
302 } 415 }
303 default: 416 default: