GE Debugger: Display if tex is framebuf.

Rather than guessing based on size, let's show explicitly.
This commit is contained in:
Unknown W. Brackets 2022-10-10 22:35:42 -07:00
parent a4bd0af3f2
commit 416265431b
20 changed files with 76 additions and 42 deletions

View file

@ -41,7 +41,7 @@ DebuggerSubscriber *WebSocketGPUBufferInit(DebuggerEventHandlerMap &map) {
}
// Note: Calls req.Respond(). Other data can be added afterward.
static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &buf, bool includeAlpha, int stackWidth) {
static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &buf, bool isFramebuffer, bool includeAlpha, int stackWidth) {
#ifdef USING_QT_UI
req.Fail("Not supported on Qt yet, pull requests accepted");
return false;
@ -83,6 +83,9 @@ static bool StreamBufferToDataURI(DebuggerRequest &req, const GPUDebugBuffer &bu
auto &json = req.Respond();
json.writeInt("width", w);
json.writeInt("height", h);
if (isFramebuffer) {
json.writeBool("isFramebuffer", isFramebuffer);
}
// Start a value...
json.writeRaw("uri", "");
@ -191,7 +194,7 @@ static std::string DescribeFormat(GPUDebugBufferFormat fmt) {
}
// Note: Calls req.Respond(). Other data can be added afterward.
static bool StreamBufferToBase64(DebuggerRequest &req, const GPUDebugBuffer &buf) {
static bool StreamBufferToBase64(DebuggerRequest &req, const GPUDebugBuffer &buf, bool isFramebuffer) {
size_t length = buf.GetStride() * buf.GetHeight();
auto &json = req.Respond();
@ -199,6 +202,9 @@ static bool StreamBufferToBase64(DebuggerRequest &req, const GPUDebugBuffer &buf
json.writeInt("height", buf.GetHeight());
json.writeBool("flipped", buf.GetFlipped());
json.writeString("format", DescribeFormat(buf.GetFormat()));
if (isFramebuffer) {
json.writeBool("isFramebuffer", isFramebuffer);
}
// Start a value without any actual data yet...
json.writeRaw("base64", "");
@ -217,7 +223,7 @@ static bool StreamBufferToBase64(DebuggerRequest &req, const GPUDebugBuffer &buf
return true;
}
static void GenericStreamBuffer(DebuggerRequest &req, std::function<bool(const GPUDebugBuffer *&)> func) {
static void GenericStreamBuffer(DebuggerRequest &req, std::function<bool(const GPUDebugBuffer *&, bool *isFramebuffer)> func) {
if (!currentDebugMIPS->isAlive()) {
return req.Fail("CPU not started");
}
@ -238,15 +244,16 @@ static void GenericStreamBuffer(DebuggerRequest &req, std::function<bool(const G
return req.Fail("Parameter 'type' must be either 'uri' or 'base64'");
const GPUDebugBuffer *buf = nullptr;
if (!func(buf)) {
bool isFramebuffer = false;
if (!func(buf, &isFramebuffer)) {
return req.Fail("Could not download output");
}
_assert_(buf != nullptr);
if (type == "base64") {
StreamBufferToBase64(req, *buf);
StreamBufferToBase64(req, *buf, isFramebuffer);
} else if (type == "uri") {
StreamBufferToDataURI(req, *buf, includeAlpha, stackWidth);
StreamBufferToDataURI(req, *buf, isFramebuffer, includeAlpha, stackWidth);
} else {
_assert_(false);
}
@ -270,7 +277,8 @@ static void GenericStreamBuffer(DebuggerRequest &req, std::function<bool(const G
// - format: string indicating format, such as 'R8G8B8A8_UNORM' or 'B8G8R8A8_UNORM'.
// - base64: base64 encode of binary data.
void WebSocketGPUBufferScreenshot(DebuggerRequest &req) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf, bool *isFramebuffer) {
*isFramebuffer = false;
return GPUStepping::GPU_GetOutputFramebuffer(buf);
});
}
@ -293,7 +301,8 @@ void WebSocketGPUBufferScreenshot(DebuggerRequest &req) {
// - format: string indicating format, such as 'R8G8B8A8_UNORM' or 'B8G8R8A8_UNORM'.
// - base64: base64 encode of binary data.
void WebSocketGPUBufferRenderColor(DebuggerRequest &req) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf, bool *isFramebuffer) {
*isFramebuffer = false;
return GPUStepping::GPU_GetCurrentFramebuffer(buf, GPU_DBG_FRAMEBUF_RENDER);
});
}
@ -316,7 +325,8 @@ void WebSocketGPUBufferRenderColor(DebuggerRequest &req) {
// - format: string indicating format, such as 'D16', 'D24_X8' or 'D32F'.
// - base64: base64 encode of binary data.
void WebSocketGPUBufferRenderDepth(DebuggerRequest &req) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf, bool *isFramebuffer) {
*isFramebuffer = false;
return GPUStepping::GPU_GetCurrentDepthbuffer(buf);
});
}
@ -339,7 +349,8 @@ void WebSocketGPUBufferRenderDepth(DebuggerRequest &req) {
// - format: string indicating format, such as 'X24_S8' or 'S8'.
// - base64: base64 encode of binary data.
void WebSocketGPUBufferRenderStencil(DebuggerRequest &req) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf, bool *isFramebuffer) {
*isFramebuffer = false;
return GPUStepping::GPU_GetCurrentStencilbuffer(buf);
});
}
@ -354,6 +365,7 @@ void WebSocketGPUBufferRenderStencil(DebuggerRequest &req) {
// Response (same event name) for 'uri' type:
// - width: numeric width of the texture (often wider than visual.)
// - height: numeric height of the texture (often wider than visual.)
// - isFramebuffer: optional, present and true if this came from a hardware framebuffer.
// - uri: data: URI of PNG image for display.
//
// Response (same event name) for 'base64' type:
@ -361,14 +373,15 @@ void WebSocketGPUBufferRenderStencil(DebuggerRequest &req) {
// - height: numeric height of the texture (often wider than visual.)
// - flipped: boolean to indicate whether buffer is vertically flipped.
// - format: string indicating format, such as 'R8G8B8A8_UNORM' or 'B8G8R8A8_UNORM'.
// - isFramebuffer: optional, present and true if this came from a hardware framebuffer.
// - base64: base64 encode of binary data.
void WebSocketGPUBufferTexture(DebuggerRequest &req) {
u32 level = 0;
if (!req.ParamU32("level", &level, false, DebuggerParamType::OPTIONAL))
return;
GenericStreamBuffer(req, [level](const GPUDebugBuffer *&buf) {
return GPUStepping::GPU_GetCurrentTexture(buf, level);
GenericStreamBuffer(req, [level](const GPUDebugBuffer *&buf, bool *isFramebuffer) {
return GPUStepping::GPU_GetCurrentTexture(buf, level, isFramebuffer);
});
}
@ -391,7 +404,9 @@ void WebSocketGPUBufferTexture(DebuggerRequest &req) {
// - format: string indicating format, such as 'R8G8B8A8_UNORM' or 'B8G8R8A8_UNORM'.
// - base64: base64 encode of binary data.
void WebSocketGPUBufferClut(DebuggerRequest &req) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf) {
GenericStreamBuffer(req, [](const GPUDebugBuffer *&buf, bool *isFramebuffer) {
// TODO: Or maybe it could be?
*isFramebuffer = false;
return GPUStepping::GPU_GetCurrentClut(buf);
});
}

View file

@ -240,7 +240,7 @@ public:
}
// Similar to GetCurrentFramebuffer(), with texture level specification.
virtual bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
virtual bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) {
return false;
}

View file

@ -1162,9 +1162,10 @@ bool TextureCacheCommon::SetOffsetTexture(u32 yOffset) {
}
}
bool TextureCacheCommon::GetCurrentFramebufferTextureDebug(GPUDebugBuffer &buffer) {
bool TextureCacheCommon::GetCurrentFramebufferTextureDebug(GPUDebugBuffer &buffer, bool *isFramebuffer) {
if (!nextFramebufferTexture_)
return false;
*isFramebuffer = true;
VirtualFramebuffer *vfb = nextFramebufferTexture_;
u8 sf = vfb->renderScaleFactor;

View file

@ -348,7 +348,7 @@ public:
bool VideoIsPlaying() {
return !videos_.empty();
}
virtual bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) { return false; }
virtual bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) { return false; }
protected:
virtual void *GetNativeTextureView(const TexCacheEntry *entry) = 0;
@ -399,7 +399,7 @@ protected:
bool GetBestFramebufferCandidate(const TextureDefinition &entry, u32 texAddrOffset, AttachCandidate *bestCandidate) const;
void SetTextureFramebuffer(const AttachCandidate &candidate);
bool GetCurrentFramebufferTextureDebug(GPUDebugBuffer &buffer);
bool GetCurrentFramebufferTextureDebug(GPUDebugBuffer &buffer, bool *isFramebuffer);
virtual void BoundFramebufferTexture() {}

View file

@ -453,10 +453,10 @@ DXGI_FORMAT TextureCacheD3D11::GetDestFormat(GETextureFormat format, GEPaletteFo
}
}
bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) {
SetTexture();
if (!nextTexture_) {
return GetCurrentFramebufferTextureDebug(buffer);
return GetCurrentFramebufferTextureDebug(buffer, isFramebuffer);
}
// Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer.
@ -499,6 +499,7 @@ bool TextureCacheD3D11::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level
context_->Unmap(stagingCopy, level);
stagingCopy->Release();
*isFramebuffer = false;
return true;
}

View file

@ -53,7 +53,7 @@ public:
void ForgetLastTexture() override;
void InvalidateLastTexture() override;
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
protected:
void BindTexture(TexCacheEntry *entry) override;

View file

@ -63,6 +63,7 @@ static GPUDebugBuffer bufferStencil;
static GPUDebugBuffer bufferTex;
static GPUDebugBuffer bufferClut;
static int bufferLevel;
static bool lastWasFramebuffer;
static u32 pauseSetCmdValue;
static GPUgstate lastGState;
@ -111,7 +112,7 @@ static void RunPauseAction() {
break;
case PAUSE_GETTEX:
bufferResult = gpuDebug->GetCurrentTexture(bufferTex, bufferLevel);
bufferResult = gpuDebug->GetCurrentTexture(bufferTex, bufferLevel, &lastWasFramebuffer);
break;
case PAUSE_GETCLUT:
@ -237,9 +238,11 @@ bool GPU_GetCurrentStencilbuffer(const GPUDebugBuffer *&buffer) {
return GetBuffer(buffer, PAUSE_GETSTENCILBUF, bufferStencil);
}
bool GPU_GetCurrentTexture(const GPUDebugBuffer *&buffer, int level) {
bool GPU_GetCurrentTexture(const GPUDebugBuffer *&buffer, int level, bool *isFramebuffer) {
bufferLevel = level;
return GetBuffer(buffer, PAUSE_GETTEX, bufferTex);
bool result = GetBuffer(buffer, PAUSE_GETTEX, bufferTex);
*isFramebuffer = lastWasFramebuffer;
return result;
}
bool GPU_GetCurrentClut(const GPUDebugBuffer *&buffer) {

View file

@ -36,7 +36,7 @@ namespace GPUStepping {
bool GPU_GetCurrentFramebuffer(const GPUDebugBuffer *&buffer, GPUDebugFramebufferType type);
bool GPU_GetCurrentDepthbuffer(const GPUDebugBuffer *&buffer);
bool GPU_GetCurrentStencilbuffer(const GPUDebugBuffer *&buffer);
bool GPU_GetCurrentTexture(const GPUDebugBuffer *&buffer, int level);
bool GPU_GetCurrentTexture(const GPUDebugBuffer *&buffer, int level, bool *isFramebuffer);
bool GPU_GetCurrentClut(const GPUDebugBuffer *&buffer);
bool GPU_SetCmdValue(u32 op);
bool GPU_FlushDrawing();

View file

@ -362,10 +362,10 @@ D3DFORMAT TextureCacheDX9::GetDestFormat(GETextureFormat format, GEPaletteFormat
}
}
bool TextureCacheDX9::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
bool TextureCacheDX9::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) {
SetTexture();
if (!nextTexture_) {
return GetCurrentFramebufferTextureDebug(buffer);
return GetCurrentFramebufferTextureDebug(buffer, isFramebuffer);
}
ApplyTexture();
@ -400,6 +400,9 @@ bool TextureCacheDX9::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level)
}
renderTarget->Release();
}
*isFramebuffer = true;
} else {
*isFramebuffer = false;
}
if (SUCCEEDED(hr)) {

View file

@ -43,7 +43,7 @@ public:
}
void InvalidateLastTexture() override;
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
protected:
void BindTexture(TexCacheEntry *entry) override;

View file

@ -385,11 +385,11 @@ Draw::DataFormat TextureCacheGLES::GetDestFormat(GETextureFormat format, GEPalet
}
}
bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) {
InvalidateLastTexture();
SetTexture();
if (!nextTexture_) {
return GetCurrentFramebufferTextureDebug(buffer);
return GetCurrentFramebufferTextureDebug(buffer, isFramebuffer);
}
// Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer.
@ -415,6 +415,7 @@ bool TextureCacheGLES::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level)
gstate_c.Dirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS);
framebufferManager_->RebindFramebuffer("RebindFramebuffer - GetCurrentTextureDebug");
*isFramebuffer = false;
return result;
}

