mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-14 18:19:36 +01:00
Merge pull request #19733 from hrydgard/ge-debugger-merge
Ge debugger refactor: Lift even more functionality into GPUCommon
This commit is contained in:
31 files changed
+340
-375
No files matched your search
@@ -189,7 +189,7 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex
|
||||
|
||||
bool clockwise = !gstate.isCullEnabled() || gstate.getCullMode() == cullMode;
|
||||
SubmitPrim(&temp[0], nullptr, prim, vertexCount, vertTypeID, clockwise, &bytesRead);
|
||||
DispatchFlush();
|
||||
Flush();
|
||||
|
||||
if (!prevThrough) {
|
||||
gstate.vertType &= ~GE_VTYPE_THROUGH;
|
||||
@@ -924,7 +924,7 @@ int DrawEngineCommon::ExtendNonIndexedPrim(const uint32_t *cmd, const uint32_t *
|
||||
|
||||
void DrawEngineCommon::SkipPrim(GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int *bytesRead) {
|
||||
if (!indexGen.PrimCompatible(prevPrim_, prim)) {
|
||||
DispatchFlush();
|
||||
Flush();
|
||||
}
|
||||
|
||||
// This isn't exactly right, if we flushed, since prims can straddle previous calls.
|
||||
@@ -950,7 +950,7 @@ void DrawEngineCommon::SkipPrim(GEPrimitiveType prim, int vertexCount, u32 vertT
|
||||
// vertTypeID is the vertex type but with the UVGen mode smashed into the top bits.
|
||||
bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, bool clockwise, int *bytesRead) {
|
||||
if (!indexGen.PrimCompatible(prevPrim_, prim) || numDrawVerts_ >= MAX_DEFERRED_DRAW_VERTS || numDrawInds_ >= MAX_DEFERRED_DRAW_INDS || vertexCountInDrawCalls_ + vertexCount > VERTEX_BUFFER_MAX) {
|
||||
DispatchFlush();
|
||||
Flush();
|
||||
}
|
||||
_dbg_assert_(numDrawVerts_ < MAX_DEFERRED_DRAW_VERTS);
|
||||
_dbg_assert_(numDrawInds_ < MAX_DEFERRED_DRAW_INDS);
|
||||
@@ -1033,7 +1033,7 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti
|
||||
if (prim == GE_PRIM_RECTANGLES && (gstate.getTextureAddress(0) & 0x3FFFFFFF) == (gstate.getFrameBufAddress() & 0x3FFFFFFF)) {
|
||||
// This prevents issues with consecutive self-renders in Ridge Racer.
|
||||
gstate_c.Dirty(DIRTY_TEXTURE_PARAMS);
|
||||
DispatchFlush();
|
||||
Flush();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -82,6 +82,11 @@ public:
|
||||
virtual ~DrawEngineCommon();
|
||||
|
||||
void Init();
|
||||
|
||||
void SetGPUCommon(GPUCommon *gpuCommon) {
|
||||
gpuCommon_ = gpuCommon;
|
||||
}
|
||||
|
||||
virtual void DeviceLost() = 0;
|
||||
virtual void DeviceRestore(Draw::DrawContext *draw) = 0;
|
||||
|
||||
@@ -89,9 +94,8 @@ public:
|
||||
|
||||
static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType);
|
||||
|
||||
// Flush is normally non-virtual but here's a virtual way to call it, used by the shared spline code, which is expensive anyway.
|
||||
// Not really sure if these wrappers are worth it...
|
||||
virtual void DispatchFlush() = 0;
|
||||
// Dispatches the queued-up draws.
|
||||
virtual void Flush() = 0;
|
||||
|
||||
// This would seem to be unnecessary now, but is still required for splines/beziers to work in the software backend since SubmitPrim
|
||||
// is different. Should probably refactor that.
|
||||
@@ -331,4 +335,6 @@ protected:
|
||||
Vec2f minOffset_;
|
||||
Vec2f maxOffset_;
|
||||
bool offsetOutsideEdge_;
|
||||
|
||||
GPUCommon *gpuCommon_;
|
||||
};
|
||||
@@ -140,14 +140,12 @@ bool FramebufferManagerCommon::PresentedThisFrame() const {
|
||||
return presentation_->PresentedThisFrame();
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format, GPURecord::Recorder *recorder) {
|
||||
void FramebufferManagerCommon::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
displayFramebufPtr_ = framebuf & 0x3FFFFFFF;
|
||||
if (Memory::IsVRAMAddress(displayFramebufPtr_))
|
||||
displayFramebufPtr_ = framebuf & 0x041FFFFF;
|
||||
displayStride_ = stride;
|
||||
displayFormat_ = format;
|
||||
GPUDebug::NotifyDisplay(framebuf, stride, format);
|
||||
recorder->NotifyDisplay(framebuf, stride, format);
|
||||
}
|
||||
|
||||
VirtualFramebuffer *FramebufferManagerCommon::GetVFBAt(u32 addr) const {
|
||||
@@ -3258,7 +3256,7 @@ void FramebufferManagerCommon::FlushBeforeCopy() {
|
||||
// all the irrelevant state checking it'll use to decide what to do. Should
|
||||
// do something more focused here.
|
||||
SetRenderFrameBuffer(gstate_c.IsDirty(DIRTY_FRAMEBUF), gstate_c.skipDrawReason);
|
||||
drawEngine_->DispatchFlush();
|
||||
drawEngine_->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -273,10 +273,6 @@ namespace Draw {
|
||||
class DrawContext;
|
||||
}
|
||||
|
||||
namespace GPURecord {
|
||||
class Recorder;
|
||||
}
|
||||
|
||||
struct DrawPixelsEntry {
|
||||
Draw::Texture *tex;
|
||||
uint64_t contentsHash;
|
||||
@@ -306,7 +302,7 @@ public:
|
||||
|
||||
void Init(int msaaLevel);
|
||||
virtual void BeginFrame();
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format, GPURecord::Recorder *recorder);
|
||||
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format);
|
||||
void DestroyFramebuf(VirtualFramebuffer *v);
|
||||
|
||||
VirtualFramebuffer *DoSetRenderFrameBuffer(FramebufferHeuristicParams ¶ms, u32 skipDrawReason);
|
||||
|
||||
@@ -703,10 +703,10 @@ uint32_t GEExpressionFunctions::getReferenceValue(uint32_t referenceIndex) {
|
||||
return state.getTransferDstAddress();
|
||||
|
||||
case GEReferenceIndex::PRIMCOUNT:
|
||||
return GPUDebug::PrimsThisFrame();
|
||||
return gpu_->PrimsThisFrame();
|
||||
|
||||
case GEReferenceIndex::LASTPRIMCOUNT:
|
||||
return GPUDebug::PrimsLastFrame();
|
||||
return gpu_->PrimsLastFrame();
|
||||
|
||||
case GEReferenceIndex::TEXADDR0:
|
||||
case GEReferenceIndex::TEXADDR1:
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "GPU/GPUDefinitions.h"
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
|
||||
class FramebufferManagerCommon;
|
||||
class TextureCacheCommon;
|
||||
@@ -212,9 +213,6 @@ public:
|
||||
virtual void ResetListStall(int listID, u32 stall) = 0;
|
||||
virtual void ResetListState(int listID, DisplayListState state) = 0;
|
||||
|
||||
GPUDebugOp DisassembleOp(u32 pc) {
|
||||
return DisassembleOp(pc, Memory::Read_U32(pc));
|
||||
}
|
||||
virtual GPUDebugOp DisassembleOp(u32 pc, u32 op) = 0;
|
||||
virtual std::vector<GPUDebugOp> DisassembleOpRange(u32 startpc, u32 endpc) = 0;
|
||||
|
||||
@@ -225,7 +223,7 @@ public:
|
||||
// Needs to be called from the GPU thread.
|
||||
// Calling from a separate thread (e.g. UI) may fail.
|
||||
virtual void SetCmdValue(u32 op) = 0;
|
||||
virtual void DispatchFlush() = 0;
|
||||
virtual void Flush() = 0;
|
||||
|
||||
virtual void GetStats(char *buffer, size_t bufsize) = 0;
|
||||
|
||||
@@ -244,6 +242,16 @@ public:
|
||||
virtual const std::list<int> &GetDisplayListQueue() = 0;
|
||||
virtual const DisplayList &GetDisplayList(int index) = 0;
|
||||
|
||||
virtual int PrimsThisFrame() const = 0;
|
||||
virtual int PrimsLastFrame() const = 0;
|
||||
|
||||
virtual void ClearBreakNext() = 0;
|
||||
virtual void SetBreakNext(GPUDebug::BreakNext next) = 0 ;
|
||||
virtual void SetBreakCount(int c, bool relative = false) = 0 ;
|
||||
virtual GPUDebug::BreakNext GetBreakNext() = 0 ;
|
||||
virtual bool SetRestrictPrims(std::string_view rule) = 0 ;
|
||||
virtual const char *GetRestrictPrims() = 0 ;
|
||||
|
||||
virtual GPURecord::Recorder *GetRecorder() = 0;
|
||||
virtual GPUBreakpoints *GetBreakpoints() = 0;
|
||||
|
||||
|
||||
@@ -580,7 +580,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, true, &generatedBytesRead);
|
||||
|
||||
if (flushOnParams_)
|
||||
DispatchFlush();
|
||||
Flush();
|
||||
|
||||
if (origVertType & GE_VTYPE_TC_MASK) {
|
||||
gstate_c.uv = prevUVScale;
|
||||
|
||||
@@ -252,8 +252,10 @@ void DrawEngineD3D11::Invalidate(InvalidationCallbackFlags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
// The inline wrapper in the header checks for numDrawCalls_ == 0
|
||||
void DrawEngineD3D11::DoFlush() {
|
||||
void DrawEngineD3D11::Flush() {
|
||||
if (!numDrawVerts_) {
|
||||
return;
|
||||
}
|
||||
bool textureNeedsApply = false;
|
||||
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
|
||||
textureCache_->SetTexture();
|
||||
@@ -465,10 +467,6 @@ void DrawEngineD3D11::DoFlush() {
|
||||
if (gstate.isClearModeAlphaMask()) clearFlag |= Draw::FBChannel::FB_STENCIL_BIT;
|
||||
if (gstate.isClearModeDepthMask()) clearFlag |= Draw::FBChannel::FB_DEPTH_BIT;
|
||||
|
||||
if (clearFlag & Draw::FBChannel::FB_COLOR_BIT) {
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
}
|
||||
|
||||
uint8_t clearStencil = clearColor >> 24;
|
||||
draw_->Clear(clearFlag, clearColor, clearDepth, clearStencil);
|
||||
|
||||
@@ -485,7 +483,7 @@ void DrawEngineD3D11::DoFlush() {
|
||||
|
||||
ResetAfterDrawInline();
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
GPUDebug::NotifyFlush();
|
||||
gpuCommon_->NotifyFlush();
|
||||
}
|
||||
|
||||
TessellationDataTransferD3D11::TessellationDataTransferD3D11(ID3D11DeviceContext *context, ID3D11Device *device)
|
||||
|
||||
@@ -77,25 +77,12 @@ public:
|
||||
|
||||
void BeginFrame();
|
||||
|
||||
// So that this can be inlined
|
||||
void Flush() {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
DoFlush();
|
||||
}
|
||||
void Flush() override;
|
||||
|
||||
void FinishDeferred() {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
DecodeVerts(decoded_);
|
||||
}
|
||||
|
||||
void DispatchFlush() override {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
Flush();
|
||||
}
|
||||
|
||||
void NotifyConfigChanged() override;
|
||||
|
||||
void ClearInputLayoutMap();
|
||||
@@ -103,8 +90,6 @@ public:
|
||||
private:
|
||||
void Invalidate(InvalidationCallbackFlags flags);
|
||||
|
||||
void DoFlush();
|
||||
|
||||
void ApplyDrawState(int prim);
|
||||
void ApplyDrawStateLate(bool applyStencilRef, uint8_t stencilRef);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ GPU_D3D11::GPU_D3D11(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
textureCache_ = textureCacheD3D11_;
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerD3D11_;
|
||||
drawEngine_.SetGPUCommon(this);
|
||||
drawEngine_.SetShaderManager(shaderManagerD3D11_);
|
||||
drawEngine_.SetTextureCache(textureCacheD3D11_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManagerD3D11_);
|
||||
|
||||
+3
-176
@@ -18,7 +18,6 @@
|
||||
#include <vector>
|
||||
#include "Common/Log.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/TimeUtil.h"
|
||||
#include "GPU/GPU.h"
|
||||
#include "GPU/Debugger/Breakpoints.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
@@ -26,21 +25,6 @@
|
||||
|
||||
namespace GPUDebug {
|
||||
|
||||
static BreakNext breakNext = BreakNext::NONE;
|
||||
static int breakAtCount = -1;
|
||||
|
||||
static int primsLastFrame = 0;
|
||||
static int primsThisFrame = 0;
|
||||
static int thisFlipNum = 0;
|
||||
|
||||
bool g_primAfterDraw = false;
|
||||
|
||||
static double lastStepTime = -1.0;
|
||||
static uint32_t g_skipPcOnce = 0;
|
||||
|
||||
static std::vector<std::pair<int, int>> restrictPrimRanges;
|
||||
static std::string restrictPrimRule;
|
||||
|
||||
const char *BreakNextToString(BreakNext next) {
|
||||
switch (next) {
|
||||
case BreakNext::NONE: return "NONE,";
|
||||
@@ -57,152 +41,6 @@ const char *BreakNextToString(BreakNext next) {
|
||||
}
|
||||
}
|
||||
|
||||
bool NeedsSlowInterpreter() {
|
||||
return breakNext != BreakNext::NONE;
|
||||
}
|
||||
|
||||
void ClearBreak() {
|
||||
breakNext = BreakNext::NONE;
|
||||
breakAtCount = -1;
|
||||
GPUStepping::ResumeFromStepping();
|
||||
lastStepTime = -1.0;
|
||||
}
|
||||
|
||||
BreakNext GetBreakNext() {
|
||||
return breakNext;
|
||||
}
|
||||
|
||||
void SetBreakNext(BreakNext next, GPUBreakpoints *breakpoints) {
|
||||
breakNext = next;
|
||||
breakAtCount = -1;
|
||||
if (next == BreakNext::TEX) {
|
||||
breakpoints->AddTextureChangeTempBreakpoint();
|
||||
} else if (next == BreakNext::PRIM || next == BreakNext::COUNT) {
|
||||
breakpoints->AddCmdBreakpoint(GE_CMD_PRIM, true);
|
||||
breakpoints->AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
breakpoints->AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
breakpoints->AddCmdBreakpoint(GE_CMD_VAP, true);
|
||||
} else if (next == BreakNext::CURVE) {
|
||||
breakpoints->AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
breakpoints->AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
} else if (next == BreakNext::DRAW) {
|
||||
// This is now handled by switching to BreakNext::PRIM when we encounter a flush.
|
||||
// This will take us to the following actual draw.
|
||||
g_primAfterDraw = true;
|
||||
}
|
||||
|
||||
if (GPUStepping::IsStepping()) {
|
||||
GPUStepping::ResumeFromStepping();
|
||||
}
|
||||
lastStepTime = next == BreakNext::NONE ? -1.0 : time_now_d();
|
||||
}
|
||||
|
||||
void SetBreakCount(int c, bool relative) {
|
||||
if (relative) {
|
||||
breakAtCount = primsThisFrame + c;
|
||||
} else {
|
||||
breakAtCount = c;
|
||||
}
|
||||
}
|
||||
|
||||
NotifyResult NotifyCommand(u32 pc, GPUBreakpoints *breakpoints) {
|
||||
u32 op = Memory::ReadUnchecked_U32(pc);
|
||||
u32 cmd = op >> 24;
|
||||
if (thisFlipNum != gpuStats.numFlips) {
|
||||
primsLastFrame = primsThisFrame;
|
||||
primsThisFrame = 0;
|
||||
thisFlipNum = gpuStats.numFlips;
|
||||
}
|
||||
|
||||
bool process = true;
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_VAP) {
|
||||
primsThisFrame++;
|
||||
|
||||
if (!restrictPrimRanges.empty()) {
|
||||
process = false;
|
||||
for (const auto &range : restrictPrimRanges) {
|
||||
if (primsThisFrame >= range.first && primsThisFrame <= range.second) {
|
||||
process = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isBreakpoint = false;
|
||||
if (breakNext == BreakNext::OP) {
|
||||
isBreakpoint = true;
|
||||
} else if (breakNext == BreakNext::COUNT) {
|
||||
isBreakpoint = primsThisFrame == breakAtCount;
|
||||
} else if (breakpoints->HasBreakpoints()) {
|
||||
isBreakpoint = breakpoints->IsBreakpoint(pc, op);
|
||||
}
|
||||
|
||||
if (isBreakpoint && pc == g_skipPcOnce) {
|
||||
INFO_LOG(Log::GeDebugger, "Skipping GE break at %08x (last break was here)", g_skipPcOnce);
|
||||
g_skipPcOnce = 0;
|
||||
return process ? NotifyResult::Execute : NotifyResult::Skip;
|
||||
}
|
||||
g_skipPcOnce = 0;
|
||||
|
||||
if (isBreakpoint) {
|
||||
breakpoints->ClearTempBreakpoints();
|
||||
|
||||
if (coreState == CORE_POWERDOWN || !gpuDebug) {
|
||||
breakNext = BreakNext::NONE;
|
||||
return process ? NotifyResult::Execute : NotifyResult::Skip;
|
||||
}
|
||||
|
||||
auto info = gpuDebug->DisassembleOp(pc);
|
||||
if (lastStepTime >= 0.0) {
|
||||
NOTICE_LOG(Log::GeDebugger, "Waiting at %08x, %s (%fms)", pc, info.desc.c_str(), (time_now_d() - lastStepTime) * 1000.0);
|
||||
lastStepTime = -1.0;
|
||||
} else {
|
||||
NOTICE_LOG(Log::GeDebugger, "Waiting at %08x, %s", pc, info.desc.c_str());
|
||||
}
|
||||
|
||||
g_skipPcOnce = pc;
|
||||
breakNext = BreakNext::NONE;
|
||||
return NotifyResult::Break; // new. caller will call GPUStepping::EnterStepping().
|
||||
}
|
||||
|
||||
return process ? NotifyResult::Execute : NotifyResult::Skip;
|
||||
}
|
||||
|
||||
void NotifyFlush() {
|
||||
if (breakNext == BreakNext::DRAW && !GPUStepping::IsStepping()) {
|
||||
// Break on the first PRIM after a flush.
|
||||
if (g_primAfterDraw) {
|
||||
NOTICE_LOG(Log::GeDebugger, "Flush detected, breaking at next PRIM");
|
||||
g_primAfterDraw = false;
|
||||
// Switch to PRIM mode.
|
||||
SetBreakNext(BreakNext::PRIM, gpuDebug->GetBreakpoints());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyDisplay(u32 framebuf, u32 stride, int format) {
|
||||
if (breakNext == BreakNext::FRAME) {
|
||||
// Start stepping at the first op of the new frame.
|
||||
breakNext = BreakNext::OP;
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyBeginFrame() {
|
||||
if (breakNext == BreakNext::VSYNC) {
|
||||
// Just start stepping as soon as we can once the vblank finishes.
|
||||
breakNext = BreakNext::OP;
|
||||
}
|
||||
}
|
||||
|
||||
int PrimsThisFrame() {
|
||||
return primsThisFrame;
|
||||
}
|
||||
|
||||
int PrimsLastFrame() {
|
||||
return primsLastFrame;
|
||||
}
|
||||
|
||||
static bool ParseRange(const std::string &s, std::pair<int, int> &range) {
|
||||
int c = sscanf(s.c_str(), "%d-%d", &range.first, &range.second);
|
||||
if (c == 0)
|
||||
@@ -212,14 +50,9 @@ static bool ParseRange(const std::string &s, std::pair<int, int> &range) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SetRestrictPrims(const char *rule) {
|
||||
if (rule == nullptr || rule[0] == 0 || (rule[0] == '*' && rule[1] == 0)) {
|
||||
restrictPrimRanges.clear();
|
||||
restrictPrimRule.clear();
|
||||
return true;
|
||||
}
|
||||
bool ParsePrimRanges(std::string_view rule, std::vector<std::pair<int, int>> *output) {
|
||||
constexpr int MAX_PRIMS = 0x7FFFFFFF;
|
||||
|
||||
static constexpr int MAX_PRIMS = 0x7FFFFFFF;
|
||||
std::vector<std::string> parts;
|
||||
SplitString(rule, ',', parts);
|
||||
|
||||
@@ -272,14 +105,8 @@ bool SetRestrictPrims(const char *rule) {
|
||||
updated.push_back(range);
|
||||
}
|
||||
}
|
||||
|
||||
restrictPrimRanges = updated;
|
||||
restrictPrimRule = rule;
|
||||
*output = updated;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char *GetRestrictPrims() {
|
||||
return restrictPrimRule.c_str();
|
||||
}
|
||||
|
||||
}
|
||||
+5
-18
@@ -17,6 +17,9 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace GPUDebug {
|
||||
@@ -34,29 +37,13 @@ enum class BreakNext {
|
||||
COUNT,
|
||||
};
|
||||
|
||||
bool NeedsSlowInterpreter();
|
||||
|
||||
void SetBreakNext(BreakNext next, GPUBreakpoints *breakpoints);
|
||||
void SetBreakCount(int c, bool relative = false);
|
||||
BreakNext GetBreakNext();
|
||||
const char *BreakNextToString(BreakNext next);
|
||||
|
||||
enum class NotifyResult {
|
||||
Execute,
|
||||
Skip,
|
||||
Break
|
||||
};
|
||||
|
||||
// While debugging is active, these may block.
|
||||
NotifyResult NotifyCommand(u32 pc, GPUBreakpoints *breakpoints);
|
||||
void NotifyFlush();
|
||||
void NotifyDisplay(u32 framebuf, u32 stride, int format);
|
||||
void NotifyBeginFrame();
|
||||
|
||||
int PrimsThisFrame();
|
||||
int PrimsLastFrame();
|
||||
|
||||
bool SetRestrictPrims(const char *rule);
|
||||
const char *GetRestrictPrims();
|
||||
const char *BreakNextToString(GPUDebug::BreakNext next);
|
||||
bool ParsePrimRanges(std::string_view rule, std::vector<std::pair<int, int>> *output);
|
||||
|
||||
} // namespace
|
||||
@@ -45,10 +45,6 @@ static bool isStepping;
|
||||
// Number of times we've entered stepping, to detect a resume asynchronously.
|
||||
static int stepCounter = 0;
|
||||
|
||||
// Debug stats.
|
||||
static double g_timeSteppingStarted;
|
||||
static double g_timeSpentStepping;
|
||||
|
||||
static std::mutex pauseLock;
|
||||
static PauseAction pauseAction = PAUSE_CONTINUE;
|
||||
static std::mutex actionLock;
|
||||
@@ -143,7 +139,7 @@ static void RunPauseAction() {
|
||||
break;
|
||||
|
||||
case PAUSE_FLUSHDRAW:
|
||||
gpuDebug->DispatchFlush();
|
||||
gpuDebug->Flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -229,8 +229,10 @@ void DrawEngineDX9::Invalidate(InvalidationCallbackFlags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
// The inline wrapper in the header checks for numDrawCalls_ == 0
|
||||
void DrawEngineDX9::DoFlush() {
|
||||
void DrawEngineDX9::Flush() {
|
||||
if (!numDrawVerts_) {
|
||||
return;
|
||||
}
|
||||
bool textureNeedsApply = false;
|
||||
if (gstate_c.IsDirty(DIRTY_TEXTURE_IMAGE | DIRTY_TEXTURE_PARAMS) && !gstate.isModeClear() && gstate.isTextureMapEnabled()) {
|
||||
textureCache_->SetTexture();
|
||||
@@ -402,10 +404,6 @@ void DrawEngineDX9::DoFlush() {
|
||||
if (gstate.isClearModeAlphaMask()) mask |= D3DCLEAR_STENCIL;
|
||||
if (gstate.isClearModeDepthMask()) mask |= D3DCLEAR_ZBUFFER;
|
||||
|
||||
if (mask & D3DCLEAR_TARGET) {
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
}
|
||||
|
||||
device_->Clear(0, NULL, mask, SwapRB(clearColor), clearDepth, clearColor >> 24);
|
||||
|
||||
if (gstate_c.Use(GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate_c.framebufFormat == GE_FORMAT_565)) {
|
||||
@@ -421,7 +419,7 @@ void DrawEngineDX9::DoFlush() {
|
||||
|
||||
ResetAfterDrawInline();
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
GPUDebug::NotifyFlush();
|
||||
gpuCommon_->NotifyFlush();
|
||||
}
|
||||
|
||||
void TessellationDataTransferDX9::SendDataToShader(const SimpleVertex *const *points, int size_u, int size_v, u32 vertType, const Spline::Weight2D &weights) {
|
||||
|
||||
@@ -68,31 +68,18 @@ public:
|
||||
void BeginFrame();
|
||||
|
||||
// So that this can be inlined
|
||||
void Flush() {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
DoFlush();
|
||||
}
|
||||
void Flush() override;
|
||||
|
||||
void FinishDeferred() {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
DecodeVerts(decoded_);
|
||||
}
|
||||
|
||||
void DispatchFlush() override {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
Flush();
|
||||
}
|
||||
|
||||
protected:
|
||||
// Not currently supported.
|
||||
bool UpdateUseHWTessellation(bool enable) const override { return false; }
|
||||
|
||||
private:
|
||||
void Invalidate(InvalidationCallbackFlags flags);
|
||||
void DoFlush();
|
||||
|
||||
void ApplyDrawState(int prim);
|
||||
void ApplyDrawStateLate();
|
||||
|
||||
@@ -56,6 +56,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerDX9_;
|
||||
|
||||
drawEngine_.SetGPUCommon(this);
|
||||
drawEngine_.SetShaderManager(shaderManagerDX9_);
|
||||
drawEngine_.SetTextureCache(textureCacheDX9_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManagerDX9_);
|
||||
|
||||
@@ -230,7 +230,10 @@ void DrawEngineGLES::Invalidate(InvalidationCallbackFlags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
void DrawEngineGLES::DoFlush() {
|
||||
void DrawEngineGLES::Flush() {
|
||||
if (!numDrawVerts_) {
|
||||
return;
|
||||
}
|
||||
PROFILE_THIS_SCOPE("flush");
|
||||
FrameData &frameData = frameData_[render_->GetCurFrame()];
|
||||
VShaderID vsid;
|
||||
@@ -434,7 +437,6 @@ void DrawEngineGLES::DoFlush() {
|
||||
if (depthMask) target |= GL_DEPTH_BUFFER_BIT;
|
||||
|
||||
render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor_.scissorX, vpAndScissor_.scissorY, vpAndScissor_.scissorW, vpAndScissor_.scissorH);
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
|
||||
if (gstate_c.Use(GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate_c.framebufFormat == GE_FORMAT_565)) {
|
||||
int scissorX1 = gstate.getScissorX1();
|
||||
@@ -451,7 +453,7 @@ void DrawEngineGLES::DoFlush() {
|
||||
bail:
|
||||
ResetAfterDrawInline();
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
GPUDebug::NotifyFlush();
|
||||
gpuCommon_->NotifyFlush();
|
||||
}
|
||||
|
||||
// TODO: Refactor this to a single USE flag.
|
||||
|
||||
@@ -85,21 +85,8 @@ public:
|
||||
void EndFrame();
|
||||
|
||||
// So that this can be inlined
|
||||
void Flush() {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
DoFlush();
|
||||
}
|
||||
|
||||
void Flush() override;
|
||||
void FinishDeferred() {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
DoFlush();
|
||||
}
|
||||
|
||||
void DispatchFlush() override {
|
||||
if (!numDrawVerts_)
|
||||
return;
|
||||
Flush();
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerGL_;
|
||||
|
||||
drawEngine_.SetGPUCommon(this);
|
||||
drawEngine_.SetShaderManager(shaderManagerGL_);
|
||||
drawEngine_.SetTextureCache(textureCacheGL_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManagerGL_);
|
||||
|
||||
+167
-11
@@ -47,11 +47,7 @@
|
||||
#include "GPU/Debugger/Stepping.h"
|
||||
|
||||
void GPUCommon::Flush() {
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
}
|
||||
|
||||
void GPUCommon::DispatchFlush() {
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
drawEngineCommon_->Flush();
|
||||
}
|
||||
|
||||
GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) :
|
||||
@@ -624,7 +620,11 @@ void GPUCommon::PSPFrame() {
|
||||
} else if (dumpThisFrame_) {
|
||||
dumpThisFrame_ = false;
|
||||
}
|
||||
GPUDebug::NotifyBeginFrame();
|
||||
|
||||
if (breakNext == GPUDebug::BreakNext::VSYNC) {
|
||||
// Just start stepping as soon as we can once the vblank finishes.
|
||||
breakNext = GPUDebug::BreakNext::OP;
|
||||
}
|
||||
recorder_.NotifyBeginFrame();
|
||||
}
|
||||
|
||||
@@ -632,7 +632,7 @@ void GPUCommon::PSPFrame() {
|
||||
bool GPUCommon::SlowRunLoop(DisplayList &list) {
|
||||
const bool dumpThisFrame = dumpThisFrame_;
|
||||
while (downcount > 0) {
|
||||
GPUDebug::NotifyResult result = GPUDebug::NotifyCommand(list.pc, &breakpoints_);
|
||||
GPUDebug::NotifyResult result = NotifyCommand(list.pc, &breakpoints_);
|
||||
|
||||
if (result == GPUDebug::NotifyResult::Execute) {
|
||||
recorder_.NotifyCommand(list.pc);
|
||||
@@ -791,7 +791,7 @@ DLResult GPUCommon::ProcessDLQueue() {
|
||||
|
||||
// To enable breakpoints, we don't do fast matrix loads while debugger active.
|
||||
debugRecording_ = recorder_.IsActive();
|
||||
useFastRunLoop_ = !(dumpThisFrame_ || debugRecording_ || GPUDebug::NeedsSlowInterpreter() || breakpoints_.HasBreakpoints());
|
||||
useFastRunLoop_ = !(dumpThisFrame_ || debugRecording_ || NeedsSlowInterpreter() || breakpoints_.HasBreakpoints());
|
||||
} else {
|
||||
resumingFromDebugBreak_ = false;
|
||||
// The bottom part of the gpuState loop below, that wasn't executed
|
||||
@@ -882,7 +882,7 @@ DLResult GPUCommon::ProcessDLQueue() {
|
||||
bool GPUCommon::ShouldSplitOverGe() const {
|
||||
// Check for debugger active.
|
||||
// We only need to do this if we want to be able to step through Ge display lists using the Ge debuggers.
|
||||
return GPUDebug::NeedsSlowInterpreter() || breakpoints_.HasBreakpoints();
|
||||
return NeedsSlowInterpreter() || breakpoints_.HasBreakpoints();
|
||||
}
|
||||
|
||||
void GPUCommon::Execute_OffsetAddr(u32 op, u32 diff) {
|
||||
@@ -1348,7 +1348,7 @@ void GPUCommon::FlushImm() {
|
||||
bool changed = texturing != prevTexturing || cullEnable != prevCullEnable || dither != prevDither;
|
||||
changed = changed || prevShading != shading || prevFog != fog;
|
||||
if (changed) {
|
||||
DispatchFlush();
|
||||
Flush();
|
||||
gstate.antiAliasEnable = (GE_CMD_ANTIALIASENABLE << 24) | (int)antialias;
|
||||
gstate.shademodel = (GE_CMD_SHADEMODE << 24) | (int)shading;
|
||||
gstate.cullfaceEnable = (GE_CMD_CULLFACEENABLE << 24) | (int)cullEnable;
|
||||
@@ -1363,7 +1363,7 @@ void GPUCommon::FlushImm() {
|
||||
immFirstSent_ = true;
|
||||
|
||||
if (changed) {
|
||||
DispatchFlush();
|
||||
Flush();
|
||||
gstate.antiAliasEnable = (GE_CMD_ANTIALIASENABLE << 24) | (int)prevAntialias;
|
||||
gstate.shademodel = (GE_CMD_SHADEMODE << 24) | (int)prevShading;
|
||||
gstate.cullfaceEnable = (GE_CMD_CULLFACEENABLE << 24) | (int)prevCullEnable;
|
||||
@@ -2007,3 +2007,159 @@ bool GPUCommon::DescribeCodePtr(const u8 *ptr, std::string &name) {
|
||||
return drawEngineCommon_->DescribeCodePtr(ptr, name);
|
||||
}
|
||||
|
||||
bool GPUCommon::NeedsSlowInterpreter() const {
|
||||
return breakNext != GPUDebug::BreakNext::NONE;
|
||||
}
|
||||
|
||||
void GPUCommon::ClearBreakNext() {
|
||||
breakNext = GPUDebug::BreakNext::NONE;
|
||||
breakAtCount = -1;
|
||||
GPUStepping::ResumeFromStepping();
|
||||
}
|
||||
|
||||
GPUDebug::BreakNext GPUCommon::GetBreakNext() {
|
||||
return breakNext;
|
||||
}
|
||||
|
||||
void GPUCommon::SetBreakNext(GPUDebug::BreakNext next) {
|
||||
breakNext = next;
|
||||
breakAtCount = -1;
|
||||
switch (next) {
|
||||
case GPUDebug::BreakNext::TEX:
|
||||
breakpoints_.AddTextureChangeTempBreakpoint();
|
||||
break;
|
||||
case GPUDebug::BreakNext::PRIM:
|
||||
case GPUDebug::BreakNext::COUNT:
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_PRIM, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_VAP, true);
|
||||
break;
|
||||
case GPUDebug::BreakNext::CURVE:
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
break;
|
||||
case GPUDebug::BreakNext::DRAW:
|
||||
// This is now handled by switching to BreakNext::PRIM when we encounter a flush.
|
||||
// This will take us to the following actual draw.
|
||||
primAfterDraw_ = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (GPUStepping::IsStepping()) {
|
||||
GPUStepping::ResumeFromStepping();
|
||||
}
|
||||
}
|
||||
|
||||
void GPUCommon::SetBreakCount(int c, bool relative) {
|
||||
if (relative) {
|
||||
breakAtCount = primsThisFrame + c;
|
||||
} else {
|
||||
breakAtCount = c;
|
||||
}
|
||||
}
|
||||
|
||||
GPUDebug::NotifyResult GPUCommon::NotifyCommand(u32 pc, GPUBreakpoints *breakpoints) {
|
||||
using namespace GPUDebug;
|
||||
|
||||
u32 op = Memory::ReadUnchecked_U32(pc);
|
||||
u32 cmd = op >> 24;
|
||||
if (thisFlipNum != gpuStats.numFlips) {
|
||||
primsLastFrame = primsThisFrame;
|
||||
primsThisFrame = 0;
|
||||
thisFlipNum = gpuStats.numFlips;
|
||||
}
|
||||
|
||||
bool process = true;
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_VAP) {
|
||||
primsThisFrame++;
|
||||
|
||||
if (!restrictPrimRanges.empty()) {
|
||||
process = false;
|
||||
for (const auto &range : restrictPrimRanges) {
|
||||
if (primsThisFrame >= range.first && primsThisFrame <= range.second) {
|
||||
process = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool isBreakpoint = false;
|
||||
if (breakNext == BreakNext::OP) {
|
||||
isBreakpoint = true;
|
||||
} else if (breakNext == BreakNext::COUNT) {
|
||||
isBreakpoint = primsThisFrame == breakAtCount;
|
||||
} else if (breakpoints->HasBreakpoints()) {
|
||||
isBreakpoint = breakpoints->IsBreakpoint(pc, op);
|
||||
}
|
||||
|
||||
if (isBreakpoint && pc == g_skipPcOnce) {
|
||||
INFO_LOG(Log::GeDebugger, "Skipping GE break at %08x (last break was here)", g_skipPcOnce);
|
||||
g_skipPcOnce = 0;
|
||||
return process ? NotifyResult::Execute : NotifyResult::Skip;
|
||||
}
|
||||
g_skipPcOnce = 0;
|
||||
|
||||
if (isBreakpoint) {
|
||||
breakpoints->ClearTempBreakpoints();
|
||||
|
||||
if (coreState == CORE_POWERDOWN) {
|
||||
breakNext = BreakNext::NONE;
|
||||
return process ? NotifyResult::Execute : NotifyResult::Skip;
|
||||
}
|
||||
|
||||
u32 op = Memory::Read_U32(pc);
|
||||
auto info = DisassembleOp(pc, op);
|
||||
NOTICE_LOG(Log::GeDebugger, "Waiting at %08x, %s", pc, info.desc.c_str());
|
||||
|
||||
g_skipPcOnce = pc;
|
||||
breakNext = BreakNext::NONE;
|
||||
return NotifyResult::Break; // new. caller will call GPUStepping::EnterStepping().
|
||||
}
|
||||
|
||||
return process ? NotifyResult::Execute : NotifyResult::Skip;
|
||||
}
|
||||
|
||||
void GPUCommon::NotifyFlush() {
|
||||
using namespace GPUDebug;
|
||||
if (breakNext == BreakNext::DRAW && !GPUStepping::IsStepping()) {
|
||||
// Break on the first PRIM after a flush.
|
||||
if (primAfterDraw_) {
|
||||
NOTICE_LOG(Log::GeDebugger, "Flush detected, breaking at next PRIM");
|
||||
primAfterDraw_ = false;
|
||||
// Switch to PRIM mode.
|
||||
SetBreakNext(BreakNext::PRIM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPUCommon::NotifyDisplay(u32 framebuf, u32 stride, int format) {
|
||||
using namespace GPUDebug;
|
||||
if (breakNext == BreakNext::FRAME) {
|
||||
// Start stepping at the first op of the new frame.
|
||||
breakNext = BreakNext::OP;
|
||||
}
|
||||
recorder_.NotifyDisplay(framebuf, stride, format);
|
||||
}
|
||||
|
||||
bool GPUCommon::SetRestrictPrims(std::string_view rule) {
|
||||
if (rule.empty() || rule == "*") {
|
||||
restrictPrimRanges.clear();
|
||||
restrictPrimRule.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (GPUDebug::ParsePrimRanges(rule, &restrictPrimRanges)) {
|
||||
restrictPrimRule = rule;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const char *GPUCommon::GetRestrictPrims() {
|
||||
return restrictPrimRule.c_str();
|
||||
}
|
||||
+40
-3
@@ -14,6 +14,7 @@
|
||||
#include "GPU/GPUState.h"
|
||||
#include "GPU/Debugger/Record.h"
|
||||
#include "GPU/Debugger/Breakpoints.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
#include "GPU/Common/ShaderCommon.h"
|
||||
#include "GPU/Common/GPUDebugInterface.h"
|
||||
#include "GPU/GPUDefinitions.h"
|
||||
@@ -305,9 +306,7 @@ public:
|
||||
|
||||
static int EstimatePerVertexCost();
|
||||
|
||||
// Note: Not virtual!
|
||||
void Flush();
|
||||
void DispatchFlush() override;
|
||||
|
||||
#ifdef USE_CRT_DBG
|
||||
#undef new
|
||||
@@ -386,7 +385,29 @@ public:
|
||||
return &breakpoints_;
|
||||
}
|
||||
|
||||
void ClearBreakNext() override;
|
||||
void SetBreakNext(GPUDebug::BreakNext next) override;
|
||||
void SetBreakCount(int c, bool relative = false) override;
|
||||
GPUDebug::BreakNext GetBreakNext() override;
|
||||
bool SetRestrictPrims(std::string_view rule) override;
|
||||
const char *GetRestrictPrims() override;
|
||||
|
||||
int PrimsThisFrame() const override {
|
||||
return primsThisFrame;
|
||||
}
|
||||
int PrimsLastFrame() const override {
|
||||
return primsLastFrame;
|
||||
}
|
||||
|
||||
void NotifyFlush();
|
||||
|
||||
protected:
|
||||
// While debugging is active, these may block.
|
||||
void NotifyDisplay(u32 framebuf, u32 stride, int format);
|
||||
|
||||
bool NeedsSlowInterpreter() const;
|
||||
GPUDebug::NotifyResult NotifyCommand(u32 pc, GPUBreakpoints *breakpoints);
|
||||
|
||||
virtual void ClearCacheNextFrame() {}
|
||||
|
||||
virtual void CheckRenderResized() {}
|
||||
@@ -469,7 +490,6 @@ protected:
|
||||
bool dumpNextFrame_ = false;
|
||||
bool dumpThisFrame_ = false;
|
||||
bool useFastRunLoop_ = false;
|
||||
bool debugRecording_ = false;
|
||||
bool interruptsEnabled_ = false;
|
||||
bool displayResized_ = false;
|
||||
bool renderResized_ = false;
|
||||
@@ -510,9 +530,26 @@ protected:
|
||||
std::string reportingPrimaryInfo_;
|
||||
std::string reportingFullInfo_;
|
||||
|
||||
// Debugging state
|
||||
bool debugRecording_ = false;
|
||||
|
||||
GPURecord::Recorder recorder_;
|
||||
GPUBreakpoints breakpoints_;
|
||||
|
||||
GPUDebug::BreakNext breakNext = GPUDebug::BreakNext::NONE;
|
||||
int breakAtCount = -1;
|
||||
|
||||
int primsLastFrame = 0;
|
||||
int primsThisFrame = 0;
|
||||
int thisFlipNum = 0;
|
||||
|
||||
bool primAfterDraw_ = false;
|
||||
|
||||
uint32_t g_skipPcOnce = 0;
|
||||
|
||||
std::vector<std::pair<int, int>> restrictPrimRanges;
|
||||
std::string restrictPrimRule;
|
||||
|
||||
private:
|
||||
void DoExecuteCall(u32 target);
|
||||
void PopDLQueue();
|
||||
|
||||
+9
-7
@@ -13,6 +13,7 @@
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
#include "GPU/Common/FramebufferManagerCommon.h"
|
||||
#include "GPU/Debugger/Debugger.h"
|
||||
|
||||
struct CommonCommandTableEntry {
|
||||
uint8_t cmd;
|
||||
@@ -512,7 +513,8 @@ void GPUCommonHW::BeginHostFrame() {
|
||||
}
|
||||
|
||||
void GPUCommonHW::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) {
|
||||
framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format, &recorder_);
|
||||
framebufferManager_->SetDisplayFramebuffer(framebuf, stride, format);
|
||||
NotifyDisplay(framebuf, stride, format);
|
||||
}
|
||||
|
||||
void GPUCommonHW::CheckFlushOp(int cmd, u32 diff) {
|
||||
@@ -521,7 +523,7 @@ void GPUCommonHW::CheckFlushOp(int cmd, u32 diff) {
|
||||
if (dumpThisFrame_) {
|
||||
NOTICE_LOG(Log::G3D, "================ FLUSH ================");
|
||||
}
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
drawEngineCommon_->Flush();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,7 +533,7 @@ void GPUCommonHW::PreExecuteOp(u32 op, u32 diff) {
|
||||
|
||||
void GPUCommonHW::CopyDisplayToOutput(bool reallyDirty) {
|
||||
// Flush anything left over.
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
drawEngineCommon_->Flush();
|
||||
|
||||
shaderManager_->DirtyLastShader();
|
||||
|
||||
@@ -847,7 +849,7 @@ void GPUCommonHW::FastRunLoop(DisplayList &list) {
|
||||
} else {
|
||||
uint64_t flags = info.flags;
|
||||
if (flags & FLAG_FLUSHBEFOREONCHANGE) {
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
drawEngineCommon_->Flush();
|
||||
}
|
||||
gstate.cmdmem[cmd] = op;
|
||||
if (flags & (FLAG_EXECUTE | FLAG_EXECUTEONCHANGE)) {
|
||||
@@ -1253,7 +1255,7 @@ bail:
|
||||
// flush back cull mode
|
||||
if (cullMode != gstate.getCullMode()) {
|
||||
// We rewrote everything to the old cull mode, so flush first.
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
drawEngineCommon_->Flush();
|
||||
|
||||
// Now update things for next time.
|
||||
gstate.cmdmem[GE_CMD_CULL] ^= 1;
|
||||
@@ -1300,7 +1302,7 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) {
|
||||
|
||||
// Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already.
|
||||
if (flushOnParams_)
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
drawEngineCommon_->Flush();
|
||||
|
||||
Spline::BezierSurface surface;
|
||||
surface.tess_u = gstate.getPatchDivisionU();
|
||||
@@ -1372,7 +1374,7 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) {
|
||||
|
||||
// Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already.
|
||||
if (flushOnParams_)
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
drawEngineCommon_->Flush();
|
||||
|
||||
Spline::SplineSurface surface;
|
||||
surface.tess_u = gstate.getPatchDivisionU();
|
||||
|
||||
+14
-13
@@ -436,6 +436,7 @@ SoftGPU::SoftGPU(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
if (!drawEngine_)
|
||||
return;
|
||||
|
||||
drawEngine_->SetGPUCommon(this);
|
||||
drawEngine_->Init();
|
||||
drawEngineCommon_ = drawEngine_;
|
||||
|
||||
@@ -493,8 +494,8 @@ void SoftGPU::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for
|
||||
displayFramebuf_ = (framebuf & 0xFF000000) == 0 ? 0x44000000 | framebuf : framebuf;
|
||||
displayStride_ = stride;
|
||||
displayFormat_ = format;
|
||||
GPUDebug::NotifyDisplay(framebuf, stride, format);
|
||||
recorder_.NotifyDisplay(framebuf, stride, format);
|
||||
|
||||
NotifyDisplay(framebuf, stride, format);
|
||||
}
|
||||
|
||||
DSStretch g_DarkStalkerStretch;
|
||||
@@ -651,7 +652,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) {
|
||||
}
|
||||
|
||||
void SoftGPU::CopyDisplayToOutput(bool reallyDirty) {
|
||||
drawEngine_->transformUnit.Flush("output");
|
||||
drawEngine_->transformUnit.Flush(this, "output");
|
||||
// The display always shows 480x272.
|
||||
CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT);
|
||||
MarkDirty(displayFramebuf_, displayStride_, 272, displayFormat_, SoftGPUVRAMDirty::CLEAR);
|
||||
@@ -839,10 +840,10 @@ void SoftGPU::Execute_BlockTransferStart(u32 op, u32 diff) {
|
||||
|
||||
// Need to flush both source and target, so we overwrite properly.
|
||||
if (Memory::IsValidRange(src, srcSize) && Memory::IsValidRange(dst, dstSize)) {
|
||||
drawEngine_->transformUnit.FlushIfOverlap("blockxfer", false, src, srcStride, width * bpp, height);
|
||||
drawEngine_->transformUnit.FlushIfOverlap("blockxfer", true, dst, dstStride, width * bpp, height);
|
||||
drawEngine_->transformUnit.FlushIfOverlap(this, "blockxfer", false, src, srcStride, width * bpp, height);
|
||||
drawEngine_->transformUnit.FlushIfOverlap(this, "blockxfer", true, dst, dstStride, width * bpp, height);
|
||||
} else {
|
||||
drawEngine_->transformUnit.Flush("blockxfer_wrap");
|
||||
drawEngine_->transformUnit.Flush(this, "blockxfer_wrap");
|
||||
}
|
||||
|
||||
DoBlockTransfer(gstate_c.skipDrawReason);
|
||||
@@ -1004,7 +1005,7 @@ void SoftGPU::Execute_LoadClut(u32 op, u32 diff) {
|
||||
clutTotalBytes = 1024;
|
||||
|
||||
// Might be copying drawing into the CLUT, so flush.
|
||||
drawEngine_->transformUnit.FlushIfOverlap("loadclut", false, clutAddr, clutTotalBytes, clutTotalBytes, 1);
|
||||
drawEngine_->transformUnit.FlushIfOverlap(this, "loadclut", false, clutAddr, clutTotalBytes, clutTotalBytes, 1);
|
||||
|
||||
bool changed = false;
|
||||
if (Memory::IsValidAddress(clutAddr)) {
|
||||
@@ -1032,7 +1033,7 @@ void SoftGPU::Execute_LoadClut(u32 op, u32 diff) {
|
||||
void SoftGPU::Execute_FramebufPtr(u32 op, u32 diff) {
|
||||
// We assume fb.data won't change while we're drawing.
|
||||
if (diff) {
|
||||
drawEngine_->transformUnit.Flush("framebuf");
|
||||
drawEngine_->transformUnit.Flush(this, "framebuf");
|
||||
fb.data = Memory::GetPointerWrite(gstate.getFrameBufAddress());
|
||||
}
|
||||
}
|
||||
@@ -1040,7 +1041,7 @@ void SoftGPU::Execute_FramebufPtr(u32 op, u32 diff) {
|
||||
void SoftGPU::Execute_FramebufFormat(u32 op, u32 diff) {
|
||||
// We should flush, because ranges within bins may change.
|
||||
if (diff)
|
||||
drawEngine_->transformUnit.Flush("framebuf");
|
||||
drawEngine_->transformUnit.Flush(this, "framebuf");
|
||||
}
|
||||
|
||||
void SoftGPU::Execute_BoundingBox(u32 op, u32 diff) {
|
||||
@@ -1051,7 +1052,7 @@ void SoftGPU::Execute_BoundingBox(u32 op, u32 diff) {
|
||||
void SoftGPU::Execute_ZbufPtr(u32 op, u32 diff) {
|
||||
// We assume depthbuf.data won't change while we're drawing.
|
||||
if (diff) {
|
||||
drawEngine_->transformUnit.Flush("depthbuf");
|
||||
drawEngine_->transformUnit.Flush(this, "depthbuf");
|
||||
// For the pointer, ignore memory mirrors. This also gives some buffer for draws that go outside.
|
||||
// TODO: Confirm how wrapping is handled in drawing. Adjust if we ever handle VRAM mirrors more accurately.
|
||||
depthbuf.data = Memory::GetPointerWrite(gstate.getDepthBufAddress() & 0x041FFFF0);
|
||||
@@ -1272,18 +1273,18 @@ void SoftGPU::Execute_Call(u32 op, u32 diff) {
|
||||
|
||||
void SoftGPU::FinishDeferred() {
|
||||
// Need to flush before going back to CPU, so drawing is appropriately visible.
|
||||
drawEngine_->transformUnit.Flush("finish");
|
||||
drawEngine_->transformUnit.Flush(this, "finish");
|
||||
}
|
||||
|
||||
int SoftGPU::ListSync(int listid, int mode) {
|
||||
// Take this as a cue that we need to finish drawing.
|
||||
drawEngine_->transformUnit.Flush("listsync");
|
||||
drawEngine_->transformUnit.Flush(this, "listsync");
|
||||
return GPUCommon::ListSync(listid, mode);
|
||||
}
|
||||
|
||||
u32 SoftGPU::DrawSync(int mode) {
|
||||
// Take this as a cue that we need to finish drawing.
|
||||
drawEngine_->transformUnit.Flush("drawsync");
|
||||
drawEngine_->transformUnit.Flush(this, "drawsync");
|
||||
return GPUCommon::DrawSync(mode);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ void SoftwareDrawEngine::NotifyConfigChanged() {
|
||||
decOptions_.applySkinInDecode = true;
|
||||
}
|
||||
|
||||
void SoftwareDrawEngine::DispatchFlush() {
|
||||
transformUnit.Flush("debug");
|
||||
void SoftwareDrawEngine::Flush() {
|
||||
transformUnit.Flush(gpuCommon_, "debug");
|
||||
}
|
||||
|
||||
void SoftwareDrawEngine::DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, bool clockwise, int *bytesRead) {
|
||||
@@ -891,12 +891,12 @@ void TransformUnit::SendTriangle(CullType cullType, const ClipVertexData *verts,
|
||||
}
|
||||
}
|
||||
|
||||
void TransformUnit::Flush(const char *reason) {
|
||||
void TransformUnit::Flush(GPUCommon *common, const char *reason) {
|
||||
if (!hasDraws_)
|
||||
return;
|
||||
|
||||
binner_->Flush(reason);
|
||||
GPUDebug::NotifyFlush();
|
||||
common->NotifyFlush();
|
||||
hasDraws_ = false;
|
||||
}
|
||||
|
||||
@@ -905,14 +905,14 @@ void TransformUnit::GetStats(char *buffer, size_t bufsize) {
|
||||
binner_->GetStats(buffer, bufsize);
|
||||
}
|
||||
|
||||
void TransformUnit::FlushIfOverlap(const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h) {
|
||||
void TransformUnit::FlushIfOverlap(GPUCommon *common, const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h) {
|
||||
if (!hasDraws_)
|
||||
return;
|
||||
|
||||
if (binner_->HasPendingWrite(addr, stride, w, h))
|
||||
Flush(reason);
|
||||
Flush(common, reason);
|
||||
if (modifying && binner_->HasPendingRead(addr, stride, w, h))
|
||||
Flush(reason);
|
||||
Flush(common, reason);
|
||||
}
|
||||
|
||||
void TransformUnit::NotifyClutUpdate(const void *src) {
|
||||
|
||||
@@ -141,8 +141,8 @@ public:
|
||||
|
||||
static bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
|
||||
|
||||
void Flush(const char *reason);
|
||||
void FlushIfOverlap(const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h);
|
||||
void Flush(GPUCommon *common, const char *reason);
|
||||
void FlushIfOverlap(GPUCommon *common, const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h);
|
||||
void NotifyClutUpdate(const void *src);
|
||||
|
||||
void GetStats(char *buffer, size_t bufsize);
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
void DeviceRestore(Draw::DrawContext *draw) override {}
|
||||
|
||||
void NotifyConfigChanged() override;
|
||||
void DispatchFlush() override;
|
||||
void Flush() override;
|
||||
void DispatchSubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertType, bool clockwise, int *bytesRead) override;
|
||||
void DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex *buffer, int vertexCount, int cullMode, bool continuation) override;
|
||||
|
||||
|
||||
@@ -216,7 +216,11 @@ void DrawEngineVulkan::Invalidate(InvalidationCallbackFlags flags) {
|
||||
}
|
||||
|
||||
// The inline wrapper in the header checks for numDrawCalls_ == 0
|
||||
void DrawEngineVulkan::DoFlush() {
|
||||
void DrawEngineVulkan::Flush() {
|
||||
if (!numDrawVerts_) {
|
||||
return;
|
||||
}
|
||||
|
||||
VulkanRenderManager *renderManager = (VulkanRenderManager *)draw_->GetNativeObject(Draw::NativeObject::RENDER_MANAGER);
|
||||
|
||||
renderManager->AssertInRenderPass();
|
||||
@@ -551,9 +555,6 @@ void DrawEngineVulkan::DoFlush() {
|
||||
// Note that since the alpha channel and the stencil channel are shared on the PSP,
|
||||
// when we clear alpha, we also clear stencil to the same value.
|
||||
draw_->Clear(mask, result.color, result.depth, result.color >> 24);
|
||||
if (clearColor || clearAlpha) {
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
}
|
||||
if (gstate_c.Use(GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
|
||||
int scissorX1 = gstate.getScissorX1();
|
||||
int scissorY1 = gstate.getScissorY1();
|
||||
@@ -569,7 +570,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
|
||||
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
|
||||
|
||||
GPUDebug::NotifyFlush();
|
||||
gpuCommon_->NotifyFlush();
|
||||
}
|
||||
|
||||
void DrawEngineVulkan::ResetAfterDraw() {
|
||||
|
||||
@@ -123,26 +123,13 @@ public:
|
||||
void DeviceLost() override;
|
||||
void DeviceRestore(Draw::DrawContext *draw) override;
|
||||
|
||||
// So that this can be inlined
|
||||
void Flush() {
|
||||
if (!numDrawInds_)
|
||||
return;
|
||||
DoFlush();
|
||||
}
|
||||
void Flush() override;
|
||||
|
||||
void FinishDeferred() {
|
||||
if (!numDrawInds_)
|
||||
return;
|
||||
// Decode any pending vertices. And also flush while we're at it, for simplicity.
|
||||
// It might be possible to only decode like in the other backends, but meh, it can't matter.
|
||||
// Issue #10095 has a nice example of where this is required.
|
||||
DoFlush();
|
||||
}
|
||||
|
||||
void DispatchFlush() override {
|
||||
if (!numDrawInds_)
|
||||
return;
|
||||
DoFlush();
|
||||
Flush();
|
||||
}
|
||||
|
||||
VKRPipelineLayout *GetPipelineLayout() const {
|
||||
@@ -183,7 +170,6 @@ private:
|
||||
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
void DoFlush();
|
||||
void UpdateUBOs();
|
||||
|
||||
NO_INLINE void ResetAfterDraw();
|
||||
|
||||
@@ -64,6 +64,7 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *gfxCtx, Draw::DrawContext *draw)
|
||||
drawEngineCommon_ = &drawEngine_;
|
||||
shaderManager_ = shaderManagerVulkan_;
|
||||
|
||||
drawEngine_.SetGPUCommon(this);
|
||||
drawEngine_.SetTextureCache(textureCacheVulkan_);
|
||||
drawEngine_.SetFramebufferManager(framebufferManagerVulkan_);
|
||||
drawEngine_.SetShaderManager(shaderManagerVulkan_);
|
||||
|
||||
+14
-12
@@ -150,7 +150,8 @@ void ImGeDisasmView::Draw(GPUDebugInterface *gpuDebug) {
|
||||
if (Memory::IsValid4AlignedAddress(addr)) {
|
||||
draw_list->AddText(lineStart, 0xFFC0C0C0, addrBuffer);
|
||||
|
||||
GPUDebugOp op = gpuDebug->DisassembleOp(addr);
|
||||
u32 opcode = Memory::Read_U32(addr);
|
||||
GPUDebugOp op = gpuDebug->DisassembleOp(addr, opcode);
|
||||
u32 color = 0xFFFFFFFF;
|
||||
char temp[16];
|
||||
snprintf(temp, sizeof(temp), "%08x", op.op);
|
||||
@@ -212,7 +213,8 @@ void ImGeDisasmView::Draw(GPUDebugInterface *gpuDebug) {
|
||||
}
|
||||
} else if (Memory::IsValid4AlignedAddress(dragAddr_)) {
|
||||
char buffer[64];
|
||||
GPUDebugOp op = gpuDebug->DisassembleOp(pc);
|
||||
u32 opcode = Memory::Read_U32(dragAddr_);
|
||||
GPUDebugOp op = gpuDebug->DisassembleOp(dragAddr_, opcode);
|
||||
// affect dragAddr_?
|
||||
if (ImGui::MenuItem("Copy Address", NULL, false)) {
|
||||
snprintf(buffer, sizeof(buffer), "%08x", dragAddr_);
|
||||
@@ -359,34 +361,34 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
||||
// GPUDebug::SetBreakNext(GPUDebug::BreakNext::FRAME);
|
||||
//}
|
||||
|
||||
bool disableStepButtons = GPUDebug::GetBreakNext() != GPUDebug::BreakNext::NONE;
|
||||
bool disableStepButtons = gpuDebug->GetBreakNext() != GPUDebug::BreakNext::NONE;
|
||||
|
||||
if (disableStepButtons) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Tex")) {
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::TEX, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::TEX);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("NonTex")) {
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::NONTEX, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::NONTEX);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Prim")) {
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::PRIM, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::PRIM);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Draw")) {
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::DRAW, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::DRAW);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Curve")) {
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::CURVE, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::CURVE);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Single step")) {
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::OP, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::OP);
|
||||
}
|
||||
if (disableStepButtons) {
|
||||
ImGui::EndDisabled();
|
||||
@@ -406,15 +408,15 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterfa
|
||||
}
|
||||
|
||||
// Display any pending step event.
|
||||
if (GPUDebug::GetBreakNext() != GPUDebug::BreakNext::NONE) {
|
||||
if (gpuDebug->GetBreakNext() != GPUDebug::BreakNext::NONE) {
|
||||
if (showBannerInFrames_ > 0) {
|
||||
showBannerInFrames_--;
|
||||
}
|
||||
if (showBannerInFrames_ == 0) {
|
||||
ImGui::Text("Step pending (waiting for CPU): %s", GPUDebug::BreakNextToString(GPUDebug::GetBreakNext()));
|
||||
ImGui::Text("Step pending (waiting for CPU): %s", GPUDebug::BreakNextToString(gpuDebug->GetBreakNext()));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel step")) {
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::NONE, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->ClearBreakNext();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -341,7 +341,8 @@ void CtrlDisplayListView::onMouseUp(WPARAM wParam, LPARAM lParam, int button)
|
||||
char *p = temp, *end = temp + space;
|
||||
for (u32 pos = selectRangeStart; pos < selectRangeEnd && p < end; pos += instructionSize)
|
||||
{
|
||||
GPUDebugOp op = gpuDebug->DisassembleOp(pos);
|
||||
u32 opcode = Memory::Read_U32(pos);
|
||||
GPUDebugOp op = gpuDebug->DisassembleOp(pos, opcode);
|
||||
p += snprintf(p, end - p, "%s\r\n", op.desc.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -135,8 +135,8 @@ StepCountDlg::~StepCountDlg() {
|
||||
void StepCountDlg::Jump(int count, bool relative) {
|
||||
if (relative && count == 0)
|
||||
return;
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::COUNT, gpuDebug->GetBreakpoints());
|
||||
GPUDebug::SetBreakCount(count, relative);
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::COUNT);
|
||||
gpuDebug->SetBreakCount(count, relative);
|
||||
};
|
||||
|
||||
BOOL StepCountDlg::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
@@ -577,7 +577,7 @@ void CGEDebugger::UpdatePreviews() {
|
||||
}
|
||||
|
||||
wchar_t primCounter[1024]{};
|
||||
swprintf(primCounter, ARRAY_SIZE(primCounter), L"%d/%d", GPUDebug::PrimsThisFrame(), GPUDebug::PrimsLastFrame());
|
||||
swprintf(primCounter, ARRAY_SIZE(primCounter), L"%d/%d", gpuDebug->PrimsThisFrame(), gpuDebug->PrimsLastFrame());
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_PRIMCOUNTER, primCounter);
|
||||
|
||||
for (GEDebuggerTab &tabState : tabStates_) {
|
||||
@@ -989,31 +989,31 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
case WM_COMMAND:
|
||||
switch (LOWORD(wParam)) {
|
||||
case IDC_GEDBG_STEPDRAW:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::DRAW, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::DRAW);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEP:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::OP, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::OP);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPTEX:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::TEX, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::TEX);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPFRAME:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::FRAME, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::FRAME);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPVSYNC:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::VSYNC, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::VSYNC);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPPRIM:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::PRIM, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::PRIM);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPCURVE:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::CURVE, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::CURVE);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_STEPCOUNT:
|
||||
@@ -1078,7 +1078,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_TEXADDR, L"");
|
||||
SetDlgItemText(m_hDlg, IDC_GEDBG_PRIMCOUNTER, L"");
|
||||
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::NONE, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::NONE);
|
||||
break;
|
||||
|
||||
case IDC_GEDBG_RECORD:
|
||||
@@ -1116,9 +1116,9 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
|
||||
case IDC_GEDBG_SETPRIMFILTER:
|
||||
{
|
||||
std::string value = GPUDebug::GetRestrictPrims();
|
||||
std::string value = gpuDebug->GetRestrictPrims();
|
||||
if (InputBox_GetString(GetModuleHandle(NULL), m_hDlg, L"Prim counter ranges", value, value)) {
|
||||
GPUDebug::SetRestrictPrims(value.c_str());
|
||||
gpuDebug->SetRestrictPrims(value.c_str());
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1126,7 +1126,7 @@ BOOL CGEDebugger::DlgProc(UINT message, WPARAM wParam, LPARAM lParam) {
|
||||
break;
|
||||
|
||||
case WM_GEDBG_STEPDISPLAYLIST:
|
||||
GPUDebug::SetBreakNext(GPUDebug::BreakNext::OP, gpuDebug->GetBreakpoints());
|
||||
gpuDebug->SetBreakNext(GPUDebug::BreakNext::OP);
|
||||
break;
|
||||
|
||||
case WM_GEDBG_TOGGLEPCBREAKPOINT:
|
||||
|
||||
Reference in new issue
Block a user