summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Tony Wasserka2015-08-16 13:34:45 +0200
committerGravatar Tony Wasserka2015-08-16 13:34:45 +0200
commitf5144e6c10a5e0e0e6a267ca7ef8451f84194ffd (patch)
treee74eb17add0b6e0c33f79b95f95d7561cad7eeae /src
parentMerge pull request #933 from neobrain/shader_debugger (diff)
parentcitra-qt/debug_utils: Use lock_guard everywhere (diff)
downloadyuzu-f5144e6c10a5e0e0e6a267ca7ef8451f84194ffd.tar.gz
yuzu-f5144e6c10a5e0e0e6a267ca7ef8451f84194ffd.tar.xz
yuzu-f5144e6c10a5e0e0e6a267ca7ef8451f84194ffd.zip
Merge pull request #997 from Lectem/cmdlist_full_debug
citra-qt: Improve pica command list widget (add mask, fix some issues)
Diffstat (limited to 'src')
-rw-r--r--src/citra_qt/debugger/graphics_cmdlists.cpp42
-rw-r--r--src/video_core/command_processor.cpp31
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp15
-rw-r--r--src/video_core/debug_utils/debug_utils.h14
4 files changed, 52 insertions, 50 deletions
diff --git a/src/citra_qt/debugger/graphics_cmdlists.cpp b/src/citra_qt/debugger/graphics_cmdlists.cpp
index 7ac3ea542..e51a4480f 100644
--- a/src/citra_qt/debugger/graphics_cmdlists.cpp
+++ b/src/citra_qt/debugger/graphics_cmdlists.cpp
@@ -175,29 +175,29 @@ int GPUCommandListModel::rowCount(const QModelIndex& parent) const {
175} 175}
176 176
177int GPUCommandListModel::columnCount(const QModelIndex& parent) const { 177int GPUCommandListModel::columnCount(const QModelIndex& parent) const {
178 return 3; 178 return 4;
179} 179}
180 180
181QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { 181QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const {
182 if (!index.isValid()) 182 if (!index.isValid())
183 return QVariant(); 183 return QVariant();
184 184
185 const auto& writes = pica_trace.writes; 185 const auto& write = pica_trace.writes[index.row()];
186 const Pica::CommandProcessor::CommandHeader cmd{writes[index.row()].Id()};
187 const u32 val{writes[index.row()].Value()};
188 186
189 if (role == Qt::DisplayRole) { 187 if (role == Qt::DisplayRole) {
190 QString content; 188 QString content;
191 switch ( index.column() ) { 189 switch ( index.column() ) {
192 case 0: 190 case 0:
193 return QString::fromLatin1(Pica::Regs::GetCommandName(cmd.cmd_id).c_str()); 191 return QString::fromLatin1(Pica::Regs::GetCommandName(write.cmd_id).c_str());
194 case 1: 192 case 1:
195 return QString("%1").arg(cmd.cmd_id, 3, 16, QLatin1Char('0')); 193 return QString("%1").arg(write.cmd_id, 3, 16, QLatin1Char('0'));
196 case 2: 194 case 2:
197 return QString("%1").arg(val, 8, 16, QLatin1Char('0')); 195 return QString("%1").arg(write.mask, 4, 2, QLatin1Char('0'));
196 case 3:
197 return QString("%1").arg(write.value, 8, 16, QLatin1Char('0'));
198 } 198 }
199 } else if (role == CommandIdRole) { 199 } else if (role == CommandIdRole) {
200 return QVariant::fromValue<int>(cmd.cmd_id.Value()); 200 return QVariant::fromValue<int>(write.cmd_id);
201 } 201 }
202 202
203 return QVariant(); 203 return QVariant();
@@ -213,6 +213,8 @@ QVariant GPUCommandListModel::headerData(int section, Qt::Orientation orientatio
213 case 1: 213 case 1:
214 return tr("Register"); 214 return tr("Register");
215 case 2: 215 case 2:
216 return tr("Mask");
217 case 3:
216 return tr("New Value"); 218 return tr("New Value");
217 } 219 }
218 220
@@ -260,7 +262,7 @@ void GPUCommandListWidget::OnCommandDoubleClicked(const QModelIndex& index) {
260} 262}
261 263
262void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { 264void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
263 QWidget* new_info_widget; 265 QWidget* new_info_widget = nullptr;
264 266
265 const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt(); 267 const unsigned int command_id = list_widget->model()->data(index, GPUCommandListModel::CommandIdRole).toUInt();
266 if (COMMAND_IN_RANGE(command_id, texture0) || 268 if (COMMAND_IN_RANGE(command_id, texture0) ||
@@ -281,14 +283,15 @@ void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) {
281 auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format); 283 auto info = Pica::DebugUtils::TextureInfo::FromPicaRegister(config, format);
282 u8* src = Memory::GetPhysicalPointer(config.GetPhysicalAddress()); 284 u8* src = Memory::GetPhysicalPointer(config.GetPhysicalAddress());
283 new_info_widget = new TextureInfoWidget(src, info); 285 new_info_widget = new TextureInfoWidget(src, info);
284 } else {
285 new_info_widget = new QWidget;
286 } 286 }
287 287 if (command_info_widget) {
288 widget()->layout()->removeWidget(command_info_widget); 288 delete command_info_widget;
289 delete command_info_widget; 289 command_info_widget = nullptr;
290 widget()->layout()->addWidget(new_info_widget); 290 }
291 command_info_widget = new_info_widget; 291 if (new_info_widget) {
292 widget()->layout()->addWidget(new_info_widget);
293 command_info_widget = new_info_widget;
294 }
292} 295}
293#undef COMMAND_IN_RANGE 296#undef COMMAND_IN_RANGE
294 297
@@ -300,7 +303,9 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi
300 303
301 list_widget = new QTreeView; 304 list_widget = new QTreeView;
302 list_widget->setModel(model); 305 list_widget->setModel(model);
303 list_widget->setFont(QFont("monospace")); 306 QFont font("monospace");
307 font.setStyleHint(QFont::Monospace); // Automatic fallback to a monospace font on on platforms without a font called "monospace"
308 list_widget->setFont(font);
304 list_widget->setRootIsDecorated(false); 309 list_widget->setRootIsDecorated(false);
305 list_widget->setUniformRowHeights(true); 310 list_widget->setUniformRowHeights(true);
306 311
@@ -324,7 +329,7 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi
324 329
325 connect(copy_all, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard())); 330 connect(copy_all, SIGNAL(clicked()), this, SLOT(CopyAllToClipboard()));
326 331
327 command_info_widget = new QWidget; 332 command_info_widget = nullptr;
328 333
329 QVBoxLayout* main_layout = new QVBoxLayout; 334 QVBoxLayout* main_layout = new QVBoxLayout;
330 main_layout->addWidget(list_widget); 335 main_layout->addWidget(list_widget);
@@ -334,7 +339,6 @@ GPUCommandListWidget::GPUCommandListWidget(QWidget* parent) : QDockWidget(tr("Pi
334 sub_layout->addWidget(copy_all); 339 sub_layout->addWidget(copy_all);
335 main_layout->addLayout(sub_layout); 340 main_layout->addLayout(sub_layout);
336 } 341 }
337 main_layout->addWidget(command_info_widget);
338 main_widget->setLayout(main_layout); 342 main_widget->setLayout(main_layout);
339 343
340 setWidget(main_widget); 344 setWidget(main_widget);
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp
index 8c741f31f..d82e20f86 100644
--- a/src/video_core/command_processor.cpp
+++ b/src/video_core/command_processor.cpp
@@ -35,7 +35,15 @@ static u32 default_attr_write_buffer[3];
35 35
36Common::Profiling::TimingCategory category_drawing("Drawing"); 36Common::Profiling::TimingCategory category_drawing("Drawing");
37 37
38static inline void WritePicaReg(u32 id, u32 value, u32 mask) { 38// Expand a 4-bit mask to 4-byte mask, e.g. 0b0101 -> 0x00FF00FF
39static const u32 expand_bits_to_bytes[] = {
40 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
41 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
42 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
43 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
44};
45
46static void WritePicaReg(u32 id, u32 value, u32 mask) {
39 auto& regs = g_state.regs; 47 auto& regs = g_state.regs;
40 48
41 if (id >= regs.NumIds()) 49 if (id >= regs.NumIds())
@@ -47,13 +55,16 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) {
47 55
48 // TODO: Figure out how register masking acts on e.g. vs.uniform_setup.set_value 56 // TODO: Figure out how register masking acts on e.g. vs.uniform_setup.set_value
49 u32 old_value = regs[id]; 57 u32 old_value = regs[id];
50 regs[id] = (old_value & ~mask) | (value & mask); 58
59 const u32 write_mask = expand_bits_to_bytes[mask];
60
61 regs[id] = (old_value & ~write_mask) | (value & write_mask);
62
63 DebugUtils::OnPicaRegWrite({ (u16)id, (u16)mask, regs[id] });
51 64
52 if (g_debug_context) 65 if (g_debug_context)
53 g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded, reinterpret_cast<void*>(&id)); 66 g_debug_context->OnEvent(DebugContext::Event::PicaCommandLoaded, reinterpret_cast<void*>(&id));
54 67
55 DebugUtils::OnPicaRegWrite(id, regs[id]);
56
57 switch(id) { 68 switch(id) {
58 // Trigger IRQ 69 // Trigger IRQ
59 case PICA_REG_INDEX(trigger_irq): 70 case PICA_REG_INDEX(trigger_irq):
@@ -469,13 +480,6 @@ void ProcessCommandList(const u32* list, u32 size) {
469 g_state.cmd_list.length = size / sizeof(u32); 480 g_state.cmd_list.length = size / sizeof(u32);
470 481
471 while (g_state.cmd_list.current_ptr < g_state.cmd_list.head_ptr + g_state.cmd_list.length) { 482 while (g_state.cmd_list.current_ptr < g_state.cmd_list.head_ptr + g_state.cmd_list.length) {
472 // Expand a 4-bit mask to 4-byte mask, e.g. 0b0101 -> 0x00FF00FF
473 static const u32 expand_bits_to_bytes[] = {
474 0x00000000, 0x000000ff, 0x0000ff00, 0x0000ffff,
475 0x00ff0000, 0x00ff00ff, 0x00ffff00, 0x00ffffff,
476 0xff000000, 0xff0000ff, 0xff00ff00, 0xff00ffff,
477 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff
478 };
479 483
480 // Align read pointer to 8 bytes 484 // Align read pointer to 8 bytes
481 if ((g_state.cmd_list.head_ptr - g_state.cmd_list.current_ptr) % 2 != 0) 485 if ((g_state.cmd_list.head_ptr - g_state.cmd_list.current_ptr) % 2 != 0)
@@ -483,14 +487,13 @@ void ProcessCommandList(const u32* list, u32 size) {
483 487
484 u32 value = *g_state.cmd_list.current_ptr++; 488 u32 value = *g_state.cmd_list.current_ptr++;
485 const CommandHeader header = { *g_state.cmd_list.current_ptr++ }; 489 const CommandHeader header = { *g_state.cmd_list.current_ptr++ };
486 const u32 write_mask = expand_bits_to_bytes[header.parameter_mask];
487 u32 cmd = header.cmd_id; 490 u32 cmd = header.cmd_id;
488 491
489 WritePicaReg(cmd, value, write_mask); 492 WritePicaReg(cmd, value, header.parameter_mask);
490 493
491 for (unsigned i = 0; i < header.extra_data_length; ++i) { 494 for (unsigned i = 0; i < header.extra_data_length; ++i) {
492 u32 cmd = header.cmd_id + (header.group_commands ? i + 1 : 0); 495 u32 cmd = header.cmd_id + (header.group_commands ? i + 1 : 0);
493 WritePicaReg(cmd, *g_state.cmd_list.current_ptr++, write_mask); 496 WritePicaReg(cmd, *g_state.cmd_list.current_ptr++, header.parameter_mask);
494 } 497 }
495 } 498 }
496} 499}
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
index ac071790a..e4b397303 100644
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -64,7 +64,7 @@ void DebugContext::OnEvent(Event event, void* data) {
64 64
65void DebugContext::Resume() { 65void DebugContext::Resume() {
66 { 66 {
67 std::unique_lock<std::mutex> lock(breakpoint_mutex); 67 std::lock_guard<std::mutex> lock(breakpoint_mutex);
68 68
69 // Tell all observers that we are about to resume 69 // Tell all observers that we are about to resume
70 for (auto& breakpoint_observer : breakpoint_observers) { 70 for (auto& breakpoint_observer : breakpoint_observers) {
@@ -312,11 +312,10 @@ void StartPicaTracing()
312 return; 312 return;
313 } 313 }
314 314
315 pica_trace_mutex.lock(); 315 std::lock_guard<std::mutex> lock(pica_trace_mutex);
316 pica_trace = std::unique_ptr<PicaTrace>(new PicaTrace); 316 pica_trace = std::unique_ptr<PicaTrace>(new PicaTrace);
317 317
318 is_pica_tracing = true; 318 is_pica_tracing = true;
319 pica_trace_mutex.unlock();
320} 319}
321 320
322bool IsPicaTracing() 321bool IsPicaTracing()
@@ -324,18 +323,18 @@ bool IsPicaTracing()
324 return is_pica_tracing != 0; 323 return is_pica_tracing != 0;
325} 324}
326 325
327void OnPicaRegWrite(u32 id, u32 value) 326void OnPicaRegWrite(PicaTrace::Write write)
328{ 327{
329 // Double check for is_pica_tracing to avoid pointless locking overhead 328 // Double check for is_pica_tracing to avoid pointless locking overhead
330 if (!is_pica_tracing) 329 if (!is_pica_tracing)
331 return; 330 return;
332 331
333 std::unique_lock<std::mutex> lock(pica_trace_mutex); 332 std::lock_guard<std::mutex> lock(pica_trace_mutex);
334 333
335 if (!is_pica_tracing) 334 if (!is_pica_tracing)
336 return; 335 return;
337 336
338 pica_trace->writes.emplace_back(id, value); 337 pica_trace->writes.push_back(write);
339} 338}
340 339
341std::unique_ptr<PicaTrace> FinishPicaTracing() 340std::unique_ptr<PicaTrace> FinishPicaTracing()
@@ -349,9 +348,9 @@ std::unique_ptr<PicaTrace> FinishPicaTracing()
349 is_pica_tracing = false; 348 is_pica_tracing = false;
350 349
351 // Wait until running tracing is finished 350 // Wait until running tracing is finished
352 pica_trace_mutex.lock(); 351 std::lock_guard<std::mutex> lock(pica_trace_mutex);
353 std::unique_ptr<PicaTrace> ret(std::move(pica_trace)); 352 std::unique_ptr<PicaTrace> ret(std::move(pica_trace));
354 pica_trace_mutex.unlock(); 353
355 return std::move(ret); 354 return std::move(ret);
356} 355}
357 356
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
index 0b30d7ffa..85762f5b4 100644
--- a/src/video_core/debug_utils/debug_utils.h
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -187,21 +187,17 @@ void DumpShader(const std::string& filename, const Regs::ShaderConfig& config,
187 187
188// Utility class to log Pica commands. 188// Utility class to log Pica commands.
189struct PicaTrace { 189struct PicaTrace {
190 struct Write : public std::pair<u32,u32> { 190 struct Write {
191 Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {} 191 u16 cmd_id;
192 192 u16 mask;
193 u32& Id() { return first; } 193 u32 value;
194 const u32& Id() const { return first; }
195
196 u32& Value() { return second; }
197 const u32& Value() const { return second; }
198 }; 194 };
199 std::vector<Write> writes; 195 std::vector<Write> writes;
200}; 196};
201 197
202void StartPicaTracing(); 198void StartPicaTracing();
203bool IsPicaTracing(); 199bool IsPicaTracing();
204void OnPicaRegWrite(u32 id, u32 value); 200void OnPicaRegWrite(PicaTrace::Write write);
205std::unique_ptr<PicaTrace> FinishPicaTracing(); 201std::unique_ptr<PicaTrace> FinishPicaTracing();
206 202
207struct TextureInfo { 203struct TextureInfo {