mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-27 00:50:05 +00:00
GPU debugger: Add functionality to inspect command lists.
This commit is contained in:
parent
930a4a3f9e
commit
90fd4e111c
@ -126,6 +126,10 @@ void TriggerCmdReqQueue(Service::Interface* self) {
|
|||||||
GPU::Write<u32>(GPU::Registers::CommandListAddress, cmd_buff[1] >> 3);
|
GPU::Write<u32>(GPU::Registers::CommandListAddress, cmd_buff[1] >> 3);
|
||||||
GPU::Write<u32>(GPU::Registers::CommandListSize, cmd_buff[2] >> 3);
|
GPU::Write<u32>(GPU::Registers::CommandListSize, cmd_buff[2] >> 3);
|
||||||
GPU::Write<u32>(GPU::Registers::ProcessCommandList, 1); // TODO: Not sure if we are supposed to always write this
|
GPU::Write<u32>(GPU::Registers::ProcessCommandList, 1); // TODO: Not sure if we are supposed to always write this
|
||||||
|
|
||||||
|
// TODO: Move this to GPU
|
||||||
|
// TODO: Not sure what units the size is measured in
|
||||||
|
g_debugger.CommandListCalled(cmd_buff[1], (u32*)Memory::GetPointer(cmd_buff[1]), cmd_buff[2]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case GXCommandId::SET_MEMORY_FILL:
|
case GXCommandId::SET_MEMORY_FILL:
|
||||||
|
@ -11,11 +11,23 @@
|
|||||||
#include "common/log.h"
|
#include "common/log.h"
|
||||||
|
|
||||||
#include "core/hle/service/gsp.h"
|
#include "core/hle/service/gsp.h"
|
||||||
|
#include "pica.h"
|
||||||
|
|
||||||
class GraphicsDebugger
|
class GraphicsDebugger
|
||||||
{
|
{
|
||||||
public:
|
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>
|
||||||
|
{
|
||||||
|
Pica::CommandHeader& GetHeader()
|
||||||
|
{
|
||||||
|
return *(Pica::CommandHeader*)&(front());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<PicaCommand> PicaCommandList;
|
||||||
|
|
||||||
// Base class for all objects which need to be notified about GPU events
|
// Base class for all objects which need to be notified about GPU events
|
||||||
class DebuggerObserver
|
class DebuggerObserver
|
||||||
{
|
{
|
||||||
@ -40,6 +52,16 @@ public:
|
|||||||
ERROR_LOG(GSP, "Received command: id=%x", cmd.id);
|
ERROR_LOG(GSP, "Received command: id=%x", cmd.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 CommandListCalled(const PicaCommandList& lst, bool is_new)
|
||||||
|
{
|
||||||
|
ERROR_LOG(GSP, "Command list called: %d", (int)is_new);
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
GraphicsDebugger* GetDebugger()
|
GraphicsDebugger* GetDebugger()
|
||||||
{
|
{
|
||||||
@ -66,12 +88,39 @@ public:
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CommandListCalled(u32 address, u32* command_list, u32 size_in_words)
|
||||||
|
{
|
||||||
|
// TODO: Decoding fun
|
||||||
|
|
||||||
|
// For now, just treating the whole command list as a single command
|
||||||
|
PicaCommandList cmdlist;
|
||||||
|
cmdlist.push_back(PicaCommand());
|
||||||
|
auto& cmd = cmdlist[0];
|
||||||
|
cmd.reserve(size_in_words);
|
||||||
|
std::copy(command_list, command_list+size_in_words, std::back_inserter(cmd));
|
||||||
|
|
||||||
|
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->CommandListCalled(obj.second, is_new);
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
const GSP_GPU::GXCommand& ReadGXCommandHistory(int index) const
|
const GSP_GPU::GXCommand& ReadGXCommandHistory(int index) const
|
||||||
{
|
{
|
||||||
// TODO: Is this thread-safe?
|
// TODO: Is this thread-safe?
|
||||||
return gx_command_history[index];
|
return gx_command_history[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<std::pair<u32,PicaCommandList>>& GetCommandLists() const
|
||||||
|
{
|
||||||
|
return command_lists;
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterObserver(DebuggerObserver* observer)
|
void RegisterObserver(DebuggerObserver* observer)
|
||||||
{
|
{
|
||||||
// TODO: Check for duplicates
|
// TODO: Check for duplicates
|
||||||
@ -94,4 +143,7 @@ private:
|
|||||||
std::vector<DebuggerObserver*> observers;
|
std::vector<DebuggerObserver*> observers;
|
||||||
|
|
||||||
std::vector<GSP_GPU::GXCommand> gx_command_history;
|
std::vector<GSP_GPU::GXCommand> gx_command_history;
|
||||||
|
|
||||||
|
// vector of pairs of command lists and their storage address
|
||||||
|
std::vector<std::pair<u32,PicaCommandList>> command_lists;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user