diff options
| author | 2020-01-02 22:03:30 -0500 | |
|---|---|---|
| committer | 2020-01-02 22:03:30 -0500 | |
| commit | c332c66eb206ccd68b5826c91e5f5fba1cf442e7 (patch) | |
| tree | 387e5129419845948ddfc3884be8acd69626f324 /src/video_core | |
| parent | Merge pull request #3243 from ReinUsesLisp/topologies (diff) | |
| parent | yuzu: Remove Maxwell debugger (diff) | |
| download | yuzu-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.txt | 2 | ||||
| -rw-r--r-- | src/video_core/debug_utils/debug_utils.cpp | 49 | ||||
| -rw-r--r-- | src/video_core/debug_utils/debug_utils.h | 157 | ||||
| -rw-r--r-- | src/video_core/engines/maxwell_3d.cpp | 31 |
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 | |||
| 9 | namespace Tegra { | ||
| 10 | |||
| 11 | void 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 | |||
| 33 | void 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 | |||
| 13 | namespace Tegra { | ||
| 14 | |||
| 15 | class DebugContext { | ||
| 16 | public: | ||
| 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 | |||
| 140 | private: | ||
| 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 | ||
| 275 | void Maxwell3D::CallMethod(const GPU::MethodCall& method_call) { | 274 | void 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 | ||
| 433 | void Maxwell3D::StepInstance(const MMEDrawMode expected_mode, const u32 count) { | 422 | void 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 |