summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-08-25 04:52:37 -0300
committerGravatar Yuri Kunde Schlesner2015-09-07 16:46:23 -0300
commit9431ee330aab4d1bb622bf9250a0cc57cfe99982 (patch)
tree29ec436c117275a6595f827dee54482b4ca011dd /src
parentMerge pull request #1117 from yuriks/fix-glad-build (diff)
downloadyuzu-9431ee330aab4d1bb622bf9250a0cc57cfe99982.tar.gz
yuzu-9431ee330aab4d1bb622bf9250a0cc57cfe99982.tar.xz
yuzu-9431ee330aab4d1bb622bf9250a0cc57cfe99982.zip
Shader Disassembly: Cleanup code and improve output alignment
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/graphics_vertex_shader.cpp145
1 files changed, 79 insertions, 66 deletions
diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp
index 1d9a00e89..eaa749f30 100644
--- a/src/citra_qt/debugger/graphics_vertex_shader.cpp
+++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp
@@ -65,6 +65,19 @@ QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orie
65 return QVariant(); 65 return QVariant();
66} 66}
67 67
68// e.g. "-c92[a0.x].xyzw"
69static void print_input(std::ostringstream& output, const SourceRegister& input,
70 bool negate, const std::string& swizzle_mask, bool align = true,
71 const std::string& address_register_name = std::string()) {
72 if (align)
73 output << std::setw(4) << std::right;
74 output << ((negate ? "-" : "") + input.GetName());
75
76 if (!address_register_name.empty())
77 output << '[' << address_register_name << ']';
78 output << '.' << swizzle_mask;
79};
80
68QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const { 81QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const {
69 switch (role) { 82 switch (role) {
70 case Qt::DisplayRole: 83 case Qt::DisplayRole:
@@ -81,43 +94,34 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
81 94
82 case 2: 95 case 2:
83 { 96 {
84 std::stringstream output; 97 std::ostringstream output;
85 output.flags(std::ios::hex); 98 output.flags(std::ios::hex | std::ios::uppercase);
99
100 // To make the code aligning columns of assembly easier to keep track of, this function
101 // keeps track of the start of the start of the previous column, allowing alignment
102 // based on desired field widths.
103 int current_column = 0;
104 auto AlignToColumn = [&](int col_width) {
105 // Prints spaces to the output to pad previous column to size and advances the
106 // column marker.
107 current_column += col_width;
108 int to_add = std::max(1, current_column - (int)output.tellp());
109 for (int i = 0; i < to_add; ++i) {
110 output << ' ';
111 }
112 };
86 113
87 Instruction instr = par->info.code[index.row()]; 114 Instruction instr = par->info.code[index.row()];
88 const SwizzlePattern& swizzle = par->info.swizzle_info[instr.common.operand_desc_id].pattern; 115 const SwizzlePattern& swizzle = par->info.swizzle_info[instr.common.operand_desc_id].pattern;
89 116
90 // longest known instruction name: "setemit " 117 // longest known instruction name: "setemit "
91 output << std::setw(8) << std::left << instr.opcode.Value().GetInfo().name; 118 int kOpcodeColumnWidth = 8;
92 119 // "rXX.xyzw "
93 // e.g. "-c92.xyzw" 120 int kOutputColumnWidth = 10;
94 static auto print_input = [](std::stringstream& output, const SourceRegister& input, 121 // "-rXX.xyzw ", no attempt is made to align indexed inputs
95 bool negate, const std::string& swizzle_mask) { 122 int kInputOperandColumnWidth = 11;
96 output << std::setw(4) << std::right << (negate ? "-" : "") + input.GetName();
97 output << "." << swizzle_mask;
98 };
99
100 // e.g. "-c92[a0.x].xyzw"
101 static auto print_input_indexed = [](std::stringstream& output, const SourceRegister& input,
102 bool negate, const std::string& swizzle_mask,
103 const std::string& address_register_name) {
104 std::string relative_address;
105 if (!address_register_name.empty())
106 relative_address = "[" + address_register_name + "]";
107
108 output << std::setw(10) << std::right << (negate ? "-" : "") + input.GetName() + relative_address;
109 output << "." << swizzle_mask;
110 };
111 123
112 // Use print_input or print_input_indexed depending on whether relative addressing is used or not. 124 output << instr.opcode.Value().GetInfo().name;
113 static auto print_input_indexed_compact = [](std::stringstream& output, const SourceRegister& input,
114 bool negate, const std::string& swizzle_mask,
115 const std::string& address_register_name) {
116 if (address_register_name.empty())
117 print_input(output, input, negate, swizzle_mask);
118 else
119 print_input_indexed(output, input, negate, swizzle_mask, address_register_name);
120 };
121 125
122 switch (instr.opcode.Value().GetInfo().type) { 126 switch (instr.opcode.Value().GetInfo().type) {
123 case OpCode::Type::Trivial: 127 case OpCode::Type::Trivial:
@@ -130,53 +134,54 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
130 switch (instr.opcode.Value().EffectiveOpCode()) { 134 switch (instr.opcode.Value().EffectiveOpCode()) {
131 case OpCode::Id::CMP: 135 case OpCode::Id::CMP:
132 { 136 {
137 AlignToColumn(kOpcodeColumnWidth);
138
133 // NOTE: CMP always writes both cc components, so we do not consider the dest mask here. 139 // NOTE: CMP always writes both cc components, so we do not consider the dest mask here.
134 output << std::setw(4) << std::right << "cc."; 140 output << " cc.xy";
135 output << "xy "; 141 AlignToColumn(kOutputColumnWidth);
136 142
137 SourceRegister src1 = instr.common.GetSrc1(false); 143 SourceRegister src1 = instr.common.GetSrc1(false);
138 SourceRegister src2 = instr.common.GetSrc2(false); 144 SourceRegister src2 = instr.common.GetSrc2(false);
139 145
140 print_input_indexed_compact(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(0,1), instr.common.AddressRegisterName()); 146 output << ' ';
141 output << " " << instr.common.compare_op.ToString(instr.common.compare_op.x) << " "; 147 print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(0,1), false, instr.common.AddressRegisterName());
142 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(0,1)); 148 output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x) << ' ';
149 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(0,1), false);
143 150
144 output << ", "; 151 output << ", ";
145 152
146 print_input_indexed_compact(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(1,1), instr.common.AddressRegisterName()); 153 print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(1,1), false, instr.common.AddressRegisterName());
147 output << " " << instr.common.compare_op.ToString(instr.common.compare_op.y) << " "; 154 output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y) << ' ';
148 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(1,1)); 155 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(1,1), false);
149 156
150 break; 157 break;
151 } 158 }
152 159
153 default: 160 default:
154 { 161 {
162 AlignToColumn(kOpcodeColumnWidth);
163
155 bool src_is_inverted = 0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed); 164 bool src_is_inverted = 0 != (instr.opcode.Value().GetInfo().subtype & OpCode::Info::SrcInversed);
156 165
157 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::Dest) { 166 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::Dest) {
158 // e.g. "r12.xy__" 167 // e.g. "r12.xy__"
159 output << std::setw(4) << std::right << instr.common.dest.Value().GetName() + "."; 168 output << std::setw(3) << std::right << instr.common.dest.Value().GetName() << '.' << swizzle.DestMaskToString();
160 output << swizzle.DestMaskToString();
161 } else if (instr.opcode.Value().GetInfo().subtype == OpCode::Info::MOVA) { 169 } else if (instr.opcode.Value().GetInfo().subtype == OpCode::Info::MOVA) {
162 output << std::setw(4) << std::right << "a0."; 170 output << " a0." << swizzle.DestMaskToString();
163 output << swizzle.DestMaskToString();
164 } else {
165 output << " ";
166 } 171 }
167 output << " "; 172 AlignToColumn(kOutputColumnWidth);
168 173
169 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::Src1) { 174 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::Src1) {
170 SourceRegister src1 = instr.common.GetSrc1(src_is_inverted); 175 SourceRegister src1 = instr.common.GetSrc1(src_is_inverted);
171 print_input_indexed(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false), instr.common.AddressRegisterName()); 176 print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false), true, instr.common.AddressRegisterName());
172 } else { 177 AlignToColumn(kInputOperandColumnWidth);
173 output << " ";
174 } 178 }
175 179
176 // TODO: In some cases, the Address Register is used as an index for SRC2 instead of SRC1 180 // TODO: In some cases, the Address Register is used as an index for SRC2 instead of SRC1
177 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::Src2) { 181 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::Src2) {
178 SourceRegister src2 = instr.common.GetSrc2(src_is_inverted); 182 SourceRegister src2 = instr.common.GetSrc2(src_is_inverted);
179 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true)); 183 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true));
184 AlignToColumn(kInputOperandColumnWidth);
180 } 185 }
181 break; 186 break;
182 } 187 }
@@ -187,45 +192,53 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
187 192
188 case OpCode::Type::Conditional: 193 case OpCode::Type::Conditional:
189 { 194 {
195 output << ' ';
196
190 switch (instr.opcode.Value().EffectiveOpCode()) { 197 switch (instr.opcode.Value().EffectiveOpCode()) {
191 case OpCode::Id::LOOP: 198 case OpCode::Id::LOOP:
192 output << "(unknown instruction format)"; 199 output << "(unknown instruction format)";
193 break; 200 break;
194 201
195 default: 202 default:
196 output << "if ";
197
198 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasCondition) { 203 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasCondition) {
199 const char* ops[] = { 204 output << '(';
200 " || ", " && ", "", "" 205
201 }; 206 if (instr.flow_control.op != instr.flow_control.JustY) {
202 if (instr.flow_control.op != instr.flow_control.JustY) 207 if (instr.flow_control.refx) output << '!';
203 output << ((!instr.flow_control.refx) ? "!" : " ") << "cc.x"; 208 output << "cc.x";
209 }
204 210
205 output << ops[instr.flow_control.op]; 211 if (instr.flow_control.op == instr.flow_control.Or) {
212 output << " || ";
213 } else if (instr.flow_control.op == instr.flow_control.And) {
214 output << " && ";
215 }
206 216
207 if (instr.flow_control.op != instr.flow_control.JustX) 217 if (instr.flow_control.op != instr.flow_control.JustX) {
208 output << ((!instr.flow_control.refy) ? "!" : " ") << "cc.y"; 218 if (instr.flow_control.refy) output << '!';
219 output << "cc.y";
220 }
209 221
210 output << " "; 222 output << ") ";
211 } else if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasUniformIndex) { 223 } else if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasUniformIndex) {
212 output << "b" << instr.flow_control.bool_uniform_id << " "; 224 output << 'b' << instr.flow_control.bool_uniform_id << ' ';
213 } 225 }
214 226
215 u32 target_addr = instr.flow_control.dest_offset; 227 u32 target_addr = instr.flow_control.dest_offset;
216 u32 target_addr_else = instr.flow_control.dest_offset; 228 u32 target_addr_else = instr.flow_control.dest_offset;
217 229
218 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasAlternative) { 230 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasAlternative) {
219 output << "else jump to 0x" << std::setw(4) << std::right << std::setfill('0') << 4 * instr.flow_control.dest_offset << " "; 231 output << "else jump to 0x" << std::setw(4) << std::right << std::setfill('0') << (4 * instr.flow_control.dest_offset);
220 } else if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasExplicitDest) { 232 } else if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasExplicitDest) {
221 output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') << 4 * instr.flow_control.dest_offset << " "; 233 output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') << (4 * instr.flow_control.dest_offset);
222 } else { 234 } else {
223 // TODO: Handle other cases 235 // TODO: Handle other cases
236 output << "(unknown destination)";
224 } 237 }
225 238
226 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasFinishPoint) { 239 if (instr.opcode.Value().GetInfo().subtype & OpCode::Info::HasFinishPoint) {
227 output << "(return on " << std::setw(4) << std::right << std::setfill('0') 240 output << " (return on " << std::setw(4) << std::right << std::setfill('0')
228 << 4 * instr.flow_control.dest_offset + 4 * instr.flow_control.num_instructions << ")"; 241 << (4 * instr.flow_control.dest_offset + 4 * instr.flow_control.num_instructions) << ')';
229 } 242 }
230 243
231 break; 244 break;
@@ -234,7 +247,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
234 } 247 }
235 248
236 default: 249 default:
237 output << "(unknown instruction format)"; 250 output << " (unknown instruction format)";
238 break; 251 break;
239 } 252 }
240 253