gpu_debugger.h 2.6 KB

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