summaryrefslogtreecommitdiff
path: root/src/citra_qt/debugger/graphics_vertex_shader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/citra_qt/debugger/graphics_vertex_shader.cpp')
-rw-r--r--src/citra_qt/debugger/graphics_vertex_shader.cpp210
1 files changed, 134 insertions, 76 deletions
diff --git a/src/citra_qt/debugger/graphics_vertex_shader.cpp b/src/citra_qt/debugger/graphics_vertex_shader.cpp
index 391666d35..c49327f9c 100644
--- a/src/citra_qt/debugger/graphics_vertex_shader.cpp
+++ b/src/citra_qt/debugger/graphics_vertex_shader.cpp
@@ -28,8 +28,8 @@ using nihstro::Instruction;
28using nihstro::SourceRegister; 28using nihstro::SourceRegister;
29using nihstro::SwizzlePattern; 29using nihstro::SwizzlePattern;
30 30
31GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent): QAbstractTableModel(parent), par(parent) { 31GraphicsVertexShaderModel::GraphicsVertexShaderModel(GraphicsVertexShaderWidget* parent)
32 32 : QAbstractTableModel(parent), par(parent) {
33} 33}
34 34
35int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const { 35int GraphicsVertexShaderModel::columnCount(const QModelIndex& parent) const {
@@ -40,10 +40,10 @@ int GraphicsVertexShaderModel::rowCount(const QModelIndex& parent) const {
40 return static_cast<int>(par->info.code.size()); 40 return static_cast<int>(par->info.code.size());
41} 41}
42 42
43QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation, int role) const { 43QVariant GraphicsVertexShaderModel::headerData(int section, Qt::Orientation orientation,
44 switch(role) { 44 int role) const {
45 case Qt::DisplayRole: 45 switch (role) {
46 { 46 case Qt::DisplayRole: {
47 if (section == 0) { 47 if (section == 0) {
48 return tr("Offset"); 48 return tr("Offset");
49 } else if (section == 1) { 49 } else if (section == 1) {
@@ -69,8 +69,8 @@ static std::string SelectorToString(u32 selector) {
69} 69}
70 70
71// e.g. "-c92[a0.x].xyzw" 71// e.g. "-c92[a0.x].xyzw"
72static void print_input(std::ostringstream& output, const SourceRegister& input, 72static void print_input(std::ostringstream& output, const SourceRegister& input, bool negate,
73 bool negate, const std::string& swizzle_mask, bool align = true, 73 const std::string& swizzle_mask, bool align = true,
74 const std::string& address_register_name = std::string()) { 74 const std::string& address_register_name = std::string()) {
75 if (align) 75 if (align)
76 output << std::setw(4) << std::right; 76 output << std::setw(4) << std::right;
@@ -83,20 +83,18 @@ static void print_input(std::ostringstream& output, const SourceRegister& input,
83 83
84QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const { 84QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) const {
85 switch (role) { 85 switch (role) {
86 case Qt::DisplayRole: 86 case Qt::DisplayRole: {
87 {
88 switch (index.column()) { 87 switch (index.column()) {
89 case 0: 88 case 0:
90 if (par->info.HasLabel(index.row())) 89 if (par->info.HasLabel(index.row()))
91 return QString::fromStdString(par->info.GetLabel(index.row())); 90 return QString::fromStdString(par->info.GetLabel(index.row()));
92 91
93 return QString("%1").arg(4*index.row(), 4, 16, QLatin1Char('0')); 92 return QString("%1").arg(4 * index.row(), 4, 16, QLatin1Char('0'));
94 93
95 case 1: 94 case 1:
96 return QString("%1").arg(par->info.code[index.row()].hex, 8, 16, QLatin1Char('0')); 95 return QString("%1").arg(par->info.code[index.row()].hex, 8, 16, QLatin1Char('0'));
97 96
98 case 2: 97 case 2: {
99 {
100 std::ostringstream output; 98 std::ostringstream output;
101 output.flags(std::ios::uppercase); 99 output.flags(std::ios::uppercase);
102 100
@@ -117,8 +115,9 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
117 const Instruction instr = par->info.code[index.row()]; 115 const Instruction instr = par->info.code[index.row()];
118 const OpCode opcode = instr.opcode; 116 const OpCode opcode = instr.opcode;
119 const OpCode::Info opcode_info = opcode.GetInfo(); 117 const OpCode::Info opcode_info = opcode.GetInfo();
120 const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd ? 118 const u32 operand_desc_id = opcode_info.type == OpCode::Type::MultiplyAdd
121 instr.mad.operand_desc_id.Value() : instr.common.operand_desc_id.Value(); 119 ? instr.mad.operand_desc_id.Value()
120 : instr.common.operand_desc_id.Value();
122 const SwizzlePattern swizzle = par->info.swizzle_info[operand_desc_id].pattern; 121 const SwizzlePattern swizzle = par->info.swizzle_info[operand_desc_id].pattern;
123 122
124 // longest known instruction name: "setemit " 123 // longest known instruction name: "setemit "
@@ -136,15 +135,14 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
136 break; 135 break;
137 136
138 case OpCode::Type::Arithmetic: 137 case OpCode::Type::Arithmetic:
139 case OpCode::Type::MultiplyAdd: 138 case OpCode::Type::MultiplyAdd: {
140 {
141 // Use custom code for special instructions 139 // Use custom code for special instructions
142 switch (opcode.EffectiveOpCode()) { 140 switch (opcode.EffectiveOpCode()) {
143 case OpCode::Id::CMP: 141 case OpCode::Id::CMP: {
144 {
145 AlignToColumn(kOpcodeColumnWidth); 142 AlignToColumn(kOpcodeColumnWidth);
146 143
147 // NOTE: CMP always writes both cc components, so we do not consider the dest mask here. 144 // NOTE: CMP always writes both cc components, so we do not consider the dest
145 // mask here.
148 output << " cc.xy"; 146 output << " cc.xy";
149 AlignToColumn(kOutputColumnWidth); 147 AlignToColumn(kOutputColumnWidth);
150 148
@@ -152,22 +150,29 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
152 SourceRegister src2 = instr.common.GetSrc2(false); 150 SourceRegister src2 = instr.common.GetSrc2(false);
153 151
154 output << ' '; 152 output << ' ';
155 print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(0,1), false, instr.common.AddressRegisterName()); 153 print_input(output, src1, swizzle.negate_src1,
156 output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x) << ' '; 154 swizzle.SelectorToString(false).substr(0, 1), false,
157 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(0,1), false); 155 instr.common.AddressRegisterName());
156 output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.x)
157 << ' ';
158 print_input(output, src2, swizzle.negate_src2,
159 swizzle.SelectorToString(true).substr(0, 1), false);
158 160
159 output << ", "; 161 output << ", ";
160 162
161 print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false).substr(1,1), false, instr.common.AddressRegisterName()); 163 print_input(output, src1, swizzle.negate_src1,
162 output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y) << ' '; 164 swizzle.SelectorToString(false).substr(1, 1), false,
163 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true).substr(1,1), false); 165 instr.common.AddressRegisterName());
166 output << ' ' << instr.common.compare_op.ToString(instr.common.compare_op.y)
167 << ' ';
168 print_input(output, src2, swizzle.negate_src2,
169 swizzle.SelectorToString(true).substr(1, 1), false);
164 170
165 break; 171 break;
166 } 172 }
167 173
168 case OpCode::Id::MAD: 174 case OpCode::Id::MAD:
169 case OpCode::Id::MADI: 175 case OpCode::Id::MADI: {
170 {
171 AlignToColumn(kOpcodeColumnWidth); 176 AlignToColumn(kOpcodeColumnWidth);
172 177
173 bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); 178 bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed);
@@ -175,34 +180,42 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
175 SourceRegister src2 = instr.mad.GetSrc2(src_is_inverted); 180 SourceRegister src2 = instr.mad.GetSrc2(src_is_inverted);
176 SourceRegister src3 = instr.mad.GetSrc3(src_is_inverted); 181 SourceRegister src3 = instr.mad.GetSrc3(src_is_inverted);
177 182
178 output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.' << swizzle.DestMaskToString(); 183 output << std::setw(3) << std::right << instr.mad.dest.Value().GetName() << '.'
184 << swizzle.DestMaskToString();
179 AlignToColumn(kOutputColumnWidth); 185 AlignToColumn(kOutputColumnWidth);
180 print_input(output, src1, swizzle.negate_src1, SelectorToString(swizzle.src1_selector)); 186 print_input(output, src1, swizzle.negate_src1,
187 SelectorToString(swizzle.src1_selector));
181 AlignToColumn(kInputOperandColumnWidth); 188 AlignToColumn(kInputOperandColumnWidth);
182 if (src_is_inverted) { 189 if (src_is_inverted) {
183 print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector)); 190 print_input(output, src2, swizzle.negate_src2,
191 SelectorToString(swizzle.src2_selector));
184 } else { 192 } else {
185 print_input(output, src2, swizzle.negate_src2, SelectorToString(swizzle.src2_selector), true, instr.mad.AddressRegisterName()); 193 print_input(output, src2, swizzle.negate_src2,
194 SelectorToString(swizzle.src2_selector), true,
195 instr.mad.AddressRegisterName());
186 } 196 }
187 AlignToColumn(kInputOperandColumnWidth); 197 AlignToColumn(kInputOperandColumnWidth);
188 if (src_is_inverted) { 198 if (src_is_inverted) {
189 print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector), true, instr.mad.AddressRegisterName()); 199 print_input(output, src3, swizzle.negate_src3,
200 SelectorToString(swizzle.src3_selector), true,
201 instr.mad.AddressRegisterName());
190 } else { 202 } else {
191 print_input(output, src3, swizzle.negate_src3, SelectorToString(swizzle.src3_selector)); 203 print_input(output, src3, swizzle.negate_src3,
204 SelectorToString(swizzle.src3_selector));
192 } 205 }
193 AlignToColumn(kInputOperandColumnWidth); 206 AlignToColumn(kInputOperandColumnWidth);
194 break; 207 break;
195 } 208 }
196 209
197 default: 210 default: {
198 {
199 AlignToColumn(kOpcodeColumnWidth); 211 AlignToColumn(kOpcodeColumnWidth);
200 212
201 bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed); 213 bool src_is_inverted = 0 != (opcode_info.subtype & OpCode::Info::SrcInversed);
202 214
203 if (opcode_info.subtype & OpCode::Info::Dest) { 215 if (opcode_info.subtype & OpCode::Info::Dest) {
204 // e.g. "r12.xy__" 216 // e.g. "r12.xy__"
205 output << std::setw(3) << std::right << instr.common.dest.Value().GetName() << '.' << swizzle.DestMaskToString(); 217 output << std::setw(3) << std::right << instr.common.dest.Value().GetName()
218 << '.' << swizzle.DestMaskToString();
206 } else if (opcode_info.subtype == OpCode::Info::MOVA) { 219 } else if (opcode_info.subtype == OpCode::Info::MOVA) {
207 output << " a0." << swizzle.DestMaskToString(); 220 output << " a0." << swizzle.DestMaskToString();
208 } 221 }
@@ -210,14 +223,18 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
210 223
211 if (opcode_info.subtype & OpCode::Info::Src1) { 224 if (opcode_info.subtype & OpCode::Info::Src1) {
212 SourceRegister src1 = instr.common.GetSrc1(src_is_inverted); 225 SourceRegister src1 = instr.common.GetSrc1(src_is_inverted);
213 print_input(output, src1, swizzle.negate_src1, swizzle.SelectorToString(false), true, instr.common.AddressRegisterName()); 226 print_input(output, src1, swizzle.negate_src1,
227 swizzle.SelectorToString(false), true,
228 instr.common.AddressRegisterName());
214 AlignToColumn(kInputOperandColumnWidth); 229 AlignToColumn(kInputOperandColumnWidth);
215 } 230 }
216 231
217 // TODO: In some cases, the Address Register is used as an index for SRC2 instead of SRC1 232 // TODO: In some cases, the Address Register is used as an index for SRC2
233 // instead of SRC1
218 if (opcode_info.subtype & OpCode::Info::Src2) { 234 if (opcode_info.subtype & OpCode::Info::Src2) {
219 SourceRegister src2 = instr.common.GetSrc2(src_is_inverted); 235 SourceRegister src2 = instr.common.GetSrc2(src_is_inverted);
220 print_input(output, src2, swizzle.negate_src2, swizzle.SelectorToString(true)); 236 print_input(output, src2, swizzle.negate_src2,
237 swizzle.SelectorToString(true));
221 AlignToColumn(kInputOperandColumnWidth); 238 AlignToColumn(kInputOperandColumnWidth);
222 } 239 }
223 break; 240 break;
@@ -228,8 +245,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
228 } 245 }
229 246
230 case OpCode::Type::Conditional: 247 case OpCode::Type::Conditional:
231 case OpCode::Type::UniformFlowControl: 248 case OpCode::Type::UniformFlowControl: {
232 {
233 output << ' '; 249 output << ' ';
234 250
235 switch (opcode.EffectiveOpCode()) { 251 switch (opcode.EffectiveOpCode()) {
@@ -242,7 +258,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
242 output << '('; 258 output << '(';
243 259
244 if (instr.flow_control.op != instr.flow_control.JustY) { 260 if (instr.flow_control.op != instr.flow_control.JustY) {
245 if (instr.flow_control.refx) output << '!'; 261 if (instr.flow_control.refx)
262 output << '!';
246 output << "cc.x"; 263 output << "cc.x";
247 } 264 }
248 265
@@ -253,7 +270,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
253 } 270 }
254 271
255 if (instr.flow_control.op != instr.flow_control.JustX) { 272 if (instr.flow_control.op != instr.flow_control.JustX) {
256 if (instr.flow_control.refy) output << '!'; 273 if (instr.flow_control.refy)
274 output << '!';
257 output << "cc.y"; 275 output << "cc.y";
258 } 276 }
259 277
@@ -266,17 +284,23 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
266 u32 target_addr_else = instr.flow_control.dest_offset; 284 u32 target_addr_else = instr.flow_control.dest_offset;
267 285
268 if (opcode_info.subtype & OpCode::Info::HasAlternative) { 286 if (opcode_info.subtype & OpCode::Info::HasAlternative) {
269 output << "else jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset); 287 output << "else jump to 0x" << std::setw(4) << std::right
288 << std::setfill('0') << std::hex
289 << (4 * instr.flow_control.dest_offset);
270 } else if (opcode_info.subtype & OpCode::Info::HasExplicitDest) { 290 } else if (opcode_info.subtype & OpCode::Info::HasExplicitDest) {
271 output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex << (4 * instr.flow_control.dest_offset); 291 output << "jump to 0x" << std::setw(4) << std::right << std::setfill('0')
292 << std::hex << (4 * instr.flow_control.dest_offset);
272 } else { 293 } else {
273 // TODO: Handle other cases 294 // TODO: Handle other cases
274 output << "(unknown destination)"; 295 output << "(unknown destination)";
275 } 296 }
276 297
277 if (opcode_info.subtype & OpCode::Info::HasFinishPoint) { 298 if (opcode_info.subtype & OpCode::Info::HasFinishPoint) {
278 output << " (return on 0x" << std::setw(4) << std::right << std::setfill('0') << std::hex 299 output << " (return on 0x" << std::setw(4) << std::right
279 << (4 * instr.flow_control.dest_offset + 4 * instr.flow_control.num_instructions) << ')'; 300 << std::setfill('0') << std::hex
301 << (4 * instr.flow_control.dest_offset +
302 4 * instr.flow_control.num_instructions)
303 << ')';
280 } 304 }
281 305
282 break; 306 break;
@@ -300,8 +324,7 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
300 case Qt::FontRole: 324 case Qt::FontRole:
301 return GetMonospaceFont(); 325 return GetMonospaceFont();
302 326
303 case Qt::BackgroundRole: 327 case Qt::BackgroundRole: {
304 {
305 // Highlight current instruction 328 // Highlight current instruction
306 int current_record_index = par->cycle_index->value(); 329 int current_record_index = par->cycle_index->value();
307 if (current_record_index < static_cast<int>(par->debug_data.records.size())) { 330 if (current_record_index < static_cast<int>(par->debug_data.records.size())) {
@@ -319,10 +342,8 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
319 return QBrush(QColor(192, 192, 192)); 342 return QBrush(QColor(192, 192, 192));
320 } 343 }
321 344
322
323 // TODO: Draw arrows for each "reachable" instruction to visualize control flow 345 // TODO: Draw arrows for each "reachable" instruction to visualize control flow
324 346
325
326 default: 347 default:
327 break; 348 break;
328 } 349 }
@@ -331,23 +352,24 @@ QVariant GraphicsVertexShaderModel::data(const QModelIndex& index, int role) con
331} 352}
332 353
333void GraphicsVertexShaderWidget::DumpShader() { 354void GraphicsVertexShaderWidget::DumpShader() {
334 QString filename = QFileDialog::getSaveFileName(this, tr("Save Shader Dump"), "shader_dump.shbin", 355 QString filename = QFileDialog::getSaveFileName(
335 tr("Shader Binary (*.shbin)")); 356 this, tr("Save Shader Dump"), "shader_dump.shbin", tr("Shader Binary (*.shbin)"));
336 357
337 if (filename.isEmpty()) { 358 if (filename.isEmpty()) {
338 // If the user canceled the dialog, don't dump anything. 359 // If the user canceled the dialog, don't dump anything.
339 return; 360 return;
340 } 361 }
341 362
342 auto& setup = Pica::g_state.vs; 363 auto& setup = Pica::g_state.vs;
343 auto& config = Pica::g_state.regs.vs; 364 auto& config = Pica::g_state.regs.vs;
344 365
345 Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup, Pica::g_state.regs.vs_output_attributes); 366 Pica::DebugUtils::DumpShader(filename.toStdString(), config, setup,
367 Pica::g_state.regs.vs_output_attributes);
346} 368}
347 369
348GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::DebugContext > debug_context, 370GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(
349 QWidget* parent) 371 std::shared_ptr<Pica::DebugContext> debug_context, QWidget* parent)
350 : BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) { 372 : BreakPointObserverDock(debug_context, "Pica Vertex Shader", parent) {
351 setObjectName("PicaVertexShader"); 373 setObjectName("PicaVertexShader");
352 374
353 // Clear input vertex data so that it contains valid float values in case a debug shader 375 // Clear input vertex data so that it contains valid float values in case a debug shader
@@ -365,7 +387,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De
365 input_data[i]->setValidator(new QDoubleValidator(input_data[i])); 387 input_data[i]->setValidator(new QDoubleValidator(input_data[i]));
366 } 388 }
367 389
368 breakpoint_warning = new QLabel(tr("(data only available at vertex shader invocation breakpoints)")); 390 breakpoint_warning =
391 new QLabel(tr("(data only available at vertex shader invocation breakpoints)"));
369 392
370 // TODO: Add some button for jumping to the shader entry point 393 // TODO: Add some button for jumping to the shader entry point
371 394
@@ -442,7 +465,8 @@ GraphicsVertexShaderWidget::GraphicsVertexShaderWidget(std::shared_ptr< Pica::De
442 465
443 // Set a minimum height so that the size of this label doesn't cause the rest of the bottom 466 // Set a minimum height so that the size of this label doesn't cause the rest of the bottom
444 // part of the UI to keep jumping up and down when cycling through instructions. 467 // part of the UI to keep jumping up and down when cycling through instructions.
445 instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() * 6); 468 instruction_description->setMinimumHeight(instruction_description->fontMetrics().lineSpacing() *
469 6);
446 instruction_description->setAlignment(Qt::AlignLeft | Qt::AlignTop); 470 instruction_description->setAlignment(Qt::AlignLeft | Qt::AlignTop);
447 main_layout->addWidget(instruction_description); 471 main_layout->addWidget(instruction_description);
448 472
@@ -471,7 +495,8 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d
471 memcpy(&input_vertex, vertex_data, sizeof(input_vertex)); 495 memcpy(&input_vertex, vertex_data, sizeof(input_vertex));
472 for (unsigned attr = 0; attr < 16; ++attr) { 496 for (unsigned attr = 0; attr < 16; ++attr) {
473 for (unsigned comp = 0; comp < 4; ++comp) { 497 for (unsigned comp = 0; comp < 4; ++comp) {
474 input_data[4 * attr + comp]->setText(QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32())); 498 input_data[4 * attr + comp]->setText(
499 QString("%1").arg(input_vertex.attr[attr][comp].ToFloat32()));
475 } 500 }
476 } 501 }
477 breakpoint_warning->hide(); 502 breakpoint_warning->hide();
@@ -498,10 +523,11 @@ void GraphicsVertexShaderWidget::Reload(bool replace_vertex_data, void* vertex_d
498 info.swizzle_info.push_back({pattern}); 523 info.swizzle_info.push_back({pattern});
499 524
500 u32 entry_point = Pica::g_state.regs.vs.main_offset; 525 u32 entry_point = Pica::g_state.regs.vs.main_offset;
501 info.labels.insert({ entry_point, "main" }); 526 info.labels.insert({entry_point, "main"});
502 527
503 // Generate debug information 528 // Generate debug information
504 debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config, shader_setup); 529 debug_data = Pica::g_state.vs.ProduceDebugInfo(input_vertex, num_attributes, shader_config,
530 shader_setup);
505 531
506 // Reload widget state 532 // Reload widget state
507 for (int attr = 0; attr < num_attributes; ++attr) { 533 for (int attr = 0; attr < num_attributes; ++attr) {
@@ -537,29 +563,60 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) {
537 563
538 auto& record = debug_data.records[index]; 564 auto& record = debug_data.records[index];
539 if (record.mask & Pica::Shader::DebugDataRecord::SRC1) 565 if (record.mask & Pica::Shader::DebugDataRecord::SRC1)
540 text += tr("SRC1: %1, %2, %3, %4\n").arg(record.src1.x.ToFloat32()).arg(record.src1.y.ToFloat32()).arg(record.src1.z.ToFloat32()).arg(record.src1.w.ToFloat32()); 566 text += tr("SRC1: %1, %2, %3, %4\n")
567 .arg(record.src1.x.ToFloat32())
568 .arg(record.src1.y.ToFloat32())
569 .arg(record.src1.z.ToFloat32())
570 .arg(record.src1.w.ToFloat32());
541 if (record.mask & Pica::Shader::DebugDataRecord::SRC2) 571 if (record.mask & Pica::Shader::DebugDataRecord::SRC2)
542 text += tr("SRC2: %1, %2, %3, %4\n").arg(record.src2.x.ToFloat32()).arg(record.src2.y.ToFloat32()).arg(record.src2.z.ToFloat32()).arg(record.src2.w.ToFloat32()); 572 text += tr("SRC2: %1, %2, %3, %4\n")
573 .arg(record.src2.x.ToFloat32())
574 .arg(record.src2.y.ToFloat32())
575 .arg(record.src2.z.ToFloat32())
576 .arg(record.src2.w.ToFloat32());
543 if (record.mask & Pica::Shader::DebugDataRecord::SRC3) 577 if (record.mask & Pica::Shader::DebugDataRecord::SRC3)
544 text += tr("SRC3: %1, %2, %3, %4\n").arg(record.src3.x.ToFloat32()).arg(record.src3.y.ToFloat32()).arg(record.src3.z.ToFloat32()).arg(record.src3.w.ToFloat32()); 578 text += tr("SRC3: %1, %2, %3, %4\n")
579 .arg(record.src3.x.ToFloat32())
580 .arg(record.src3.y.ToFloat32())
581 .arg(record.src3.z.ToFloat32())
582 .arg(record.src3.w.ToFloat32());
545 if (record.mask & Pica::Shader::DebugDataRecord::DEST_IN) 583 if (record.mask & Pica::Shader::DebugDataRecord::DEST_IN)
546 text += tr("DEST_IN: %1, %2, %3, %4\n").arg(record.dest_in.x.ToFloat32()).arg(record.dest_in.y.ToFloat32()).arg(record.dest_in.z.ToFloat32()).arg(record.dest_in.w.ToFloat32()); 584 text += tr("DEST_IN: %1, %2, %3, %4\n")
585 .arg(record.dest_in.x.ToFloat32())
586 .arg(record.dest_in.y.ToFloat32())
587 .arg(record.dest_in.z.ToFloat32())
588 .arg(record.dest_in.w.ToFloat32());
547 if (record.mask & Pica::Shader::DebugDataRecord::DEST_OUT) 589 if (record.mask & Pica::Shader::DebugDataRecord::DEST_OUT)
548 text += tr("DEST_OUT: %1, %2, %3, %4\n").arg(record.dest_out.x.ToFloat32()).arg(record.dest_out.y.ToFloat32()).arg(record.dest_out.z.ToFloat32()).arg(record.dest_out.w.ToFloat32()); 590 text += tr("DEST_OUT: %1, %2, %3, %4\n")
591 .arg(record.dest_out.x.ToFloat32())
592 .arg(record.dest_out.y.ToFloat32())
593 .arg(record.dest_out.z.ToFloat32())
594 .arg(record.dest_out.w.ToFloat32());
549 595
550 if (record.mask & Pica::Shader::DebugDataRecord::ADDR_REG_OUT) 596 if (record.mask & Pica::Shader::DebugDataRecord::ADDR_REG_OUT)
551 text += tr("Addres Registers: %1, %2\n").arg(record.address_registers[0]).arg(record.address_registers[1]); 597 text += tr("Addres Registers: %1, %2\n")
598 .arg(record.address_registers[0])
599 .arg(record.address_registers[1]);
552 if (record.mask & Pica::Shader::DebugDataRecord::CMP_RESULT) 600 if (record.mask & Pica::Shader::DebugDataRecord::CMP_RESULT)
553 text += tr("Compare Result: %1, %2\n").arg(record.conditional_code[0] ? "true" : "false").arg(record.conditional_code[1] ? "true" : "false"); 601 text += tr("Compare Result: %1, %2\n")
602 .arg(record.conditional_code[0] ? "true" : "false")
603 .arg(record.conditional_code[1] ? "true" : "false");
554 604
555 if (record.mask & Pica::Shader::DebugDataRecord::COND_BOOL_IN) 605 if (record.mask & Pica::Shader::DebugDataRecord::COND_BOOL_IN)
556 text += tr("Static Condition: %1\n").arg(record.cond_bool ? "true" : "false"); 606 text += tr("Static Condition: %1\n").arg(record.cond_bool ? "true" : "false");
557 if (record.mask & Pica::Shader::DebugDataRecord::COND_CMP_IN) 607 if (record.mask & Pica::Shader::DebugDataRecord::COND_CMP_IN)
558 text += tr("Dynamic Conditions: %1, %2\n").arg(record.cond_cmp[0] ? "true" : "false").arg(record.cond_cmp[1] ? "true" : "false"); 608 text += tr("Dynamic Conditions: %1, %2\n")
609 .arg(record.cond_cmp[0] ? "true" : "false")
610 .arg(record.cond_cmp[1] ? "true" : "false");
559 if (record.mask & Pica::Shader::DebugDataRecord::LOOP_INT_IN) 611 if (record.mask & Pica::Shader::DebugDataRecord::LOOP_INT_IN)
560 text += tr("Loop Parameters: %1 (repeats), %2 (initializer), %3 (increment), %4\n").arg(record.loop_int.x).arg(record.loop_int.y).arg(record.loop_int.z).arg(record.loop_int.w); 612 text += tr("Loop Parameters: %1 (repeats), %2 (initializer), %3 (increment), %4\n")
561 613 .arg(record.loop_int.x)
562 text += tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0')); 614 .arg(record.loop_int.y)
615 .arg(record.loop_int.z)
616 .arg(record.loop_int.w);
617
618 text +=
619 tr("Instruction offset: 0x%1").arg(4 * record.instruction_offset, 4, 16, QLatin1Char('0'));
563 if (record.mask & Pica::Shader::DebugDataRecord::NEXT_INSTR) { 620 if (record.mask & Pica::Shader::DebugDataRecord::NEXT_INSTR) {
564 text += tr(" -> 0x%2").arg(4 * record.next_instruction, 4, 16, QLatin1Char('0')); 621 text += tr(" -> 0x%2").arg(4 * record.next_instruction, 4, 16, QLatin1Char('0'));
565 } else { 622 } else {
@@ -570,6 +627,7 @@ void GraphicsVertexShaderWidget::OnCycleIndexChanged(int index) {
570 627
571 // Emit model update notification and scroll to current instruction 628 // Emit model update notification and scroll to current instruction
572 QModelIndex instr_index = model->index(record.instruction_offset, 0); 629 QModelIndex instr_index = model->index(record.instruction_offset, 0);
573 emit model->dataChanged(instr_index, model->index(record.instruction_offset, model->columnCount())); 630 emit model->dataChanged(instr_index,
631 model->index(record.instruction_offset, model->columnCount()));
574 binary_list->scrollTo(instr_index, QAbstractItemView::EnsureVisible); 632 binary_list->scrollTo(instr_index, QAbstractItemView::EnsureVisible);
575} 633}