summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2020-01-02 23:09:31 -0300
committerGravatar ReinUsesLisp2020-01-02 23:09:44 -0300
commit0d6d8129c46f96b2e9f05c592e0d9a6bc3769619 (patch)
tree387e5129419845948ddfc3884be8acd69626f324 /src
parentMerge pull request #3243 from ReinUsesLisp/topologies (diff)
downloadyuzu-0d6d8129c46f96b2e9f05c592e0d9a6bc3769619.tar.gz
yuzu-0d6d8129c46f96b2e9f05c592e0d9a6bc3769619.tar.xz
yuzu-0d6d8129c46f96b2e9f05c592e0d9a6bc3769619.zip
yuzu: Remove Maxwell debugger
This was carried from Citra and wasn't really used on yuzu. It also adds some runtime overhead. This commit removes it from yuzu's codebase.
Diffstat (limited to 'src')
-rw-r--r--src/core/core.cpp10
-rw-r--r--src/core/core.h4
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp49
-rw-r--r--src/video_core/debug_utils/debug_utils.h157
-rw-r--r--src/video_core/engines/maxwell_3d.cpp31
-rw-r--r--src/yuzu/CMakeLists.txt5
-rw-r--r--src/yuzu/debugger/graphics/graphics_breakpoint_observer.cpp27
-rw-r--r--src/yuzu/debugger/graphics/graphics_breakpoint_observer.h33
-rw-r--r--src/yuzu/debugger/graphics/graphics_breakpoints.cpp221
-rw-r--r--src/yuzu/debugger/graphics/graphics_breakpoints.h45
-rw-r--r--src/yuzu/debugger/graphics/graphics_breakpoints_p.h37
-rw-r--r--src/yuzu/main.cpp11
-rw-r--r--src/yuzu/main.h8
14 files changed, 0 insertions, 640 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp
index c45fb960c..d697b80ef 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -46,7 +46,6 @@
46#include "core/settings.h" 46#include "core/settings.h"
47#include "core/telemetry_session.h" 47#include "core/telemetry_session.h"
48#include "core/tools/freezer.h" 48#include "core/tools/freezer.h"
49#include "video_core/debug_utils/debug_utils.h"
50#include "video_core/renderer_base.h" 49#include "video_core/renderer_base.h"
51#include "video_core/video_core.h" 50#include "video_core/video_core.h"
52 51
@@ -341,7 +340,6 @@ struct System::Impl {
341 std::unique_ptr<Loader::AppLoader> app_loader; 340 std::unique_ptr<Loader::AppLoader> app_loader;
342 std::unique_ptr<VideoCore::RendererBase> renderer; 341 std::unique_ptr<VideoCore::RendererBase> renderer;
343 std::unique_ptr<Tegra::GPU> gpu_core; 342 std::unique_ptr<Tegra::GPU> gpu_core;
344 std::shared_ptr<Tegra::DebugContext> debug_context;
345 std::unique_ptr<Hardware::InterruptManager> interrupt_manager; 343 std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
346 Memory::Memory memory; 344 Memory::Memory memory;
347 CpuCoreManager cpu_core_manager; 345 CpuCoreManager cpu_core_manager;
@@ -580,14 +578,6 @@ Loader::AppLoader& System::GetAppLoader() const {
580 return *impl->app_loader; 578 return *impl->app_loader;
581} 579}
582 580
583void System::SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context) {
584 impl->debug_context = std::move(context);
585}
586
587Tegra::DebugContext* System::GetGPUDebugContext() const {
588 return impl->debug_context.get();
589}
590
591void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) { 581void System::SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs) {
592 impl->virtual_filesystem = std::move(vfs); 582 impl->virtual_filesystem = std::move(vfs);
593} 583}
diff --git a/src/core/core.h b/src/core/core.h
index 91184e433..e240c5c58 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -307,10 +307,6 @@ public:
307 Service::SM::ServiceManager& ServiceManager(); 307 Service::SM::ServiceManager& ServiceManager();
308 const Service::SM::ServiceManager& ServiceManager() const; 308 const Service::SM::ServiceManager& ServiceManager() const;
309 309
310 void SetGPUDebugContext(std::shared_ptr<Tegra::DebugContext> context);
311
312 Tegra::DebugContext* GetGPUDebugContext() const;
313
314 void SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs); 310 void SetFilesystem(std::shared_ptr<FileSys::VfsFilesystem> vfs);
315 311
316 std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const; 312 std::shared_ptr<FileSys::VfsFilesystem> GetFilesystem() const;
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 2594cd0bd..65d7b9f93 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -4,8 +4,6 @@ add_library(video_core STATIC
4 buffer_cache/map_interval.h 4 buffer_cache/map_interval.h
5 dma_pusher.cpp 5 dma_pusher.cpp
6 dma_pusher.h 6 dma_pusher.h
7 debug_utils/debug_utils.cpp
8 debug_utils/debug_utils.h
9 engines/const_buffer_engine_interface.h 7 engines/const_buffer_engine_interface.h
10 engines/const_buffer_info.h 8 engines/const_buffer_info.h
11 engines/engine_upload.cpp 9 engines/engine_upload.cpp
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
deleted file mode 100644
index f0ef67535..000000000
--- a/src/video_core/debug_utils/debug_utils.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#include <mutex>
6
7#include "video_core/debug_utils/debug_utils.h"
8
9namespace Tegra {
10
11void DebugContext::DoOnEvent(Event event, void* data) {
12 {
13 std::unique_lock lock{breakpoint_mutex};
14
15 // TODO(Subv): Commit the rasterizer's caches so framebuffers, render targets, etc. will
16 // show on debug widgets
17
18 // TODO: Should stop the CPU thread here once we multithread emulation.
19
20 active_breakpoint = event;
21 at_breakpoint = true;
22
23 // Tell all observers that we hit a breakpoint
24 for (auto& breakpoint_observer : breakpoint_observers) {
25 breakpoint_observer->OnMaxwellBreakPointHit(event, data);
26 }
27
28 // Wait until another thread tells us to Resume()
29 resume_from_breakpoint.wait(lock, [&] { return !at_breakpoint; });
30 }
31}
32
33void DebugContext::Resume() {
34 {
35 std::lock_guard lock{breakpoint_mutex};
36
37 // Tell all observers that we are about to resume
38 for (auto& breakpoint_observer : breakpoint_observers) {
39 breakpoint_observer->OnMaxwellResume();
40 }
41
42 // Resume the waiting thread (i.e. OnEvent())
43 at_breakpoint = false;
44 }
45
46 resume_from_breakpoint.notify_one();
47}
48
49} // namespace Tegra
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
deleted file mode 100644
index ac3a2eb01..000000000
--- a/src/video_core/debug_utils/debug_utils.h
+++ /dev/null
@@ -1,157 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <condition_variable>
9#include <list>
10#include <memory>
11#include <mutex>
12
13namespace Tegra {
14
15class DebugContext {
16public:
17 enum class Event {
18 FirstEvent = 0,
19
20 MaxwellCommandLoaded = FirstEvent,
21 MaxwellCommandProcessed,
22 IncomingPrimitiveBatch,
23 FinishedPrimitiveBatch,
24
25 NumEvents
26 };
27
28 /**
29 * Inherit from this class to be notified of events registered to some debug context.
30 * Most importantly this is used for our debugger GUI.
31 *
32 * To implement event handling, override the OnMaxwellBreakPointHit and OnMaxwellResume methods.
33 * @warning All BreakPointObservers need to be on the same thread to guarantee thread-safe state
34 * access
35 * @todo Evaluate an alternative interface, in which there is only one managing observer and
36 * multiple child observers running (by design) on the same thread.
37 */
38 class BreakPointObserver {
39 public:
40 /// Constructs the object such that it observes events of the given DebugContext.
41 explicit BreakPointObserver(std::shared_ptr<DebugContext> debug_context)
42 : context_weak(debug_context) {
43 std::unique_lock lock{debug_context->breakpoint_mutex};
44 debug_context->breakpoint_observers.push_back(this);
45 }
46
47 virtual ~BreakPointObserver() {
48 auto context = context_weak.lock();
49 if (context) {
50 {
51 std::unique_lock lock{context->breakpoint_mutex};
52 context->breakpoint_observers.remove(this);
53 }
54
55 // If we are the last observer to be destroyed, tell the debugger context that
56 // it is free to continue. In particular, this is required for a proper yuzu
57 // shutdown, when the emulation thread is waiting at a breakpoint.
58 if (context->breakpoint_observers.empty())
59 context->Resume();
60 }
61 }
62
63 /**
64 * Action to perform when a breakpoint was reached.
65 * @param event Type of event which triggered the breakpoint
66 * @param data Optional data pointer (if unused, this is a nullptr)
67 * @note This function will perform nothing unless it is overridden in the child class.
68 */
69 virtual void OnMaxwellBreakPointHit(Event event, void* data) {}
70
71 /**
72 * Action to perform when emulation is resumed from a breakpoint.
73 * @note This function will perform nothing unless it is overridden in the child class.
74 */
75 virtual void OnMaxwellResume() {}
76
77 protected:
78 /**
79 * Weak context pointer. This need not be valid, so when requesting a shared_ptr via
80 * context_weak.lock(), always compare the result against nullptr.
81 */
82 std::weak_ptr<DebugContext> context_weak;
83 };
84
85 /**
86 * Simple structure defining a breakpoint state
87 */
88 struct BreakPoint {
89 bool enabled = false;
90 };
91
92 /**
93 * Static constructor used to create a shared_ptr of a DebugContext.
94 */
95 static std::shared_ptr<DebugContext> Construct() {
96 return std::shared_ptr<DebugContext>(new DebugContext);
97 }
98
99 /**
100 * Used by the emulation core when a given event has happened. If a breakpoint has been set
101 * for this event, OnEvent calls the event handlers of the registered breakpoint observers.
102 * The current thread then is halted until Resume() is called from another thread (or until
103 * emulation is stopped).
104 * @param event Event which has happened
105 * @param data Optional data pointer (pass nullptr if unused). Needs to remain valid until
106 * Resume() is called.
107 */
108 void OnEvent(Event event, void* data) {
109 // This check is left in the header to allow the compiler to inline it.
110 if (!breakpoints[(int)event].enabled)
111 return;
112 // For the rest of event handling, call a separate function.
113 DoOnEvent(event, data);
114 }
115
116 void DoOnEvent(Event event, void* data);
117
118 /**
119 * Resume from the current breakpoint.
120 * @warning Calling this from the same thread that OnEvent was called in will cause a deadlock.
121 * Calling from any other thread is safe.
122 */
123 void Resume();
124
125 /**
126 * Delete all set breakpoints and resume emulation.
127 */
128 void ClearBreakpoints() {
129 for (auto& bp : breakpoints) {
130 bp.enabled = false;
131 }
132 Resume();
133 }
134
135 // TODO: Evaluate if access to these members should be hidden behind a public interface.
136 std::array<BreakPoint, static_cast<int>(Event::NumEvents)> breakpoints;
137 Event active_breakpoint{};
138 bool at_breakpoint = false;
139
140private:
141 /**
142 * Private default constructor to make sure people always construct this through Construct()
143 * instead.
144 */
145 DebugContext() = default;
146
147 /// Mutex protecting current breakpoint state and the observer list.
148 std::mutex breakpoint_mutex;
149
150 /// Used by OnEvent to wait for resumption.
151 std::condition_variable resume_from_breakpoint;
152
153 /// List of registered observers
154 std::list<BreakPointObserver*> breakpoint_observers;
155};
156
157} // namespace Tegra
diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp
index e1cb8b0b0..1d1f780e7 100644
--- a/src/video_core/engines/maxwell_3d.cpp
+++ b/src/video_core/engines/maxwell_3d.cpp
@@ -7,7 +7,6 @@
7#include "common/assert.h" 7#include "common/assert.h"
8#include "core/core.h" 8#include "core/core.h"
9#include "core/core_timing.h" 9#include "core/core_timing.h"
10#include "video_core/debug_utils/debug_utils.h"
11#include "video_core/engines/maxwell_3d.h" 10#include "video_core/engines/maxwell_3d.h"
12#include "video_core/engines/shader_type.h" 11#include "video_core/engines/shader_type.h"
13#include "video_core/memory_manager.h" 12#include "video_core/memory_manager.h"
@@ -273,8 +272,6 @@ void Maxwell3D::CallMacroMethod(u32 method, std::size_t num_parameters, const u3
273} 272}
274 273
275void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { 274void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
276 auto debug_context = system.GetGPUDebugContext();
277
278 const u32 method = method_call.method; 275 const u32 method = method_call.method;
279 276
280 if (method == cb_data_state.current) { 277 if (method == cb_data_state.current) {
@@ -315,10 +312,6 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
315 ASSERT_MSG(method < Regs::NUM_REGS, 312 ASSERT_MSG(method < Regs::NUM_REGS,
316 "Invalid Maxwell3D register, increase the size of the Regs structure"); 313 "Invalid Maxwell3D register, increase the size of the Regs structure");
317 314
318 if (debug_context) {
319 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandLoaded, nullptr);
320 }
321
322 if (regs.reg_array[method] != method_call.argument) { 315 if (regs.reg_array[method] != method_call.argument) {
323 regs.reg_array[method] = method_call.argument; 316 regs.reg_array[method] = method_call.argument;
324 const std::size_t dirty_reg = dirty_pointers[method]; 317 const std::size_t dirty_reg = dirty_pointers[method];
@@ -424,10 +417,6 @@ void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) {
424 default: 417 default:
425 break; 418 break;
426 } 419 }
427
428 if (debug_context) {
429 debug_context->OnEvent(Tegra::DebugContext::Event::MaxwellCommandProcessed, nullptr);
430 }
431} 420}
432 421
433void Maxwell3D::StepInstance(const MMEDrawMode expected_mode, const u32 count) { 422void Maxwell3D::StepInstance(const MMEDrawMode expected_mode, const u32 count) {
@@ -485,12 +474,6 @@ void Maxwell3D::FlushMMEInlineDraw() {
485 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?"); 474 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
486 ASSERT(mme_draw.instance_count == mme_draw.gl_end_count); 475 ASSERT(mme_draw.instance_count == mme_draw.gl_end_count);
487 476
488 auto debug_context = system.GetGPUDebugContext();
489
490 if (debug_context) {
491 debug_context->OnEvent(Tegra::DebugContext::Event::IncomingPrimitiveBatch, nullptr);
492 }
493
494 // Both instance configuration registers can not be set at the same time. 477 // Both instance configuration registers can not be set at the same time.
495 ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont, 478 ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
496 "Illegal combination of instancing parameters"); 479 "Illegal combination of instancing parameters");
@@ -500,10 +483,6 @@ void Maxwell3D::FlushMMEInlineDraw() {
500 rasterizer.DrawMultiBatch(is_indexed); 483 rasterizer.DrawMultiBatch(is_indexed);
501 } 484 }
502 485
503 if (debug_context) {
504 debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr);
505 }
506
507 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if 486 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
508 // the game is trying to draw indexed or direct mode. This needs to be verified on HW still - 487 // the game is trying to draw indexed or direct mode. This needs to be verified on HW still -
509 // it's possible that it is incorrect and that there is some other register used to specify the 488 // it's possible that it is incorrect and that there is some other register used to specify the
@@ -650,12 +629,6 @@ void Maxwell3D::DrawArrays() {
650 regs.vertex_buffer.count); 629 regs.vertex_buffer.count);
651 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?"); 630 ASSERT_MSG(!(regs.index_array.count && regs.vertex_buffer.count), "Both indexed and direct?");
652 631
653 auto debug_context = system.GetGPUDebugContext();
654
655 if (debug_context) {
656 debug_context->OnEvent(Tegra::DebugContext::Event::IncomingPrimitiveBatch, nullptr);
657 }
658
659 // Both instance configuration registers can not be set at the same time. 632 // Both instance configuration registers can not be set at the same time.
660 ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont, 633 ASSERT_MSG(!regs.draw.instance_next || !regs.draw.instance_cont,
661 "Illegal combination of instancing parameters"); 634 "Illegal combination of instancing parameters");
@@ -673,10 +646,6 @@ void Maxwell3D::DrawArrays() {
673 rasterizer.DrawBatch(is_indexed); 646 rasterizer.DrawBatch(is_indexed);
674 } 647 }
675 648
676 if (debug_context) {
677 debug_context->OnEvent(Tegra::DebugContext::Event::FinishedPrimitiveBatch, nullptr);
678 }
679
680 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if 649 // TODO(bunnei): Below, we reset vertex count so that we can use these registers to determine if
681 // the game is trying to draw indexed or direct mode. This needs to be verified on HW still - 650 // the game is trying to draw indexed or direct mode. This needs to be verified on HW still -
682 // it's possible that it is incorrect and that there is some other register used to specify the 651 // it's possible that it is incorrect and that there is some other register used to specify the
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index ff1c1d985..11ae1e66e 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -78,11 +78,6 @@ add_executable(yuzu
78 configuration/configure_web.cpp 78 configuration/configure_web.cpp
79 configuration/configure_web.h 79 configuration/configure_web.h
80 configuration/configure_web.ui 80 configuration/configure_web.ui
81 debugger/graphics/graphics_breakpoint_observer.cpp
82 debugger/graphics/graphics_breakpoint_observer.h
83 debugger/graphics/graphics_breakpoints.cpp
84 debugger/graphics/graphics_breakpoints.h
85 debugger/graphics/graphics_breakpoints_p.h
86 debugger/console.cpp 81 debugger/console.cpp
87 debugger/console.h 82 debugger/console.h
88 debugger/profiler.cpp 83 debugger/profiler.cpp
diff --git a/src/yuzu/debugger/graphics/graphics_breakpoint_observer.cpp b/src/yuzu/debugger/graphics/graphics_breakpoint_observer.cpp
deleted file mode 100644
index 5f459ccfb..000000000
--- a/src/yuzu/debugger/graphics/graphics_breakpoint_observer.cpp
+++ /dev/null
@@ -1,27 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QMetaType>
6#include "yuzu/debugger/graphics/graphics_breakpoint_observer.h"
7
8BreakPointObserverDock::BreakPointObserverDock(std::shared_ptr<Tegra::DebugContext> debug_context,
9 const QString& title, QWidget* parent)
10 : QDockWidget(title, parent), BreakPointObserver(debug_context) {
11 qRegisterMetaType<Tegra::DebugContext::Event>("Tegra::DebugContext::Event");
12
13 connect(this, &BreakPointObserverDock::Resumed, this, &BreakPointObserverDock::OnResumed);
14
15 // NOTE: This signal is emitted from a non-GUI thread, but connect() takes
16 // care of delaying its handling to the GUI thread.
17 connect(this, &BreakPointObserverDock::BreakPointHit, this,
18 &BreakPointObserverDock::OnBreakPointHit, Qt::BlockingQueuedConnection);
19}
20
21void BreakPointObserverDock::OnMaxwellBreakPointHit(Tegra::DebugContext::Event event, void* data) {
22 emit BreakPointHit(event, data);
23}
24
25void BreakPointObserverDock::OnMaxwellResume() {
26 emit Resumed();
27}
diff --git a/src/yuzu/debugger/graphics/graphics_breakpoint_observer.h b/src/yuzu/debugger/graphics/graphics_breakpoint_observer.h
deleted file mode 100644
index ab32f0115..000000000
--- a/src/yuzu/debugger/graphics/graphics_breakpoint_observer.h
+++ /dev/null
@@ -1,33 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <QDockWidget>
8#include "video_core/debug_utils/debug_utils.h"
9
10/**
11 * Utility class which forwards calls to OnMaxwellBreakPointHit and OnMaxwellResume to public slots.
12 * This is because the Maxwell breakpoint callbacks are called from a non-GUI thread, while
13 * the widget usually wants to perform reactions in the GUI thread.
14 */
15class BreakPointObserverDock : public QDockWidget,
16 protected Tegra::DebugContext::BreakPointObserver {
17 Q_OBJECT
18
19public:
20 BreakPointObserverDock(std::shared_ptr<Tegra::DebugContext> debug_context, const QString& title,
21 QWidget* parent = nullptr);
22
23 void OnMaxwellBreakPointHit(Tegra::DebugContext::Event event, void* data) override;
24 void OnMaxwellResume() override;
25
26signals:
27 void Resumed();
28 void BreakPointHit(Tegra::DebugContext::Event event, void* data);
29
30private:
31 virtual void OnBreakPointHit(Tegra::DebugContext::Event event, void* data) = 0;
32 virtual void OnResumed() = 0;
33};
diff --git a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp b/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
deleted file mode 100644
index 1c80082a4..000000000
--- a/src/yuzu/debugger/graphics/graphics_breakpoints.cpp
+++ /dev/null
@@ -1,221 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <QLabel>
6#include <QMetaType>
7#include <QPushButton>
8#include <QTreeView>
9#include <QVBoxLayout>
10#include "common/assert.h"
11#include "yuzu/debugger/graphics/graphics_breakpoints.h"
12#include "yuzu/debugger/graphics/graphics_breakpoints_p.h"
13
14BreakPointModel::BreakPointModel(std::shared_ptr<Tegra::DebugContext> debug_context,
15 QObject* parent)
16 : QAbstractListModel(parent), context_weak(debug_context),
17 at_breakpoint(debug_context->at_breakpoint),
18 active_breakpoint(debug_context->active_breakpoint) {}
19
20int BreakPointModel::columnCount(const QModelIndex& parent) const {
21 return 1;
22}
23
24int BreakPointModel::rowCount(const QModelIndex& parent) const {
25 return static_cast<int>(Tegra::DebugContext::Event::NumEvents);
26}
27
28QVariant BreakPointModel::data(const QModelIndex& index, int role) const {
29 const auto event = static_cast<Tegra::DebugContext::Event>(index.row());
30
31 switch (role) {
32 case Qt::DisplayRole: {
33 if (index.column() == 0) {
34 return DebugContextEventToString(event);
35 }
36 break;
37 }
38
39 case Qt::CheckStateRole: {
40 if (index.column() == 0)
41 return data(index, Role_IsEnabled).toBool() ? Qt::Checked : Qt::Unchecked;
42 break;
43 }
44
45 case Qt::BackgroundRole: {
46 if (at_breakpoint && index.row() == static_cast<int>(active_breakpoint)) {
47 return QBrush(QColor(0xE0, 0xE0, 0x10));
48 }
49 break;
50 }
51
52 case Role_IsEnabled: {
53 auto context = context_weak.lock();
54 return context && context->breakpoints[(int)event].enabled;
55 }
56
57 default:
58 break;
59 }
60 return QVariant();
61}
62
63Qt::ItemFlags BreakPointModel::flags(const QModelIndex& index) const {
64 if (!index.isValid())
65 return 0;
66
67 Qt::ItemFlags flags = Qt::ItemIsEnabled;
68 if (index.column() == 0)
69 flags |= Qt::ItemIsUserCheckable;
70 return flags;
71}
72
73bool BreakPointModel::setData(const QModelIndex& index, const QVariant& value, int role) {
74 const auto event = static_cast<Tegra::DebugContext::Event>(index.row());
75
76 switch (role) {
77 case Qt::CheckStateRole: {
78 if (index.column() != 0)
79 return false;
80
81 auto context = context_weak.lock();
82 if (!context)
83 return false;
84
85 context->breakpoints[(int)event].enabled = value == Qt::Checked;
86 QModelIndex changed_index = createIndex(index.row(), 0);
87 emit dataChanged(changed_index, changed_index);
88 return true;
89 }
90 }
91
92 return false;
93}
94
95void BreakPointModel::OnBreakPointHit(Tegra::DebugContext::Event event) {
96 auto context = context_weak.lock();
97 if (!context)
98 return;
99
100 active_breakpoint = context->active_breakpoint;
101 at_breakpoint = context->at_breakpoint;
102 emit dataChanged(createIndex(static_cast<int>(event), 0),
103 createIndex(static_cast<int>(event), 0));
104}
105
106void BreakPointModel::OnResumed() {
107 auto context = context_weak.lock();
108 if (!context)
109 return;
110
111 at_breakpoint = context->at_breakpoint;
112 emit dataChanged(createIndex(static_cast<int>(active_breakpoint), 0),
113 createIndex(static_cast<int>(active_breakpoint), 0));
114 active_breakpoint = context->active_breakpoint;
115}
116
117QString BreakPointModel::DebugContextEventToString(Tegra::DebugContext::Event event) {
118 switch (event) {
119 case Tegra::DebugContext::Event::MaxwellCommandLoaded:
120 return tr("Maxwell command loaded");
121 case Tegra::DebugContext::Event::MaxwellCommandProcessed:
122 return tr("Maxwell command processed");
123 case Tegra::DebugContext::Event::IncomingPrimitiveBatch:
124 return tr("Incoming primitive batch");
125 case Tegra::DebugContext::Event::FinishedPrimitiveBatch:
126 return tr("Finished primitive batch");
127 case Tegra::DebugContext::Event::NumEvents:
128 break;
129 }
130
131 return tr("Unknown debug context event");
132}
133
134GraphicsBreakPointsWidget::GraphicsBreakPointsWidget(
135 std::shared_ptr<Tegra::DebugContext> debug_context, QWidget* parent)
136 : QDockWidget(tr("Maxwell Breakpoints"), parent), Tegra::DebugContext::BreakPointObserver(
137 debug_context) {
138 setObjectName(QStringLiteral("TegraBreakPointsWidget"));
139
140 status_text = new QLabel(tr("Emulation running"));
141 resume_button = new QPushButton(tr("Resume"));
142 resume_button->setEnabled(false);
143
144 breakpoint_model = new BreakPointModel(debug_context, this);
145 breakpoint_list = new QTreeView;
146 breakpoint_list->setRootIsDecorated(false);
147 breakpoint_list->setHeaderHidden(true);
148 breakpoint_list->setModel(breakpoint_model);
149
150 qRegisterMetaType<Tegra::DebugContext::Event>("Tegra::DebugContext::Event");
151
152 connect(breakpoint_list, &QTreeView::doubleClicked, this,
153 &GraphicsBreakPointsWidget::OnItemDoubleClicked);
154
155 connect(resume_button, &QPushButton::clicked, this,
156 &GraphicsBreakPointsWidget::OnResumeRequested);
157
158 connect(this, &GraphicsBreakPointsWidget::BreakPointHit, this,
159 &GraphicsBreakPointsWidget::OnBreakPointHit, Qt::BlockingQueuedConnection);
160 connect(this, &GraphicsBreakPointsWidget::Resumed, this, &GraphicsBreakPointsWidget::OnResumed);
161
162 connect(this, &GraphicsBreakPointsWidget::BreakPointHit, breakpoint_model,
163 &BreakPointModel::OnBreakPointHit, Qt::BlockingQueuedConnection);
164 connect(this, &GraphicsBreakPointsWidget::Resumed, breakpoint_model,
165 &BreakPointModel::OnResumed);
166
167 connect(this, &GraphicsBreakPointsWidget::BreakPointsChanged,
168 [this](const QModelIndex& top_left, const QModelIndex& bottom_right) {
169 breakpoint_model->dataChanged(top_left, bottom_right);
170 });
171
172 QWidget* main_widget = new QWidget;
173 auto main_layout = new QVBoxLayout;
174 {
175 auto sub_layout = new QHBoxLayout;
176 sub_layout->addWidget(status_text);
177 sub_layout->addWidget(resume_button);
178 main_layout->addLayout(sub_layout);
179 }
180 main_layout->addWidget(breakpoint_list);
181 main_widget->setLayout(main_layout);
182
183 setWidget(main_widget);
184}
185
186void GraphicsBreakPointsWidget::OnMaxwellBreakPointHit(Event event, void* data) {
187 // Process in GUI thread
188 emit BreakPointHit(event, data);
189}
190
191void GraphicsBreakPointsWidget::OnBreakPointHit(Tegra::DebugContext::Event event, void* data) {
192 status_text->setText(tr("Emulation halted at breakpoint"));
193 resume_button->setEnabled(true);
194}
195
196void GraphicsBreakPointsWidget::OnMaxwellResume() {
197 // Process in GUI thread
198 emit Resumed();
199}
200
201void GraphicsBreakPointsWidget::OnResumed() {
202 status_text->setText(tr("Emulation running"));
203 resume_button->setEnabled(false);
204}
205
206void GraphicsBreakPointsWidget::OnResumeRequested() {
207 if (auto context = context_weak.lock())
208 context->Resume();
209}
210
211void GraphicsBreakPointsWidget::OnItemDoubleClicked(const QModelIndex& index) {
212 if (!index.isValid())
213 return;
214
215 QModelIndex check_index = breakpoint_list->model()->index(index.row(), 0);
216 QVariant enabled = breakpoint_list->model()->data(check_index, Qt::CheckStateRole);
217 QVariant new_state = Qt::Unchecked;
218 if (enabled == Qt::Unchecked)
219 new_state = Qt::Checked;
220 breakpoint_list->model()->setData(check_index, new_state, Qt::CheckStateRole);
221}
diff --git a/src/yuzu/debugger/graphics/graphics_breakpoints.h b/src/yuzu/debugger/graphics/graphics_breakpoints.h
deleted file mode 100644
index a920a2ae5..000000000
--- a/src/yuzu/debugger/graphics/graphics_breakpoints.h
+++ /dev/null
@@ -1,45 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <QDockWidget>
9#include "video_core/debug_utils/debug_utils.h"
10
11class QLabel;
12class QPushButton;
13class QTreeView;
14
15class BreakPointModel;
16
17class GraphicsBreakPointsWidget : public QDockWidget, Tegra::DebugContext::BreakPointObserver {
18 Q_OBJECT
19
20 using Event = Tegra::DebugContext::Event;
21
22public:
23 explicit GraphicsBreakPointsWidget(std::shared_ptr<Tegra::DebugContext> debug_context,
24 QWidget* parent = nullptr);
25
26 void OnMaxwellBreakPointHit(Tegra::DebugContext::Event event, void* data) override;
27 void OnMaxwellResume() override;
28
29signals:
30 void Resumed();
31 void BreakPointHit(Tegra::DebugContext::Event event, void* data);
32 void BreakPointsChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
33
34private:
35 void OnBreakPointHit(Tegra::DebugContext::Event event, void* data);
36 void OnItemDoubleClicked(const QModelIndex&);
37 void OnResumeRequested();
38 void OnResumed();
39
40 QLabel* status_text;
41 QPushButton* resume_button;
42
43 BreakPointModel* breakpoint_model;
44 QTreeView* breakpoint_list;
45};
diff --git a/src/yuzu/debugger/graphics/graphics_breakpoints_p.h b/src/yuzu/debugger/graphics/graphics_breakpoints_p.h
deleted file mode 100644
index fb488e38f..000000000
--- a/src/yuzu/debugger/graphics/graphics_breakpoints_p.h
+++ /dev/null
@@ -1,37 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <QAbstractListModel>
9#include "video_core/debug_utils/debug_utils.h"
10
11class BreakPointModel : public QAbstractListModel {
12 Q_OBJECT
13
14public:
15 enum {
16 Role_IsEnabled = Qt::UserRole,
17 };
18
19 BreakPointModel(std::shared_ptr<Tegra::DebugContext> context, QObject* parent);
20
21 int columnCount(const QModelIndex& parent = QModelIndex()) const override;
22 int rowCount(const QModelIndex& parent = QModelIndex()) const override;
23 QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
24 Qt::ItemFlags flags(const QModelIndex& index) const override;
25
26 bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole) override;
27
28 void OnBreakPointHit(Tegra::DebugContext::Event event);
29 void OnResumed();
30
31private:
32 static QString DebugContextEventToString(Tegra::DebugContext::Event event);
33
34 std::weak_ptr<Tegra::DebugContext> context_weak;
35 bool at_breakpoint;
36 Tegra::DebugContext::Event active_breakpoint;
37};
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index 867f8e913..b21fbf826 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -93,7 +93,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
93#include "core/perf_stats.h" 93#include "core/perf_stats.h"
94#include "core/settings.h" 94#include "core/settings.h"
95#include "core/telemetry_session.h" 95#include "core/telemetry_session.h"
96#include "video_core/debug_utils/debug_utils.h"
97#include "yuzu/about_dialog.h" 96#include "yuzu/about_dialog.h"
98#include "yuzu/bootmanager.h" 97#include "yuzu/bootmanager.h"
99#include "yuzu/compatdb.h" 98#include "yuzu/compatdb.h"
@@ -101,7 +100,6 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
101#include "yuzu/configuration/config.h" 100#include "yuzu/configuration/config.h"
102#include "yuzu/configuration/configure_dialog.h" 101#include "yuzu/configuration/configure_dialog.h"
103#include "yuzu/debugger/console.h" 102#include "yuzu/debugger/console.h"
104#include "yuzu/debugger/graphics/graphics_breakpoints.h"
105#include "yuzu/debugger/profiler.h" 103#include "yuzu/debugger/profiler.h"
106#include "yuzu/debugger/wait_tree.h" 104#include "yuzu/debugger/wait_tree.h"
107#include "yuzu/discord.h" 105#include "yuzu/discord.h"
@@ -187,8 +185,6 @@ GMainWindow::GMainWindow()
187 provider(std::make_unique<FileSys::ManualContentProvider>()) { 185 provider(std::make_unique<FileSys::ManualContentProvider>()) {
188 InitializeLogging(); 186 InitializeLogging();
189 187
190 debug_context = Tegra::DebugContext::Construct();
191
192 setAcceptDrops(true); 188 setAcceptDrops(true);
193 ui.setupUi(this); 189 ui.setupUi(this);
194 statusBar()->hide(); 190 statusBar()->hide();
@@ -495,11 +491,6 @@ void GMainWindow::InitializeDebugWidgets() {
495 debug_menu->addAction(microProfileDialog->toggleViewAction()); 491 debug_menu->addAction(microProfileDialog->toggleViewAction());
496#endif 492#endif
497 493
498 graphicsBreakpointsWidget = new GraphicsBreakPointsWidget(debug_context, this);
499 addDockWidget(Qt::RightDockWidgetArea, graphicsBreakpointsWidget);
500 graphicsBreakpointsWidget->hide();
501 debug_menu->addAction(graphicsBreakpointsWidget->toggleViewAction());
502
503 waitTreeWidget = new WaitTreeWidget(this); 494 waitTreeWidget = new WaitTreeWidget(this);
504 addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget); 495 addDockWidget(Qt::LeftDockWidgetArea, waitTreeWidget);
505 waitTreeWidget->hide(); 496 waitTreeWidget->hide();
@@ -869,8 +860,6 @@ bool GMainWindow::LoadROM(const QString& filename) {
869 Core::System& system{Core::System::GetInstance()}; 860 Core::System& system{Core::System::GetInstance()};
870 system.SetFilesystem(vfs); 861 system.SetFilesystem(vfs);
871 862
872 system.SetGPUDebugContext(debug_context);
873
874 system.SetAppletFrontendSet({ 863 system.SetAppletFrontendSet({
875 nullptr, // Parental Controls 864 nullptr, // Parental Controls
876 std::make_unique<QtErrorDisplay>(*this), // 865 std::make_unique<QtErrorDisplay>(*this), //
diff --git a/src/yuzu/main.h b/src/yuzu/main.h
index 7f46bea2b..a56f9a981 100644
--- a/src/yuzu/main.h
+++ b/src/yuzu/main.h
@@ -22,7 +22,6 @@ class Config;
22class EmuThread; 22class EmuThread;
23class GameList; 23class GameList;
24class GImageInfo; 24class GImageInfo;
25class GraphicsBreakPointsWidget;
26class GRenderWindow; 25class GRenderWindow;
27class LoadingScreen; 26class LoadingScreen;
28class MicroProfileDialog; 27class MicroProfileDialog;
@@ -42,10 +41,6 @@ class ManualContentProvider;
42class VfsFilesystem; 41class VfsFilesystem;
43} // namespace FileSys 42} // namespace FileSys
44 43
45namespace Tegra {
46class DebugContext;
47}
48
49enum class EmulatedDirectoryTarget { 44enum class EmulatedDirectoryTarget {
50 NAND, 45 NAND,
51 SDMC, 46 SDMC,
@@ -223,8 +218,6 @@ private:
223 218
224 Ui::MainWindow ui; 219 Ui::MainWindow ui;
225 220
226 std::shared_ptr<Tegra::DebugContext> debug_context;
227
228 GRenderWindow* render_window; 221 GRenderWindow* render_window;
229 GameList* game_list; 222 GameList* game_list;
230 LoadingScreen* loading_screen; 223 LoadingScreen* loading_screen;
@@ -255,7 +248,6 @@ private:
255 // Debugger panes 248 // Debugger panes
256 ProfilerWidget* profilerWidget; 249 ProfilerWidget* profilerWidget;
257 MicroProfileDialog* microProfileDialog; 250 MicroProfileDialog* microProfileDialog;
258 GraphicsBreakPointsWidget* graphicsBreakpointsWidget;
259 WaitTreeWidget* waitTreeWidget; 251 WaitTreeWidget* waitTreeWidget;
260 252
261 QAction* actions_recent_files[max_recent_files_item]; 253 QAction* actions_recent_files[max_recent_files_item];