View file

@ -55,7 +55,7 @@ public:
lastBoundTexture = nullptr;
}
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
void DeviceLost();
void DeviceRestore(Draw::DrawContext *draw);

View file

@ -3190,11 +3190,11 @@ bool GPUCommon::GetCurrentClut(GPUDebugBuffer &buffer) {
return textureCache_->GetCurrentClutBuffer(buffer);
}
bool GPUCommon::GetCurrentTexture(GPUDebugBuffer &buffer, int level) {
bool GPUCommon::GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) {
if (!gstate.isTextureMapEnabled()) {
return false;
}
return textureCache_->GetCurrentTextureDebug(buffer, level);
return textureCache_->GetCurrentTextureDebug(buffer, level, isFramebuffer);
}
bool GPUCommon::DescribeCodePtr(const u8 *ptr, std::string &name) {

View file

@ -200,7 +200,7 @@ public:
bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) override;
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) override;
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;

View file

@ -1405,8 +1405,8 @@ bool SoftGPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) {
return true;
}
bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer, int level)
{
bool SoftGPU::GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) {
*isFramebuffer = false;
return Rasterizer::GetCurrentTexture(buffer, level);
}

View file

@ -162,7 +162,7 @@ public:
bool GetOutputFramebuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer) override;
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level) override;
bool GetCurrentTexture(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
bool GetCurrentClut(GPUDebugBuffer &buffer) override;
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices) override;

