diff options
| author | 2015-08-16 13:34:45 +0200 | |
|---|---|---|
| committer | 2015-08-16 13:34:45 +0200 | |
| commit | f5144e6c10a5e0e0e6a267ca7ef8451f84194ffd (patch) | |
| tree | e74eb17add0b6e0c33f79b95f95d7561cad7eeae /src | |
| parent | Merge pull request #933 from neobrain/shader_debugger (diff) | |
| parent | citra-qt/debug_utils: Use lock_guard everywhere (diff) | |
| download | yuzu-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.cpp | 42 | ||||
| -rw-r--r-- | src/video_core/command_processor.cpp | 31 | ||||
| -rw-r--r-- | src/video_core/debug_utils/debug_utils.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/debug_utils/debug_utils.h | 14 |
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 | ||
| 177 | int GPUCommandListModel::columnCount(const QModelIndex& parent) const { | 177 | int GPUCommandListModel::columnCount(const QModelIndex& parent) const { |
| 178 | return 3; | 178 | return 4; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | QVariant GPUCommandListModel::data(const QModelIndex& index, int role) const { | 181 | QVariant 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 | ||
| 262 | void GPUCommandListWidget::SetCommandInfo(const QModelIndex& index) { | 264 | void 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 | ||
| 36 | Common::Profiling::TimingCategory category_drawing("Drawing"); | 36 | Common::Profiling::TimingCategory category_drawing("Drawing"); |
| 37 | 37 | ||
| 38 | static inline void WritePicaReg(u32 id, u32 value, u32 mask) { | 38 | // Expand a 4-bit mask to 4-byte mask, e.g. 0b0101 -> 0x00FF00FF |
| 39 | static 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 | |||
| 46 | static 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 | ||
| 65 | void DebugContext::Resume() { | 65 | void 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 | ||
| 322 | bool IsPicaTracing() | 321 | bool IsPicaTracing() |
| @@ -324,18 +323,18 @@ bool IsPicaTracing() | |||
| 324 | return is_pica_tracing != 0; | 323 | return is_pica_tracing != 0; |
| 325 | } | 324 | } |
| 326 | 325 | ||
| 327 | void OnPicaRegWrite(u32 id, u32 value) | 326 | void 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 | ||
| 341 | std::unique_ptr<PicaTrace> FinishPicaTracing() | 340 | std::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. |
| 189 | struct PicaTrace { | 189 | struct 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 | ||
| 202 | void StartPicaTracing(); | 198 | void StartPicaTracing(); |
| 203 | bool IsPicaTracing(); | 199 | bool IsPicaTracing(); |
| 204 | void OnPicaRegWrite(u32 id, u32 value); | 200 | void OnPicaRegWrite(PicaTrace::Write write); |
| 205 | std::unique_ptr<PicaTrace> FinishPicaTracing(); | 201 | std::unique_ptr<PicaTrace> FinishPicaTracing(); |
| 206 | 202 | ||
| 207 | struct TextureInfo { | 203 | struct TextureInfo { |