summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2019-06-26 12:19:43 -0400
committerGravatar FernandoS272019-07-09 08:14:41 -0400
commit34357b110c3f04f6b98ca586fd776b0df569b6d8 (patch)
tree28070463fed57a8a5055d616399df4a6d06b16f5
parentshader_ir: Correct max sizing (diff)
downloadyuzu-34357b110c3f04f6b98ca586fd776b0df569b6d8.tar.gz
yuzu-34357b110c3f04f6b98ca586fd776b0df569b6d8.tar.xz
yuzu-34357b110c3f04f6b98ca586fd776b0df569b6d8.zip
shader_ir: Correct parsing of scheduling instructions and correct sizing
-rw-r--r--src/video_core/shader/control_flow.cpp41
-rw-r--r--src/video_core/shader/decode.cpp2
2 files changed, 30 insertions, 13 deletions
diff --git a/src/video_core/shader/control_flow.cpp b/src/video_core/shader/control_flow.cpp
index a26de6795..1775dfd81 100644
--- a/src/video_core/shader/control_flow.cpp
+++ b/src/video_core/shader/control_flow.cpp
@@ -20,10 +20,10 @@ using Tegra::Shader::OpCode;
20 20
21constexpr s32 unassigned_branch = -2; 21constexpr s32 unassigned_branch = -2;
22 22
23/*** 23/**
24 * 'ControlStack' represents a static stack of control jumps such as SSY and PBK 24 * 'ControlStack' represents a static stack of control jumps such as SSY and PBK
25 * stacks in Maxwell. 25 * stacks in Maxwell.
26 ***/ 26 **/
27struct ControlStack { 27struct ControlStack {
28 static constexpr std::size_t stack_fixed_size = 20; 28 static constexpr std::size_t stack_fixed_size = 20;
29 std::array<u32, stack_fixed_size> stack{}; 29 std::array<u32, stack_fixed_size> stack{};
@@ -105,9 +105,11 @@ struct BlockInfo {
105}; 105};
106 106
107struct CFGRebuildState { 107struct CFGRebuildState {
108 explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size) 108 explicit CFGRebuildState(const ProgramCode& program_code, const std::size_t program_size,
109 : program_code{program_code}, program_size{program_size} {} 109 const u32 start)
110 : program_code{program_code}, program_size{program_size}, start{start} {}
110 111
112 u32 start{};
111 std::vector<BlockInfo> block_info{}; 113 std::vector<BlockInfo> block_info{};
112 std::list<u32> inspect_queries{}; 114 std::list<u32> inspect_queries{};
113 std::list<Query> queries{}; 115 std::list<Query> queries{};
@@ -120,7 +122,7 @@ struct CFGRebuildState {
120 const std::size_t program_size; 122 const std::size_t program_size;
121}; 123};
122 124
123enum class BlockCollision : u32 { None = 0, Found = 1, Inside = 2 }; 125enum class BlockCollision : u32 { None, Found, Inside };
124 126
125std::pair<BlockCollision, std::vector<BlockInfo>::iterator> TryGetBlock(CFGRebuildState& state, 127std::pair<BlockCollision, std::vector<BlockInfo>::iterator> TryGetBlock(CFGRebuildState& state,
126 u32 address) { 128 u32 address) {
@@ -155,15 +157,26 @@ Pred GetPredicate(u32 index, bool negated) {
155 return static_cast<Pred>(index + (negated ? 8 : 0)); 157 return static_cast<Pred>(index + (negated ? 8 : 0));
156} 158}
157 159
160/**
161 * Returns whether the instruction at the specified offset is a 'sched' instruction.
162 * Sched instructions always appear before a sequence of 3 instructions.
163 */
164constexpr bool IsSchedInstruction(u32 offset, u32 main_offset) {
165 constexpr u32 SchedPeriod = 4;
166 u32 absolute_offset = offset - main_offset;
167
168 return (absolute_offset % SchedPeriod) == 0;
169}
170
158enum class ParseResult : u32 { 171enum class ParseResult : u32 {
159 ControlCaught = 0, 172 ControlCaught,
160 BlockEnd = 1, 173 BlockEnd,
161 AbnormalFlow = 2, 174 AbnormalFlow,
162}; 175};
163 176
164ParseResult ParseCode(CFGRebuildState& state, u32 address, ParseInfo& parse_info) { 177ParseResult ParseCode(CFGRebuildState& state, u32 address, ParseInfo& parse_info) {
165 u32 offset = static_cast<u32>(address); 178 u32 offset = static_cast<u32>(address);
166 const u32 end_address = static_cast<u32>(state.program_size / 8U); 179 const u32 end_address = static_cast<u32>(state.program_size / sizeof(Instruction));
167 180
168 const auto insert_label = ([](CFGRebuildState& state, u32 address) { 181 const auto insert_label = ([](CFGRebuildState& state, u32 address) {
169 auto pair = state.labels.emplace(address); 182 auto pair = state.labels.emplace(address);
@@ -183,6 +196,10 @@ ParseResult ParseCode(CFGRebuildState& state, u32 address, ParseInfo& parse_info
183 parse_info.branch_info.ignore = true; 196 parse_info.branch_info.ignore = true;
184 break; 197 break;
185 } 198 }
199 if (IsSchedInstruction(offset, state.start)) {
200 offset++;
201 continue;
202 }
186 const Instruction instr = {state.program_code[offset]}; 203 const Instruction instr = {state.program_code[offset]};
187 const auto opcode = OpCode::Decode(instr); 204 const auto opcode = OpCode::Decode(instr);
188 if (!opcode || opcode->get().GetType() != OpCode::Type::Flow) { 205 if (!opcode || opcode->get().GetType() != OpCode::Type::Flow) {
@@ -447,11 +464,11 @@ bool TryQuery(CFGRebuildState& state) {
447 464
448std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size, 465std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u32 program_size,
449 u32 start_address) { 466 u32 start_address) {
450 CFGRebuildState state{program_code, program_size}; 467 CFGRebuildState state{program_code, program_size, start_address};
451 // Inspect Code and generate blocks 468 // Inspect Code and generate blocks
452 state.labels.clear(); 469 state.labels.clear();
453 state.labels.emplace(start_address); 470 state.labels.emplace(start_address);
454 state.inspect_queries.push_back(start_address); 471 state.inspect_queries.push_back(state.start);
455 while (!state.inspect_queries.empty()) { 472 while (!state.inspect_queries.empty()) {
456 if (!TryInspectAddress(state)) { 473 if (!TryInspectAddress(state)) {
457 return {}; 474 return {};
@@ -459,7 +476,7 @@ std::optional<ShaderCharacteristics> ScanFlow(const ProgramCode& program_code, u
459 } 476 }
460 // Decompile Stacks 477 // Decompile Stacks
461 Query start_query{}; 478 Query start_query{};
462 start_query.address = start_address; 479 start_query.address = state.start;
463 state.queries.push_back(start_query); 480 state.queries.push_back(start_query);
464 bool decompiled = true; 481 bool decompiled = true;
465 while (!state.queries.empty()) { 482 while (!state.queries.empty()) {
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index b0bd6630f..07a154d77 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -39,7 +39,7 @@ void ShaderIR::Decode() {
39 std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); 39 std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header));
40 40
41 disable_flow_stack = false; 41 disable_flow_stack = false;
42 const auto info = ScanFlow(program_code, program_size, main_offset); 42 const auto info = ScanFlow(program_code, MAX_PROGRAM_LENGTH * sizeof(u64), main_offset);
43 if (info) { 43 if (info) {
44 const auto& shader_info = *info; 44 const auto& shader_info = *info;
45 coverage_begin = shader_info.start; 45 coverage_begin = shader_info.start;