#pragma once #include "GPU/Common/GPUDebugInterface.h" // GE-related windows of the ImDebugger struct ImConfig; struct ImControl; class FramebufferManagerCommon; class TextureCacheCommon; constexpr ImU32 ImDebuggerColor_Diff = IM_COL32(255, 96, 32, 255); constexpr ImU32 ImDebuggerColor_DiffAlpha = IM_COL32(255, 96, 32, 128); void DrawFramebuffersWindow(ImConfig &cfg, FramebufferManagerCommon *framebufferManager); void DrawTexturesWindow(ImConfig &cfg, TextureCacheCommon *textureCache); void DrawDisplayWindow(ImConfig &cfg, FramebufferManagerCommon *framebufferManager); void DrawDebugStatsWindow(ImConfig &cfg); class ImGeDisasmView { public: void Draw(GPUDebugInterface *gpuDebug); bool followPC_ = true; void GotoPC() { gotoPC_ = true; } void GotoAddr(uint32_t addr) { selectedAddr_ = addr; } void NotifyStep(); private: u32 selectedAddr_ = 0; u32 dragAddr_ = INVALID_ADDR; bool bpPopup_ = false; bool gotoPC_ = false; enum : u32 { INVALID_ADDR = 0xFFFFFFFF }; }; class ImGeStateWindow { public: void Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug); void Snapshot(); }; void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug); namespace Draw { class Texture; enum class Aspect; enum class DataFormat : uint8_t; } class PixelLookup { public: virtual ~PixelLookup() {} virtual bool FormatValueAt(char *buf, size_t bufSize, int x, int y) const = 0; }; struct ImGePixelViewer : public PixelLookup { ~ImGePixelViewer(); bool Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw, float zoom); void Snapshot() { dirty_ = true; } bool FormatValueAt(char *buf, size_t bufSize, int x, int y) const override; void DeviceLost(); uint32_t addr = 0x04110000; uint16_t stride = 512; uint16_t width = 480; uint16_t height = 272; GEBufferFormat format = GE_FORMAT_DEPTH16; bool useAlpha = false; bool showAlpha = false; float scale = 20.0f; private: void UpdateTexture(Draw::DrawContext *draw); Draw::Texture *texture_ = nullptr; bool dirty_ = true; }; // Reads back framebuffers, not textures. struct ImGeReadbackViewer : public PixelLookup { ImGeReadbackViewer(); ~ImGeReadbackViewer(); bool Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw, float zoom); void Snapshot() { dirty_ = true; } bool FormatValueAt(char *buf, size_t bufSize, int x, int y) const override; void DeviceLost(); VirtualFramebuffer *GetVFB(FramebufferManagerCommon *fbMan) const; // We need to re-fetch the vfb each frame from these parameters. u32 fbAddr = 0; u32 fbStride = 0; GEBufferFormat fbFormat = GE_FORMAT_INVALID; // This specifies what to show Draw::Aspect aspect; float scale = 1.0f; // Scales depth values. private: uint8_t *data_ = nullptr; Draw::DataFormat readbackFmt_; Draw::Texture *texture_ = nullptr; bool dirty_ = true; }; class ImGePixelViewerWindow { public: void Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug, Draw::DrawContext *draw); void Snapshot() { viewer_.Snapshot(); } void Show(uint32_t address, int width, int height, int stride, GEBufferFormat format) { viewer_.addr = address; viewer_.width = width; viewer_.height = height; viewer_.stride = stride; viewer_.format = format; } void DeviceLost() { viewer_.DeviceLost(); } private: ImGePixelViewer viewer_; }; class ImGeDebuggerWindow { public: ImGeDebuggerWindow(); void Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug, Draw::DrawContext *draw); ImGeDisasmView &View() { return disasmView_; } const char *Title() const { return "GE Debugger"; } void NotifyStep(); void DeviceLost(); private: ImGeDisasmView disasmView_; ImGeReadbackViewer rbViewer_; ImGePixelViewer swViewer_; int showBannerInFrames_ = 0; bool reloadPreview_ = false; GEPrimitiveType previewPrim_ = GEPrimitiveType::GE_PRIM_TRIANGLES; std::vector previewIndices_; std::vector previewVertices_; int previewCount_ = 0; Draw::Aspect selectedAspect_; float previewZoom_ = 1.0f; };