mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Add a ImGeReadbackViewer for virtual framebuffers
This commit is contained in:
parent
d057121508
commit
c4f2add076
2 changed files with 83 additions and 12 deletions
|
@ -161,7 +161,8 @@ void ImGePixelViewerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInte
|
|||
}
|
||||
|
||||
ImGePixelViewer::~ImGePixelViewer() {
|
||||
texture_->Release();
|
||||
if (texture_)
|
||||
texture_->Release();
|
||||
}
|
||||
|
||||
void ImGePixelViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw) {
|
||||
|
@ -182,6 +183,40 @@ void ImGePixelViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw)
|
|||
}
|
||||
}
|
||||
|
||||
ImGeReadbackViewer::ImGeReadbackViewer() {
|
||||
channel = Draw::FB_COLOR_BIT;
|
||||
}
|
||||
|
||||
ImGeReadbackViewer::~ImGeReadbackViewer() {
|
||||
if (texture_)
|
||||
texture_->Release();
|
||||
delete[] data_;
|
||||
}
|
||||
|
||||
void ImGeReadbackViewer::Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw) {
|
||||
FramebufferManagerCommon *fbmanager = gpuDebug->GetFramebufferManagerCommon();
|
||||
if (!vfb || !vfb->fbo || !fbmanager) {
|
||||
ImGui::TextUnformatted("(N/A)");
|
||||
return;
|
||||
}
|
||||
|
||||
if (dirty_) {
|
||||
dirty_ = false;
|
||||
|
||||
delete[] data_;
|
||||
int w = vfb->fbo->Width();
|
||||
int h = vfb->fbo->Height();
|
||||
Draw::DataFormat fmt = Draw::DataFormat::R8G8B8A8_UNORM;
|
||||
data_ = new uint8_t[w * h * 4];
|
||||
draw->CopyFramebufferToMemory(vfb->fbo, channel, 0, 0, w, h, fmt, data_, w, Draw::ReadbackMode::BLOCK, "debugger");
|
||||
|
||||
// But for now, let's just draw the original FB, and we can always do that with color at least.
|
||||
}
|
||||
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(vfb->fbo, Draw::FB_COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImGui::Image(texId, ImVec2((float)vfb->fbo->Width(), (float)vfb->fbo->Height()));
|
||||
}
|
||||
|
||||
void ImGePixelViewer::UpdateTexture(Draw::DrawContext *draw) {
|
||||
if (texture_) {
|
||||
texture_->Release();
|
||||
|
@ -557,6 +592,12 @@ void ImGeDebuggerWindow::NotifyStep() {
|
|||
swViewer_.showAlpha = false;
|
||||
swViewer_.useAlpha = false;
|
||||
swViewer_.Snapshot();
|
||||
|
||||
FramebufferManagerCommon *fbman = gpuDebug->GetFramebufferManagerCommon();
|
||||
if (fbman) {
|
||||
rbViewer_.vfb = fbman->GetExactVFB(gstate.getFrameBufAddress(), gstate.FrameBufStride(), gstate.FrameBufFormat());
|
||||
}
|
||||
rbViewer_.Snapshot();
|
||||
}
|
||||
|
||||
void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug, Draw::DrawContext *draw) {
|
||||
|
@ -708,9 +749,7 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
|||
ImDrawList *drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
if (coreState == CORE_STEPPING_GE) {
|
||||
FramebufferManagerCommon *fbman = gpuDebug->GetFramebufferManagerCommon();
|
||||
u32 fbptr = gstate.getFrameBufAddress();
|
||||
VirtualFramebuffer *vfb = fbman ? fbman->GetVFBAt(fbptr) : nullptr;
|
||||
VirtualFramebuffer *vfb = rbViewer_.vfb;
|
||||
if (vfb) {
|
||||
if (vfb->fbo) {
|
||||
ImGui::Text("Framebuffer: %s", vfb->fbo->Tag());
|
||||
|
@ -723,8 +762,10 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
|||
if (ImGui::BeginTabItem("Color")) {
|
||||
const ImVec2 p0 = ImGui::GetCursorScreenPos();
|
||||
ImVec2 p1;
|
||||
if (vfb) {
|
||||
p1 = ImVec2(p0.x + vfb->width, p0.y + vfb->height);
|
||||
float scale = 1.0f;
|
||||
if (vfb && vfb->fbo) {
|
||||
scale = vfb->renderScaleFactor;
|
||||
p1 = ImVec2(p0.x + vfb->fbo->Width(), p0.y + vfb->fbo->Height());
|
||||
} else {
|
||||
// Guess
|
||||
p1 = ImVec2(p0.x + swViewer_.width, p0.y + swViewer_.height);
|
||||
|
@ -734,14 +775,15 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
|||
drawList->PushClipRect(p0, p1, true);
|
||||
|
||||
if (vfb) {
|
||||
ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(vfb->fbo, Draw::FB_COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
ImGui::Image(texId, ImVec2(vfb->width, vfb->height));
|
||||
rbViewer_.Draw(gpuDebug, draw);
|
||||
// ImTextureID texId = ImGui_ImplThin3d_AddFBAsTextureTemp(vfb->fbo, Draw::FB_COLOR_BIT, ImGuiPipeline::TexturedOpaque);
|
||||
// ImGui::Image(texId, ImVec2(vfb->width, vfb->height));
|
||||
} else {
|
||||
swViewer_.Draw(gpuDebug, draw);
|
||||
}
|
||||
|
||||
// Draw vertex preview on top!
|
||||
DrawPreviewPrimitive(drawList, p0, previewPrim_, previewIndices_, previewVertices_, previewCount_, false);
|
||||
DrawPreviewPrimitive(drawList, p0, previewPrim_, previewIndices_, previewVertices_, previewCount_, false, scale, scale);
|
||||
|
||||
drawList->PopClipRect();
|
||||
|
||||
|
@ -756,8 +798,8 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
|||
ImGui::EndTabBar();
|
||||
}
|
||||
|
||||
if (vfb) {
|
||||
ImGui::Text("%dx%d (emulated: %dx%d)", vfb->width, vfb->height, vfb->bufferWidth, vfb->bufferHeight);
|
||||
if (vfb && vfb->fbo) {
|
||||
ImGui::Text("VFB %dx%d (emulated: %dx%d)", vfb->width, vfb->height, vfb->fbo->Width(), vfb->fbo->Height());
|
||||
} else {
|
||||
// Use the swViewer_!
|
||||
ImGui::Text("Raw FB: %08x (%s)", gstate.getFrameBufRawAddress(), GeBufferFormatToString(gstate.FrameBufFormat()));
|
||||
|
|
|
@ -54,9 +54,17 @@ private:
|
|||
|
||||
namespace Draw {
|
||||
class Texture;
|
||||
enum FBChannel;
|
||||
}
|
||||
|
||||
struct ImGePixelViewer {
|
||||
class PixelLookup {
|
||||
public:
|
||||
virtual ~PixelLookup() {}
|
||||
|
||||
uint32_t GetPixel(int x, int y);
|
||||
};
|
||||
|
||||
struct ImGePixelViewer : public PixelLookup {
|
||||
~ImGePixelViewer();
|
||||
void Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *draw);
|
||||
void Snapshot() {
|
||||
|
@ -78,6 +86,26 @@ private:
|
|||
bool dirty_ = true;
|
||||
};
|
||||
|
||||
// Reads back framebuffers, not textures.
|
||||
struct ImGeReadbackViewer : public PixelLookup {
|
||||
ImGeReadbackViewer();
|
||||
~ImGeReadbackViewer();
|
||||
void Draw(GPUDebugInterface *gpuDebug, Draw::DrawContext *);
|
||||
void Snapshot() {
|
||||
dirty_ = true;
|
||||
}
|
||||
|
||||
VirtualFramebuffer *vfb = nullptr;
|
||||
|
||||
// This specifies what to show
|
||||
Draw::FBChannel channel;
|
||||
|
||||
private:
|
||||
uint8_t *data_ = nullptr;
|
||||
Draw::Texture *texture_ = nullptr;
|
||||
bool dirty_ = true;
|
||||
};
|
||||
|
||||
class ImGePixelViewerWindow {
|
||||
public:
|
||||
void Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface *gpuDebug, Draw::DrawContext *draw);
|
||||
|
@ -111,6 +139,7 @@ public:
|
|||
|
||||
private:
|
||||
ImGeDisasmView disasmView_;
|
||||
ImGeReadbackViewer rbViewer_;
|
||||
ImGePixelViewer swViewer_;
|
||||
int showBannerInFrames_ = 0;
|
||||
bool reloadPreview_ = false;
|
||||
|
|
Loading…
Add table
Reference in a new issue