gpu_debugger.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // Copyright 2014 Citra Emulator Project
  2. // Licensed under GPLv2
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <algorithm>
  6. #include <functional>
  7. #include <vector>
  8. #include "common/log.h"
  9. #include "core/hle/service/gsp_gpu.h"
  10. #include "command_processor.h"
  11. #include "pica.h"
  12. class GraphicsDebugger
  13. {
  14. public:
  15. // Base class for all objects which need to be notified about GPU events
  16. class DebuggerObserver
  17. {
  18. public:
  19. DebuggerObserver() : observed(nullptr) { }
  20. virtual ~DebuggerObserver()
  21. {
  22. if (observed)
  23. observed->UnregisterObserver(this);
  24. }
  25. /**
  26. * Called when a GX command has been processed and is ready for being
  27. * read via GraphicsDebugger::ReadGXCommandHistory.
  28. * @param total_command_count Total number of commands in the GX history
  29. * @note All methods in this class are called from the GSP thread
  30. */
  31. virtual void GXCommandProcessed(int total_command_count)
  32. {
  33. const GSP_GPU::Command& cmd = observed->ReadGXCommandHistory(total_command_count-1);
  34. ERROR_LOG(GSP, "Received command: id=%x", (int)cmd.id.Value());
  35. }
  36. protected:
  37. const GraphicsDebugger* GetDebugger() const
  38. {
  39. return observed;
  40. }
  41. private:
  42. GraphicsDebugger* observed;
  43. bool in_destruction;
  44. friend class GraphicsDebugger;
  45. };
  46. void GXCommandProcessed(u8* command_data)
  47. {
  48. if (observers.empty())
  49. return;
  50. gx_command_history.push_back(GSP_GPU::Command());
  51. GSP_GPU::Command& cmd = gx_command_history[gx_command_history.size()-1];
  52. memcpy(&cmd, command_data, sizeof(GSP_GPU::Command));
  53. ForEachObserver([this](DebuggerObserver* observer) {
  54. observer->GXCommandProcessed(this->gx_command_history.size());
  55. } );
  56. }
  57. const GSP_GPU::Command& ReadGXCommandHistory(int index) const
  58. {
  59. // TODO: Is this thread-safe?
  60. return gx_command_history[index];
  61. }
  62. void RegisterObserver(DebuggerObserver* observer)
  63. {
  64. // TODO: Check for duplicates
  65. observers.push_back(observer);
  66. observer->observed = this;
  67. }
  68. void UnregisterObserver(DebuggerObserver* observer)
  69. {
  70. std::remove(observers.begin(), observers.end(), observer);
  71. observer->observed = nullptr;
  72. }
  73. private:
  74. void ForEachObserver(std::function<void (DebuggerObserver*)> func)
  75. {
  76. std::for_each(observers.begin(),observers.end(), func);
  77. }
  78. std::vector<DebuggerObserver*> observers;
  79. std::vector<GSP_GPU::Command> gx_command_history;
  80. };