diff options
| author | 2019-09-23 11:15:09 -0400 | |
|---|---|---|
| committer | 2019-10-25 09:01:29 -0400 | |
| commit | 2ef696c85a37917102a9f869775180ab225f0d56 (patch) | |
| tree | 43f4cfa0571a910c80416bdb23f0b4099a609d14 /src | |
| parent | Merge pull request #3029 from jroweboy/revert (diff) | |
| download | yuzu-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.cpp | 113 |
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 | ||
| 127 | struct BranchIndirectInfo { | ||
| 128 | u32 buffer{}; | ||
| 129 | u32 offset{}; | ||
| 130 | u32 entries{}; | ||
| 131 | s32 relative_position{}; | ||
| 132 | }; | ||
| 133 | |||
| 134 | std::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 | |||
| 127 | std::pair<ParseResult, ParseInfo> ParseCode(CFGRebuildState& state, u32 address) { | 232 | std::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: |