diff options
Diffstat (limited to '')
-rw-r--r-- | src/video_core/command_processor.cpp | 2 | ||||
-rw-r--r-- | src/video_core/debug_utils/debug_utils.cpp | 55 | ||||
-rw-r--r-- | src/video_core/debug_utils/debug_utils.h | 21 | ||||
-rw-r--r-- | src/video_core/gpu_debugger.h | 63 |
4 files changed, 78 insertions, 63 deletions
diff --git a/src/video_core/command_processor.cpp b/src/video_core/command_processor.cpp index f7a412bc1..76fdb4e4a 100644 --- a/src/video_core/command_processor.cpp +++ b/src/video_core/command_processor.cpp @@ -33,6 +33,8 @@ static inline void WritePicaReg(u32 id, u32 value, u32 mask) { u32 old_value = registers[id]; registers[id] = (old_value & ~mask) | (value & mask); + DebugUtils::OnPicaRegWrite(id, registers[id]); + switch(id) { // It seems like these trigger vertex rendering case PICA_REG_INDEX(trigger_draw): diff --git a/src/video_core/debug_utils/debug_utils.cpp b/src/video_core/debug_utils/debug_utils.cpp index f41249eac..1bbc0330c 100644 --- a/src/video_core/debug_utils/debug_utils.cpp +++ b/src/video_core/debug_utils/debug_utils.cpp @@ -4,6 +4,7 @@ #include <algorithm> #include <fstream> +#include <mutex> #include <string> #include "video_core/pica.h" @@ -260,6 +261,60 @@ void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data } } +static std::unique_ptr<PicaTrace> pica_trace; +static std::mutex pica_trace_mutex; +static int is_pica_tracing = false; + +void StartPicaTracing() +{ + if (is_pica_tracing) { + ERROR_LOG(GPU, "StartPicaTracing called even though tracing already running!"); + return; + } + + pica_trace_mutex.lock(); + pica_trace = std::unique_ptr<PicaTrace>(new PicaTrace); + + is_pica_tracing = true; + pica_trace_mutex.unlock(); +} + +bool IsPicaTracing() +{ + return is_pica_tracing; +} + +void OnPicaRegWrite(u32 id, u32 value) +{ + // Double check for is_pica_tracing to avoid pointless locking overhead + if (!is_pica_tracing) + return; + + std::unique_lock<std::mutex> lock(pica_trace_mutex); + + if (!is_pica_tracing) + return; + + pica_trace->writes.push_back({id, value}); +} + +std::unique_ptr<PicaTrace> FinishPicaTracing() +{ + if (!is_pica_tracing) { + ERROR_LOG(GPU, "FinishPicaTracing called even though tracing already running!"); + return {}; + } + + // signalize that no further tracing should be performed + is_pica_tracing = false; + + // Wait until running tracing is finished + pica_trace_mutex.lock(); + std::unique_ptr<PicaTrace> ret(std::move(pica_trace)); + pica_trace_mutex.unlock(); + return std::move(ret); +} + } // namespace } // namespace diff --git a/src/video_core/debug_utils/debug_utils.h b/src/video_core/debug_utils/debug_utils.h index bd7a0a89b..023500066 100644 --- a/src/video_core/debug_utils/debug_utils.h +++ b/src/video_core/debug_utils/debug_utils.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <memory> #include <vector> #include "video_core/pica.h" @@ -38,6 +39,26 @@ private: void DumpShader(const u32* binary_data, u32 binary_size, const u32* swizzle_data, u32 swizzle_size, u32 main_offset, const Regs::VSOutputAttributes* output_attributes); + +// Utility class to log Pica commands. +struct PicaTrace { + struct Write : public std::pair<u32,u32> { + Write(u32 id, u32 value) : std::pair<u32,u32>(id, value) {} + + u32& Id() { return first; } + const u32& Id() const { return first; } + + u32& Value() { return second; } + const u32& Value() const { return second; } + }; + std::vector<Write> writes; +}; + +void StartPicaTracing(); +bool IsPicaTracing(); +void OnPicaRegWrite(u32 id, u32 value); +std::unique_ptr<PicaTrace> FinishPicaTracing(); + } // namespace } // namespace diff --git a/src/video_core/gpu_debugger.h b/src/video_core/gpu_debugger.h index 2ba873457..5a81fcfcb 100644 --- a/src/video_core/gpu_debugger.h +++ b/src/video_core/gpu_debugger.h @@ -18,19 +18,6 @@ class GraphicsDebugger { public: - // A few utility structs used to expose data - // A vector of commands represented by their raw byte sequence - struct PicaCommand : public std::vector<u32> - { - const Pica::CommandProcessor::CommandHeader& GetHeader() const - { - const u32& val = at(1); - return *(Pica::CommandProcessor::CommandHeader*)&val; - } - }; - - typedef std::vector<PicaCommand> PicaCommandList; - // Base class for all objects which need to be notified about GPU events class DebuggerObserver { @@ -55,16 +42,6 @@ public: ERROR_LOG(GSP, "Received command: id=%x", (int)cmd.id.Value()); } - /** - * @param lst command list which triggered this call - * @param is_new true if the command list was called for the first time - * @todo figure out how to make sure called functions don't keep references around beyond their life time - */ - virtual void OnCommandListCalled(const PicaCommandList& lst, bool is_new) - { - ERROR_LOG(GSP, "Command list called: %d", (int)is_new); - } - protected: const GraphicsDebugger* GetDebugger() const { @@ -93,49 +70,12 @@ public: } ); } - void CommandListCalled(u32 address, u32* command_list, u32 size_in_words) - { - if (observers.empty()) - return; - - PicaCommandList cmdlist; - for (u32* parse_pointer = command_list; parse_pointer < command_list + size_in_words;) - { - const Pica::CommandProcessor::CommandHeader& header = *(Pica::CommandProcessor::CommandHeader*)(&parse_pointer[1]); - - cmdlist.push_back(PicaCommand()); - auto& cmd = cmdlist.back(); - - size_t size = 2 + header.extra_data_length; - size = (size + 1) / 2 * 2; // align to 8 bytes - cmd.reserve(size); - std::copy(parse_pointer, parse_pointer + size, std::back_inserter(cmd)); - - parse_pointer += size; - } - - auto obj = std::pair<u32,PicaCommandList>(address, cmdlist); - auto it = std::find(command_lists.begin(), command_lists.end(), obj); - bool is_new = (it == command_lists.end()); - if (is_new) - command_lists.push_back(obj); - - ForEachObserver([&](DebuggerObserver* observer) { - observer->OnCommandListCalled(obj.second, is_new); - } ); - } - const GSP_GPU::Command& ReadGXCommandHistory(int index) const { // TODO: Is this thread-safe? return gx_command_history[index]; } - const std::vector<std::pair<u32,PicaCommandList>>& GetCommandLists() const - { - return command_lists; - } - void RegisterObserver(DebuggerObserver* observer) { // TODO: Check for duplicates @@ -158,7 +98,4 @@ private: std::vector<DebuggerObserver*> observers; std::vector<GSP_GPU::Command> gx_command_history; - - // vector of pairs of command lists and their storage address - std::vector<std::pair<u32,PicaCommandList>> command_lists; }; |