summaryrefslogtreecommitdiffstats
path: root/src/video_core
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2018-03-22 21:19:35 +0100
committerSubv <subv2112@gmail.com>2018-03-24 17:31:49 +0100
commit77fd0d47e70968bcbc87a3b5607cd29e6211f656 (patch)
tree54e91cede780bbd5bec2612547a61bdd799e36af /src/video_core
parentGPU: Added a method to unswizzle a texture without decoding it. (diff)
downloadyuzu-77fd0d47e70968bcbc87a3b5607cd29e6211f656.tar
yuzu-77fd0d47e70968bcbc87a3b5607cd29e6211f656.tar.gz
yuzu-77fd0d47e70968bcbc87a3b5607cd29e6211f656.tar.bz2
yuzu-77fd0d47e70968bcbc87a3b5607cd29e6211f656.tar.lz
yuzu-77fd0d47e70968bcbc87a3b5607cd29e6211f656.tar.xz
yuzu-77fd0d47e70968bcbc87a3b5607cd29e6211f656.tar.zst
yuzu-77fd0d47e70968bcbc87a3b5607cd29e6211f656.zip
Diffstat (limited to 'src/video_core')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/debug_utils/debug_utils.cpp66
-rw-r--r--src/video_core/debug_utils/debug_utils.h165
-rw-r--r--src/video_core/gpu.cpp4
-rw-r--r--src/video_core/gpu.h5
5 files changed, 242 insertions, 0 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 8c0e6663b..3dab81769 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -1,6 +1,8 @@
add_library(video_core STATIC
command_processor.cpp
command_processor.h
+ debug_utils/debug_utils.cpp
+ debug_utils/debug_utils.h
engines/fermi_2d.cpp
engines/fermi_2d.h
engines/maxwell_3d.cpp
diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp
new file mode 100644
index 000000000..73fd4d7a3
--- /dev/null
+++ b/src/video_core/debug_utils/debug_utils.cpp
@@ -0,0 +1,66 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <condition_variable>
+#include <cstdint>
+#include <cstring>
+#include <fstream>
+#include <map>
+#include <mutex>
+#include <string>
+
+#include "common/assert.h"
+#include "common/bit_field.h"
+#include "common/color.h"
+#include "common/common_types.h"
+#include "common/file_util.h"
+#include "common/logging/log.h"
+#include "common/math_util.h"
+#include "common/vector_math.h"
+#include "video_core/debug_utils/debug_utils.h"
+
+namespace Tegra {
+
+std::shared_ptr<DebugContext> g_debug_context;
+
+void DebugContext::DoOnEvent(Event event, void* data) {
+ {
+ std::unique_lock<std::mutex> lock(breakpoint_mutex);
+
+ // TODO(Subv): Commit the rasterizer's caches so framebuffers, render targets, etc. will
+ // show on debug widgets
+
+ // TODO: Should stop the CPU thread here once we multithread emulation.
+
+ active_breakpoint = event;
+ at_breakpoint = true;
+
+ // Tell all observers that we hit a breakpoint
+ for (auto& breakpoint_observer : breakpoint_observers) {
+ breakpoint_observer->OnMaxwellBreakPointHit(event, data);
+ }
+
+ // Wait until another thread tells us to Resume()
+ resume_from_breakpoint.wait(lock, [&] { return !at_breakpoint; });
+ }
+}
+
+void DebugContext::Resume() {
+ {
+ std::lock_guard<std::mutex> lock(breakpoint_mutex);
+
+ // Tell all observers that we are about to resume
+ for (auto& breakpoint_observer : breakpoint_observers) {
+ breakpoint_observer->OnMaxwellResume();
+ }
+
+ // Resume the waiting thread (i.e. OnEvent())
+ at_breakpoint = false;
+ }
+
+ resume_from_breakpoint.notify_one();
+}
+
+} // namespace Tegra
diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h
new file mode 100644
index 000000000..98461d6d9
--- /dev/null
+++ b/src/video_core/debug_utils/debug_utils.h
@@ -0,0 +1,165 @@
+// Copyright 2014 Citra Emulator Project
+// Licensed under GPLv2
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <algorithm>
+#include <array>
+#include <condition_variable>
+#include <iterator>
+#include <list>
+#include <map>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <utility>
+#include <vector>
+#include "common/common_types.h"
+#include "common/vector_math.h"
+
+namespace Tegra {
+
+class DebugContext {
+public:
+ enum class Event {
+ FirstEvent = 0,
+
+ MaxwellCommandLoaded = FirstEvent,
+ MaxwellCommandProcessed,
+ IncomingPrimitiveBatch,
+ FinishedPrimitiveBatch,
+
+ NumEvents
+ };
+
+ /**
+ * Inherit from this class to be notified of events registered to some debug context.
+ * Most importantly this is used for our debugger GUI.
+ *
+ * To implement event handling, override the OnMaxwellBreakPointHit and OnMaxwellResume methods.
+ * @warning All BreakPointObservers need to be on the same thread to guarantee thread-safe state
+ * access
+ * @todo Evaluate an alternative interface, in which there is only one managing observer and
+ * multiple child observers running (by design) on the same thread.
+ */
+ class BreakPointObserver {
+ public:
+ /// Constructs the object such that it observes events of the given DebugContext.
+ BreakPointObserver(std::shared_ptr<DebugContext> debug_context)
+ : context_weak(debug_context) {
+ std::unique_lock<std::mutex> lock(debug_context->breakpoint_mutex);
+ debug_context->breakpoint_observers.push_back(this);
+ }
+
+ virtual ~BreakPointObserver() {
+ auto context = context_weak.lock();
+ if (context) {
+ std::unique_lock<std::mutex> lock(context->breakpoint_mutex);
+ context->breakpoint_observers.remove(this);
+
+ // If we are the last observer to be destroyed, tell the debugger context that
+ // it is free to continue. In particular, this is required for a proper yuzu
+ // shutdown, when the emulation thread is waiting at a breakpoint.
+ if (context->breakpoint_observers.empty())
+ context->Resume();
+ }
+ }
+
+ /**
+ * Action to perform when a breakpoint was reached.
+ * @param event Type of event which triggered the breakpoint
+ * @param data Optional data pointer (if unused, this is a nullptr)
+ * @note This function will perform nothing unless it is overridden in the child class.
+ */
+ virtual void OnMaxwellBreakPointHit(Event event, void* data) {}
+
+ /**
+ * Action to perform when emulation is resumed from a breakpoint.
+ * @note This function will perform nothing unless it is overridden in the child class.
+ */
+ virtual void OnMaxwellResume() {}
+
+ protected:
+ /**
+ * Weak context pointer. This need not be valid, so when requesting a shared_ptr via
+ * context_weak.lock(), always compare the result against nullptr.
+ */
+ std::weak_ptr<DebugContext> context_weak;
+ };
+
+ /**
+ * Simple structure defining a breakpoint state
+ */
+ struct BreakPoint {
+ bool enabled = false;
+ };
+
+ /**
+ * Static constructor used to create a shared_ptr of a DebugContext.
+ */
+ static std::shared_ptr<DebugContext> Construct() {
+ return std::shared_ptr<DebugContext>(new DebugContext);
+ }
+
+ /**
+ * Used by the emulation core when a given event has happened. If a breakpoint has been set
+ * for this event, OnEvent calls the event handlers of the registered breakpoint observers.
+ * The current thread then is halted until Resume() is called from another thread (or until
+ * emulation is stopped).
+ * @param event Event which has happened
+ * @param data Optional data pointer (pass nullptr if unused). Needs to remain valid until
+ * Resume() is called.
+ */
+ void OnEvent(Event event, void* data) {
+ // This check is left in the header to allow the compiler to inline it.
+ if (!breakpoints[(int)event].enabled)
+ return;
+ // For the rest of event handling, call a separate function.
+ DoOnEvent(event, data);
+ }
+
+ void DoOnEvent(Event event, void* data);
+
+ /**
+ * Resume from the current breakpoint.
+ * @warning Calling this from the same thread that OnEvent was called in will cause a deadlock.
+ * Calling from any other thread is safe.
+ */
+ void Resume();
+
+ /**
+ * Delete all set breakpoints and resume emulation.
+ */
+ void ClearBreakpoints() {
+ for (auto& bp : breakpoints) {
+ bp.enabled = false;
+ }
+ Resume();
+ }
+
+ // TODO: Evaluate if access to these members should be hidden behind a public interface.
+ std::array<BreakPoint, (int)Event::NumEvents> breakpoints;
+ Event active_breakpoint;
+ bool at_breakpoint = false;
+
+private:
+ /**
+ * Private default constructor to make sure people always construct this through Construct()
+ * instead.
+ */
+ DebugContext() = default;
+
+ /// Mutex protecting current breakpoint state and the observer list.
+ std::mutex breakpoint_mutex;
+
+ /// Used by OnEvent to wait for resumption.
+ std::condition_variable resume_from_breakpoint;
+
+ /// List of registered observers
+ std::list<BreakPointObserver*> breakpoint_observers;
+};
+
+extern std::shared_ptr<DebugContext> g_debug_context;
+
+} // namespace Tegra
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index c384d236e..9463cd5d6 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -18,4 +18,8 @@ GPU::GPU() {
GPU::~GPU() = default;
+const Tegra::Engines::Maxwell3D& GPU::Get3DEngine() const {
+ return *maxwell_3d;
+}
+
} // namespace Tegra
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index 206b3e05e..778b63218 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -13,6 +13,8 @@
namespace Tegra {
+class DebugContext;
+
/**
* Struct describing framebuffer configuration
*/
@@ -66,6 +68,9 @@ public:
/// Processes a command list stored at the specified address in GPU memory.
void ProcessCommandList(GPUVAddr address, u32 size);
+ /// Returns a reference to the Maxwell3D GPU engine.
+ const Engines::Maxwell3D& Get3DEngine() const;
+
std::unique_ptr<MemoryManager> memory_manager;
Engines::Maxwell3D& Maxwell3D() {