summaryrefslogtreecommitdiff
path: root/src/video_core
diff options
context:
space:
mode:
authorGravatar bunnei2020-01-02 22:03:30 -0500
committerGravatar GitHub2020-01-02 22:03:30 -0500
commitc332c66eb206ccd68b5826c91e5f5fba1cf442e7 (patch)
tree387e5129419845948ddfc3884be8acd69626f324 /src/video_core
parentMerge pull request #3243 from ReinUsesLisp/topologies (diff)
parentyuzu: Remove Maxwell debugger (diff)
downloadyuzu-c332c66eb206ccd68b5826c91e5f5fba1cf442e7.tar.gz
yuzu-c332c66eb206ccd68b5826c91e5f5fba1cf442e7.tar.xz
yuzu-c332c66eb206ccd68b5826c91e5f5fba1cf442e7.zip
Merge pull request #3267 from ReinUsesLisp/remove-maxwell-debugger
yuzu: Remove Maxwell debugger
Diffstat (limited to 'src/video_core')
-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
4 files changed, 0 insertions, 239 deletions
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