View file

@ -774,10 +774,10 @@ void TextureCacheVulkan::BoundFramebufferTexture() {
imageView_ = (VkImageView)draw_->GetNativeObject(Draw::NativeObject::BOUND_TEXTURE0_IMAGEVIEW);
}
bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) {
bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) {
SetTexture();
if (!nextTexture_) {
return GetCurrentFramebufferTextureDebug(buffer);
return GetCurrentFramebufferTextureDebug(buffer, isFramebuffer);
}
// Apply texture may need to rebuild the texture if we're about to render, or bind a framebuffer.
@ -829,6 +829,7 @@ bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int leve
// So let's dirty the things that are involved in Vulkan dynamic state. Readbacks are not frequent so this won't hurt other backends.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_BLEND_STATE | DIRTY_DEPTHSTENCIL_STATE);
framebufferManager_->RebindFramebuffer("RebindFramebuffer - GetCurrentTextureDebug");
*isFramebuffer = false;
return true;
}

View file

@ -81,7 +81,7 @@ public:
sampler = curSampler_;
}
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level) override;
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
void GetStats(char *ptr, size_t size);

View file

@ -376,7 +376,10 @@ void CGEDebugger::DescribePrimaryPreview(const GPUgstate &state, char desc[256])
if (showClut_) {
// In this case, we're showing the texture here.
snprintf(desc, 256, "Texture L%d: 0x%08x (%dx%d)", textureLevel_, state.getTextureAddress(textureLevel_), state.getTextureWidth(textureLevel_), state.getTextureHeight(textureLevel_));
if (primaryIsFramebuffer_)
snprintf(desc, 256, "FB Tex L%d: 0x%08x (%dx%d)", textureLevel_, state.getTextureAddress(textureLevel_), state.getTextureWidth(textureLevel_), state.getTextureHeight(textureLevel_));
else
snprintf(desc, 256, "Texture L%d: 0x%08x (%dx%d)", textureLevel_, state.getTextureAddress(textureLevel_), state.getTextureWidth(textureLevel_), state.getTextureHeight(textureLevel_));
return;
}
@ -416,6 +419,8 @@ void CGEDebugger::DescribeSecondPreview(const GPUgstate &state, char desc[256])
if (showClut_) {
snprintf(desc, 256, "CLUT: 0x%08x (%d)", state.getClutAddress(), state.getClutPaletteFormat());
} else if (secondIsFramebuffer_) {
snprintf(desc, 256, "FB Tex L%d: 0x%08x (%dx%d)", textureLevel_, state.getTextureAddress(textureLevel_), state.getTextureWidth(textureLevel_), state.getTextureHeight(textureLevel_));
} else {
snprintf(desc, 256, "Texture L%d: 0x%08x (%dx%d)", textureLevel_, state.getTextureAddress(textureLevel_), state.getTextureWidth(textureLevel_), state.getTextureHeight(textureLevel_));
}
@ -658,8 +663,9 @@ void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) {
SetupPreviews();
primaryBuffer_ = nullptr;
primaryIsFramebuffer_ = false;
if (showClut_) {
bufferResult = GPU_GetCurrentTexture(primaryBuffer_, textureLevel_);
bufferResult = GPU_GetCurrentTexture(primaryBuffer_, textureLevel_, &primaryIsFramebuffer_);
flags = TexturePreviewFlags(state);
if (bufferResult) {
UpdateLastTexture(state.getTextureAddress(textureLevel_));
@ -707,10 +713,11 @@ void CGEDebugger::UpdateSecondPreview(const GPUgstate &state) {
SetupPreviews();
secondBuffer_ = nullptr;
secondIsFramebuffer_ = false;
if (showClut_) {
bufferResult = GPU_GetCurrentClut(secondBuffer_);
} else {
bufferResult = GPU_GetCurrentTexture(secondBuffer_, textureLevel_);
bufferResult = GPU_GetCurrentTexture(secondBuffer_, textureLevel_, &secondIsFramebuffer_);
if (bufferResult) {
UpdateLastTexture(state.getTextureAddress(textureLevel_));
} else {

View file

@ -139,6 +139,8 @@ private:
// The most recent primary/framebuffer and texture buffers.
const GPUDebugBuffer *primaryBuffer_ = nullptr;
const GPUDebugBuffer *secondBuffer_ = nullptr;
bool primaryIsFramebuffer_ = false;
bool secondIsFramebuffer_ = false;
uint32_t primaryTrackX_ = 0xFFFFFFFF;
uint32_t primaryTrackY_ = 0xFFFFFFFF;