mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Fix the ImGe debugger vertex list
This commit is contained in:
@@ -22,6 +22,12 @@ public:
|
||||
std::string_view as_view() const {
|
||||
return std::string_view(start_, p_ - start_);
|
||||
}
|
||||
const char *begin() const {
|
||||
return start_;
|
||||
}
|
||||
const char *end() {
|
||||
return p_;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return p_ - start_;
|
||||
|
||||
@@ -202,7 +202,7 @@ private:
|
||||
int scaleFactor_ = 0;
|
||||
};
|
||||
|
||||
// TODO: Replace with TransformedVertex?
|
||||
// This is used to represent both pre- and post transformed vertices, so is a bit of a mess.
|
||||
struct GPUDebugVertex {
|
||||
float u;
|
||||
float v;
|
||||
@@ -213,20 +213,27 @@ struct GPUDebugVertex {
|
||||
float w;
|
||||
|
||||
union {
|
||||
u8 c[4];
|
||||
u8 c0[4];
|
||||
u32 color0_32;
|
||||
};
|
||||
union {
|
||||
u8 c1[4];
|
||||
u32 color1_32;
|
||||
};
|
||||
|
||||
float fog;
|
||||
|
||||
float nx;
|
||||
float ny;
|
||||
float nz;
|
||||
|
||||
float weights[8];
|
||||
};
|
||||
|
||||
enum class DebugVertexFlags {
|
||||
Transformed = 1 << 0,
|
||||
Clipped = 1 << 1,
|
||||
DrawCoords = 1 << 2, // if not set, output X/Y will be in screen coords.
|
||||
};
|
||||
ENUM_CLASS_BITOPS(DebugVertexFlags);
|
||||
|
||||
|
||||
@@ -1325,7 +1325,7 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
}
|
||||
|
||||
const u32 vertTypeID = GetVertTypeID(gstate.vertType, gstate.getUVGenMode(), true);
|
||||
bool savedVertexFullAlpha = gstate_c.vertexFullAlpha;
|
||||
const bool throughMode = (vertTypeID & GE_VTYPE_THROUGH) != 0;
|
||||
|
||||
// Points is the only primitive that generates 6x as many vertices as input indices (2 triangles per point).
|
||||
std::vector<u16> indexTemp;
|
||||
@@ -1363,7 +1363,10 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
LoadUVScaleOffsetVec(gstate).Store(&uvScale.uScale);
|
||||
|
||||
const u8 *startPos = verts + indexLowerBound * dec->VertexSize();
|
||||
|
||||
bool savedVertexFullAlpha = gstate_c.vertexFullAlpha;
|
||||
dec->DecodeVerts(vertsTemp.data(), startPos, &uvScale, verticesToDecode);
|
||||
gstate_c.vertexFullAlpha = savedVertexFullAlpha;
|
||||
|
||||
int numDecodedVerts = verticesToDecode;
|
||||
u16 *inds = indexTemp.data();
|
||||
@@ -1384,6 +1387,7 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
for (int i = 0; i < verticesToDecode; i++) {
|
||||
reader.Goto(i);
|
||||
GPUDebugVertex &sv = debugVertices[i];
|
||||
sv = {};
|
||||
if (vertTypeID & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(&sv.u);
|
||||
} else {
|
||||
@@ -1393,7 +1397,7 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
if (vertTypeID & GE_VTYPE_COL_MASK) {
|
||||
sv.color0_32 = reader.ReadColor0_8888();
|
||||
} else {
|
||||
memcpy(sv.c, defaultColor, 4);
|
||||
memcpy(sv.c0, defaultColor, 4);
|
||||
}
|
||||
|
||||
if (vertTypeID & GE_VTYPE_NRM_MASK) {
|
||||
@@ -1403,6 +1407,11 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
sv.ny = 0.0f;
|
||||
sv.nz = 1.0f;
|
||||
}
|
||||
|
||||
if (vertTypeID & GE_VTYPE_WEIGHT_MASK) {
|
||||
reader.ReadWeights(sv.weights);
|
||||
}
|
||||
|
||||
reader.ReadPosAuto((float *)&sv.x);
|
||||
}
|
||||
|
||||
@@ -1470,7 +1479,7 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
params.transformed = transformed.data();
|
||||
params.transformedExpanded = transformedExpanded.data();
|
||||
|
||||
RunSoftwareTransform(params, prim, verticesToDecode, dec->GetDecVtxFmt(), numDecodedVerts, 65536, generatedIndices, inds, (int)indexTemp.size(), &result);
|
||||
RunSoftwareTransform(params, prim, vertTypeID, dec->GetDecVtxFmt(), numDecodedVerts, 65536, generatedIndices, inds, (int)indexTemp.size(), &result);
|
||||
|
||||
// Output of software transform is always triangles.
|
||||
prim = GE_PRIM_TRIANGLES;
|
||||
@@ -1486,22 +1495,31 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
debugIndices.resize(result.drawIndexCount);
|
||||
memcpy(debugIndices.data(), inds, result.drawIndexCount * sizeof(u16));
|
||||
|
||||
|
||||
const bool applyOffset = (flags & DebugVertexFlags::DrawCoords) && !throughMode;
|
||||
const float offsetX = applyOffset ? -gstate.getOffsetX() : 0.0f;
|
||||
const float offsetY = applyOffset ? -gstate.getOffsetY() : 0.0f;
|
||||
|
||||
// Convert the transformed vertices to the debug vertex format.
|
||||
debugVertices.resize(result.drawVertexCount);
|
||||
for (int i = 0; i < result.drawVertexCount; i++) {
|
||||
const TransformedVertex &vtx = result.drawBuffer[i];
|
||||
GPUDebugVertex &dv = debugVertices[i];
|
||||
dv.x = vtx.x;
|
||||
dv.y = vtx.y;
|
||||
dv.x = vtx.x + offsetX;
|
||||
dv.y = vtx.y + offsetY;
|
||||
dv.z = vtx.z;
|
||||
dv.w = vtx.pos_w;
|
||||
dv.u = vtx.u;
|
||||
dv.v = vtx.v;
|
||||
dv.fog = vtx.fog;
|
||||
dv.c[0] = (vtx.color0_32 >> 24) & 0xFF;
|
||||
dv.c[1] = (vtx.color0_32 >> 16) & 0xFF;
|
||||
dv.c[2] = (vtx.color0_32 >> 8) & 0xFF;
|
||||
dv.c[3] = vtx.color0_32 & 0xFF;
|
||||
dv.c0[0] = (vtx.color0_32 >> 24) & 0xFF;
|
||||
dv.c0[1] = (vtx.color0_32 >> 16) & 0xFF;
|
||||
dv.c0[2] = (vtx.color0_32 >> 8) & 0xFF;
|
||||
dv.c0[3] = vtx.color0_32 & 0xFF;
|
||||
dv.c1[0] = (vtx.color1_32 >> 24) & 0xFF;
|
||||
dv.c1[1] = (vtx.color1_32 >> 16) & 0xFF;
|
||||
dv.c1[2] = (vtx.color1_32 >> 8) & 0xFF;
|
||||
dv.c1[3] = vtx.color1_32 & 0xFF;
|
||||
}
|
||||
*outPrim = prim;
|
||||
return true;
|
||||
|
||||
+64
-95
@@ -12,6 +12,38 @@
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
const char *const g_vertexListDecodedColNames[] = {
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"U",
|
||||
"V",
|
||||
"Color",
|
||||
"NX",
|
||||
"NY",
|
||||
"NZ",
|
||||
"W0",
|
||||
"W1",
|
||||
"W2",
|
||||
"W3",
|
||||
"W4",
|
||||
"W5",
|
||||
"W6",
|
||||
"W7",
|
||||
};
|
||||
|
||||
const char *const g_vertexListTransformedColNames[] = {
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"W",
|
||||
"U",
|
||||
"V",
|
||||
"Color0",
|
||||
"Color1",
|
||||
"Fog",
|
||||
};
|
||||
|
||||
void FormatStateRow(char *dest, size_t destSize, CmdFormatType fmt, u32 value, bool enabled, u32 otherValue, u32 otherValue2) {
|
||||
value &= 0xFFFFFF;
|
||||
otherValue &= 0xFFFFFF;
|
||||
@@ -540,122 +572,59 @@ void FormatStateRow(char *dest, size_t destSize, CmdFormatType fmt, u32 value, b
|
||||
}
|
||||
}
|
||||
|
||||
void FormatVertCol(char *dest, size_t destSize, const GPUDebugVertex &vert, int col) {
|
||||
void FormatVertColTransformed(char *dest, size_t destSize, const GPUDebugVertex &vert, VertexListTransformedCol col) {
|
||||
switch (col) {
|
||||
case VERTEXLIST_COL_X: snprintf(dest, destSize, "%f", vert.x); break;
|
||||
case VERTEXLIST_COL_Y: snprintf(dest, destSize, "%f", vert.y); break;
|
||||
case VERTEXLIST_COL_Z: snprintf(dest, destSize, "%f", vert.z); break;
|
||||
case VERTEXLIST_COL_W: snprintf(dest, destSize, "%f", vert.w); break;
|
||||
case VERTEXLIST_COL_U: snprintf(dest, destSize, "%f", vert.u); break;
|
||||
case VERTEXLIST_COL_V: snprintf(dest, destSize, "%f", vert.v); break;
|
||||
case VERTEXLIST_COL_COLOR:
|
||||
snprintf(dest, destSize, "%02x%02x%02x%02x", vert.c[0], vert.c[1], vert.c[2], vert.c[3]);
|
||||
case VertexListTransformedCol::X: snprintf(dest, destSize, "%f", vert.x); break;
|
||||
case VertexListTransformedCol::Y: snprintf(dest, destSize, "%f", vert.y); break;
|
||||
case VertexListTransformedCol::Z: snprintf(dest, destSize, "%f", vert.z); break;
|
||||
case VertexListTransformedCol::W: snprintf(dest, destSize, "%f", vert.w); break;
|
||||
case VertexListTransformedCol::U: snprintf(dest, destSize, "%f", vert.u); break;
|
||||
case VertexListTransformedCol::V: snprintf(dest, destSize, "%f", vert.v); break;
|
||||
case VertexListTransformedCol::COLOR0:
|
||||
snprintf(dest, destSize, "%02x%02x%02x%02x", vert.c0[0], vert.c0[1], vert.c0[2], vert.c0[3]);
|
||||
break;
|
||||
case VERTEXLIST_COL_NX: snprintf(dest, destSize, "%f", vert.nx); break;
|
||||
case VERTEXLIST_COL_NY: snprintf(dest, destSize, "%f", vert.ny); break;
|
||||
case VERTEXLIST_COL_NZ: snprintf(dest, destSize, "%f", vert.nz); break;
|
||||
case VERTEXLIST_COL_FOG: snprintf(dest, destSize, "%f", vert.fog); break;
|
||||
|
||||
case VertexListTransformedCol::COLOR1:
|
||||
snprintf(dest, destSize, "%02x%02x%02x%02x", vert.c1[0], vert.c1[1], vert.c1[2], vert.c1[3]);
|
||||
break;
|
||||
case VertexListTransformedCol::FOG: snprintf(dest, destSize, "%f", vert.fog); break;
|
||||
default:
|
||||
truncate_cpy(dest, destSize, "Invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FormatVertColRawType(char *dest, size_t destSize, const void *data, int type, int offset);
|
||||
static void FormatVertColRawColor(char *dest, size_t destSize, const void *data, int type);
|
||||
|
||||
void FormatVertColRaw(VertexDecoder *decoder, char *dest, size_t destSize, int row, int col) {
|
||||
void FormatVertColDecoded(char *dest, size_t destSize, const GPUDebugVertex &vert, VertexListDecodedCol col) {
|
||||
if (PSP_GetBootState() != BootState::Complete) {
|
||||
truncate_cpy(dest, destSize, "Invalid");
|
||||
return;
|
||||
}
|
||||
|
||||
// We could use the vertex decoder and reader, but those already do some minor adjustments.
|
||||
// There's only a few values - let's just go after them directly.
|
||||
const u8 *vert = Memory::GetPointer(gpu->GetVertexAddress()) + row * decoder->size;
|
||||
const u8 *pos = vert + decoder->posoff;
|
||||
const u8 *tc = vert + decoder->tcoff;
|
||||
const u8 *color = vert + decoder->coloff;
|
||||
const u8 *norm = vert + decoder->nrmoff;
|
||||
|
||||
switch (col) {
|
||||
case VERTEXLIST_COL_X:
|
||||
FormatVertColRawType(dest, destSize, pos, decoder->pos, 0);
|
||||
case VertexListDecodedCol::X: snprintf(dest, destSize, "%f", vert.x); break;
|
||||
case VertexListDecodedCol::Y: snprintf(dest, destSize, "%f", vert.y); break;
|
||||
case VertexListDecodedCol::Z: snprintf(dest, destSize, "%f", vert.z); break;
|
||||
case VertexListDecodedCol::U: snprintf(dest, destSize, "%f", vert.u); break;
|
||||
case VertexListDecodedCol::V: snprintf(dest, destSize, "%f", vert.v); break;
|
||||
case VertexListDecodedCol::COLOR:
|
||||
snprintf(dest, destSize, "%02x%02x%02x%02x", vert.c0[0], vert.c0[1], vert.c0[2], vert.c0[3]);
|
||||
break;
|
||||
case VERTEXLIST_COL_Y:
|
||||
FormatVertColRawType(dest, destSize, pos, decoder->pos, 1);
|
||||
break;
|
||||
case VERTEXLIST_COL_Z:
|
||||
FormatVertColRawType(dest, destSize, pos, decoder->pos, 2);
|
||||
break;
|
||||
case VERTEXLIST_COL_U:
|
||||
FormatVertColRawType(dest, destSize, tc, decoder->tc, 0);
|
||||
break;
|
||||
case VERTEXLIST_COL_V:
|
||||
FormatVertColRawType(dest, destSize, tc, decoder->tc, 1);
|
||||
break;
|
||||
case VERTEXLIST_COL_COLOR:
|
||||
FormatVertColRawColor(dest, destSize, color, decoder->col);
|
||||
break;
|
||||
|
||||
case VERTEXLIST_COL_NX: FormatVertColRawType(dest, destSize, norm, decoder->nrm, 0); break;
|
||||
case VERTEXLIST_COL_NY: FormatVertColRawType(dest, destSize, norm, decoder->nrm, 1); break;
|
||||
case VERTEXLIST_COL_NZ: FormatVertColRawType(dest, destSize, norm, decoder->nrm, 2); break;
|
||||
|
||||
case VertexListDecodedCol::NX: snprintf(dest, destSize, "%f", vert.nx); break;
|
||||
case VertexListDecodedCol::NY: snprintf(dest, destSize, "%f", vert.ny); break;
|
||||
case VertexListDecodedCol::NZ: snprintf(dest, destSize, "%f", vert.nz); break;
|
||||
case VertexListDecodedCol::W0: snprintf(dest, destSize, "%f", vert.weights[0]); break;
|
||||
case VertexListDecodedCol::W1: snprintf(dest, destSize, "%f", vert.weights[1]); break;
|
||||
case VertexListDecodedCol::W2: snprintf(dest, destSize, "%f", vert.weights[2]); break;
|
||||
case VertexListDecodedCol::W3: snprintf(dest, destSize, "%f", vert.weights[3]); break;
|
||||
case VertexListDecodedCol::W4: snprintf(dest, destSize, "%f", vert.weights[4]); break;
|
||||
case VertexListDecodedCol::W5: snprintf(dest, destSize, "%f", vert.weights[5]); break;
|
||||
case VertexListDecodedCol::W6: snprintf(dest, destSize, "%f", vert.weights[6]); break;
|
||||
case VertexListDecodedCol::W7: snprintf(dest, destSize, "%f", vert.weights[7]); break;
|
||||
default:
|
||||
truncate_cpy(dest, destSize, "Invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FormatVertColRawType(char *dest, size_t destSize, const void *data, int type, int offset) {
|
||||
switch (type) {
|
||||
case 0:
|
||||
truncate_cpy(dest, destSize, "-");
|
||||
break;
|
||||
|
||||
case 1: // 8-bit
|
||||
snprintf(dest, destSize, "%02x", ((const u8 *)data)[offset]);
|
||||
break;
|
||||
|
||||
case 2: // 16-bit
|
||||
snprintf(dest, destSize, "%04x", ((const u16_le *)data)[offset]);
|
||||
break;
|
||||
|
||||
case 3: // float
|
||||
snprintf(dest, destSize, "%f", ((const float *)data)[offset]);
|
||||
break;
|
||||
|
||||
default:
|
||||
truncate_cpy(dest, destSize, "Invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void FormatVertColRawColor(char *dest, size_t destSize, const void *data, int type) {
|
||||
switch (type) {
|
||||
case GE_VTYPE_COL_NONE >> GE_VTYPE_COL_SHIFT:
|
||||
truncate_cpy(dest, destSize, "-");
|
||||
break;
|
||||
|
||||
case GE_VTYPE_COL_565 >> GE_VTYPE_COL_SHIFT:
|
||||
case GE_VTYPE_COL_5551 >> GE_VTYPE_COL_SHIFT:
|
||||
case GE_VTYPE_COL_4444 >> GE_VTYPE_COL_SHIFT:
|
||||
snprintf(dest, destSize, "%04x", *(const u16_le *)data);
|
||||
break;
|
||||
|
||||
case GE_VTYPE_COL_8888 >> GE_VTYPE_COL_SHIFT:
|
||||
snprintf(dest, destSize, "%08x", *(const u32_le *)data);
|
||||
break;
|
||||
|
||||
default:
|
||||
truncate_cpy(dest, destSize, "Invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void SwapUVs(GPUDebugVertex &a, GPUDebugVertex &b) {
|
||||
float tempu = a.u;
|
||||
float tempv = a.v;
|
||||
|
||||
+41
-15
@@ -10,20 +10,45 @@
|
||||
#include "GPU/Common/SplineCommon.h"
|
||||
#include "GPU/GPUCommon.h"
|
||||
|
||||
enum VertexListCols {
|
||||
VERTEXLIST_COL_X,
|
||||
VERTEXLIST_COL_Y,
|
||||
VERTEXLIST_COL_Z,
|
||||
VERTEXLIST_COL_W,
|
||||
VERTEXLIST_COL_U,
|
||||
VERTEXLIST_COL_V,
|
||||
VERTEXLIST_COL_COLOR,
|
||||
VERTEXLIST_COL_NX,
|
||||
VERTEXLIST_COL_NY,
|
||||
VERTEXLIST_COL_NZ,
|
||||
VERTEXLIST_COL_FOG,
|
||||
VERTEXLIST_COL_COUNT,
|
||||
// TODO: Add back a true raw vertex list?
|
||||
|
||||
enum class VertexListDecodedCol {
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
U,
|
||||
V,
|
||||
COLOR,
|
||||
NX,
|
||||
NY,
|
||||
NZ,
|
||||
W0,
|
||||
W1,
|
||||
W2,
|
||||
W3,
|
||||
W4,
|
||||
W5,
|
||||
W6,
|
||||
W7,
|
||||
COUNT,
|
||||
};
|
||||
extern const char *const g_vertexListDecodedColNames[];
|
||||
|
||||
enum class VertexListTransformedCol {
|
||||
X,
|
||||
Y,
|
||||
Z,
|
||||
W,
|
||||
U,
|
||||
V,
|
||||
COLOR0,
|
||||
COLOR1,
|
||||
FOG,
|
||||
COUNT,
|
||||
};
|
||||
|
||||
// Indexed by the above enum;
|
||||
extern const char *const g_vertexListTransformedColNames[];
|
||||
|
||||
extern const GECommand g_stateFlagsRows[];
|
||||
extern const GECommand g_stateLightingRows[];
|
||||
@@ -38,8 +63,9 @@ struct GPUDebugVertex;
|
||||
class VertexDecoder;
|
||||
|
||||
void FormatStateRow(char *dest, size_t destSize, CmdFormatType fmt, u32 value, bool enabled, u32 otherValue, u32 otherValue2);
|
||||
void FormatVertCol(char *dest, size_t destSize, const GPUDebugVertex &vert, int col);
|
||||
void FormatVertColRaw(VertexDecoder *decoder, char *dest, size_t destSize, int row, int col);
|
||||
|
||||
void FormatVertColDecoded(char *dest, size_t destSize, const GPUDebugVertex &vert, VertexListDecodedCol col);
|
||||
void FormatVertColTransformed(char *dest, size_t destSize, const GPUDebugVertex &vert, VertexListTransformedCol col);
|
||||
|
||||
// These are utilities used by the debugger vertex preview.
|
||||
bool GetPrimPreview(u32 op, GEPrimitiveType &prim, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int *lowerIndexBound, bool transformed);
|
||||
|
||||
@@ -1,5 +1,22 @@
|
||||
#include "GPU/ge_constants.h"
|
||||
|
||||
const char *GePrimTypeToString(GEPrimitiveType prim) {
|
||||
static constexpr const char * primTypes[8] = {
|
||||
"POINTS",
|
||||
"LINES",
|
||||
"LINE_STRIP",
|
||||
"TRI_LIST",
|
||||
"TRI_STRIP",
|
||||
"TRI_FAN",
|
||||
"RECTS",
|
||||
"CONTINUE_PREV",
|
||||
};
|
||||
const int p = static_cast<int>(prim);
|
||||
if (p < 0 || p >= 8)
|
||||
return "INVALID";
|
||||
return primTypes[p];
|
||||
}
|
||||
|
||||
const char *GeBufferFormatToString(GEBufferFormat fmt) {
|
||||
switch (fmt) {
|
||||
case GE_FORMAT_4444: return "4444";
|
||||
|
||||
+3
-14
@@ -94,17 +94,6 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer, int bufsize) {
|
||||
u32 cmd = op >> 24;
|
||||
u32 data = op & 0xFFFFFF;
|
||||
|
||||
static constexpr const char * primTypes[8] = {
|
||||
"POINTS",
|
||||
"LINES",
|
||||
"LINE_STRIP",
|
||||
"TRIANGLES",
|
||||
"TRIANGLE_STRIP",
|
||||
"TRIANGLE_FAN",
|
||||
"RECTANGLES",
|
||||
"CONTINUE_PREVIOUS",
|
||||
};
|
||||
|
||||
// Handle control and drawing commands here directly. The others we delegate.
|
||||
switch (cmd)
|
||||
{
|
||||
@@ -144,9 +133,9 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer, int bufsize) {
|
||||
u32 count = data & 0xFFFF;
|
||||
u32 type = (data >> 16) & 7;
|
||||
if (gstate.vertType & GE_VTYPE_IDX_MASK)
|
||||
snprintf(buffer, bufsize, "DRAW PRIM %s: count= %i vaddr= %08x, iaddr= %08x", type < 7 ? primTypes[type] : "INVALID", count, gstate_c.vertexAddr, gstate_c.indexAddr);
|
||||
snprintf(buffer, bufsize, "DRAW PRIM %s: count= %i vaddr= %08x, iaddr= %08x", GePrimTypeToString(static_cast<GEPrimitiveType>(type)), count, gstate_c.vertexAddr, gstate_c.indexAddr);
|
||||
else
|
||||
snprintf(buffer, bufsize, "DRAW PRIM %s: count= %i vaddr= %08x", type < 7 ? primTypes[type] : "INVALID", count, gstate_c.vertexAddr);
|
||||
snprintf(buffer, bufsize, "DRAW PRIM %s: count= %i vaddr= %08x", GePrimTypeToString(static_cast<GEPrimitiveType>(type)), count, gstate_c.vertexAddr);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1365,7 +1354,7 @@ void GeDisassembleOp(u32 pc, u32 op, u32 prev, char *buffer, int bufsize) {
|
||||
bool texturing = (data & GE_IMM_TEXTURE) != 0;
|
||||
bool dither = (data & GE_IMM_DITHER) != 0;
|
||||
char *p = buffer;
|
||||
p += snprintf(p, bufsize - (p - buffer), "Vertex draw: alpha=%02x, prim=%s", data & 0xFF, primTypes[(data >> 8) & 7]);
|
||||
p += snprintf(p, bufsize - (p - buffer), "Vertex draw: alpha=%02x, prim=%s", data & 0xFF, GePrimTypeToString(static_cast<GEPrimitiveType>((data >> 8) & 7)));
|
||||
if (antialias)
|
||||
p += snprintf(p, bufsize - (p - buffer), ", antialias");
|
||||
if (clip != 0)
|
||||
|
||||
@@ -1016,9 +1016,9 @@ bool TransformUnit::GetCurrentDrawAsDebugVertices(int count, std::vector<GPUDebu
|
||||
}
|
||||
|
||||
if (gstate.vertType & GE_VTYPE_COL_MASK) {
|
||||
memcpy(vertices[i].c, vert.color, sizeof(vertices[i].c));
|
||||
memcpy(vertices[i].c0, vert.color, sizeof(vertices[i].c0));
|
||||
} else {
|
||||
memset(vertices[i].c, 0, sizeof(vertices[i].c));
|
||||
memset(vertices[i].c0, 0, sizeof(vertices[i].c0));
|
||||
}
|
||||
vertices[i].nx = vert.nrm.x;
|
||||
vertices[i].ny = vert.nrm.y;
|
||||
|
||||
@@ -595,6 +595,8 @@ enum GEPrimitiveType : int8_t {
|
||||
GE_PRIM_INVALID = -1,
|
||||
};
|
||||
|
||||
const char *GePrimTypeToString(GEPrimitiveType prim);
|
||||
|
||||
enum GELogicOp : uint8_t {
|
||||
GE_LOGIC_CLEAR = 0,
|
||||
GE_LOGIC_AND = 1,
|
||||
|
||||
@@ -121,7 +121,6 @@ struct ImConfig {
|
||||
int requesterToken;
|
||||
|
||||
bool sasShowAllVoices = false;
|
||||
bool vertexListTransformed = false;
|
||||
bool vertexListClipped = false;
|
||||
|
||||
float fbViewerZoom = 1.0f;
|
||||
|
||||
+63
-58
@@ -1709,85 +1709,91 @@ void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebug)
|
||||
return;
|
||||
}
|
||||
|
||||
ImGui::Checkbox("Transformed", &cfg.vertexListTransformed);
|
||||
ImGui::SameLine();
|
||||
if (gstate.isModeThrough()) {
|
||||
ImGui::BeginDisabled();
|
||||
}
|
||||
ImGui::Checkbox("Clipped", &cfg.vertexListClipped);
|
||||
if (gstate.isModeThrough()) {
|
||||
ImGui::EndDisabled();
|
||||
}
|
||||
|
||||
const ImGuiTableFlags tableFlags =
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_ScrollY;
|
||||
|
||||
if (ImGui::BeginTabBar("vertexmode", ImGuiTabBarFlags_None)) {
|
||||
auto state = gpuDebug->GetGState();
|
||||
char fmtTemp[256];
|
||||
FormatStateRow(fmtTemp, sizeof(fmtTemp), CMD_FMT_VERTEXTYPE, state.vertType, true, false, false);
|
||||
ImGui::TextUnformatted(fmtTemp);
|
||||
auto buildVertexTable = [&](bool transformed) {
|
||||
// Let's see if it's fast enough to just do all this each frame.
|
||||
GEPrimitiveType prim;
|
||||
std::vector<GPUDebugVertex> vertices;
|
||||
std::vector<u16> indices;
|
||||
int indexOffset = 0;
|
||||
|
||||
// Let's see if it's fast enough to just do all this each frame.
|
||||
GEPrimitiveType prim;
|
||||
int rowCount_ = gpuDebug->GetCurrentPrimCount(&prim);
|
||||
std::vector<GPUDebugVertex> vertices;
|
||||
std::vector<u16> indices;
|
||||
int previewIndexOffset_ = 0;
|
||||
DebugVertexFlags flags{};
|
||||
if (transformed) {
|
||||
flags |= DebugVertexFlags::Transformed | DebugVertexFlags::DrawCoords;
|
||||
}
|
||||
if (cfg.vertexListClipped && !gstate.isModeThrough()) {
|
||||
flags |= DebugVertexFlags::Clipped;
|
||||
}
|
||||
|
||||
DebugVertexFlags flags{};
|
||||
if (cfg.vertexListTransformed) {
|
||||
flags |= DebugVertexFlags::Transformed;
|
||||
}
|
||||
if (cfg.vertexListClipped) {
|
||||
flags |= DebugVertexFlags::Clipped;
|
||||
}
|
||||
int inputVertexCount = gpuDebug->GetCurrentPrimCount(&prim);
|
||||
|
||||
// This performs software transform, if transformed is checked. We might want to cache it? Although, it's only for a single draw...
|
||||
TransformStats stats;
|
||||
if (!gpuDebug->GetCurrentDrawAsDebugVertices(prim, &prim, rowCount_, vertices, indices, &previewIndexOffset_, &stats, flags)) {
|
||||
rowCount_ = 0;
|
||||
}
|
||||
auto buildVertexTable = [&](bool raw) {
|
||||
// Ignore indices for now.
|
||||
if (ImGui::BeginTable("rawverts", VERTEXLIST_COL_COUNT + 1, tableFlags)) {
|
||||
static VertexDecoder decoder;
|
||||
u32 vertTypeID = GetVertTypeID(state.vertType, state.getUVGenMode(), true);
|
||||
VertexDecoderOptions options{};
|
||||
decoder.SetVertexType(vertTypeID, options);
|
||||
// This performs software transform, if transformed is checked. We might want to cache it? Although, it's only for a single draw...
|
||||
TransformStats stats;
|
||||
if (!gpuDebug->GetCurrentDrawAsDebugVertices(prim, &prim, inputVertexCount, vertices, indices, &indexOffset, &stats, flags)) {
|
||||
inputVertexCount = 0;
|
||||
}
|
||||
|
||||
static const char * const colNames[] = {
|
||||
"Index",
|
||||
"X",
|
||||
"Y",
|
||||
"Z",
|
||||
"W",
|
||||
"U",
|
||||
"V",
|
||||
"Color",
|
||||
"NX",
|
||||
"NY",
|
||||
"NZ",
|
||||
"Fog",
|
||||
};
|
||||
for (int i = 0; i < ARRAY_SIZE(colNames); i++) {
|
||||
ImGui::TableSetupColumn(colNames[i], ImGuiTableColumnFlags_WidthFixed, 0.0f, i);
|
||||
const int rowCount = indices.empty() ? (int)vertices.size() : (int)indices.size();
|
||||
|
||||
char statusLine[256];
|
||||
StringWriter w(statusLine);
|
||||
w.F("%s: ", GePrimTypeToString(prim));
|
||||
char fmtTemp[256];
|
||||
FormatStateRow(fmtTemp, sizeof(fmtTemp), CMD_FMT_VERTEXTYPE, state.vertType, true, false, false);
|
||||
w.F("%s", fmtTemp);
|
||||
if (gstate.isModeClear()) {
|
||||
w.C(" (clearmode)");
|
||||
}
|
||||
ImGui::TextUnformatted(w.begin(), w.end());
|
||||
|
||||
if (transformed) {
|
||||
ImGui::Text("Culled far: %d near: %d Clipped: %d", stats.culledTrianglesFar, stats.culledTrianglesNear, stats.clippedTriangles);
|
||||
}
|
||||
|
||||
const int colCount = transformed ? (int)VertexListTransformedCol::COUNT : (int)VertexListDecodedCol::COUNT;
|
||||
|
||||
// + 1 for the index column.
|
||||
if (ImGui::BeginTable("rawverts", colCount + 1, tableFlags)) {
|
||||
const char *const *colNames = transformed ? g_vertexListTransformedColNames : g_vertexListDecodedColNames;
|
||||
|
||||
ImGui::TableSetupColumn("Index", ImGuiTableColumnFlags_WidthFixed, 0.0f, 0);
|
||||
for (int i = 0; i < colCount; i++) {
|
||||
ImGui::TableSetupColumn(colNames[i], ImGuiTableColumnFlags_WidthFixed, 0.0f, i + 1);
|
||||
}
|
||||
ImGui::TableSetupScrollFreeze(0, 1); // Make header row always visible
|
||||
ImGui::TableHeadersRow();
|
||||
|
||||
ImGuiListClipper clipper;
|
||||
_dbg_assert_(rowCount_ >= 0);
|
||||
clipper.Begin(rowCount_);
|
||||
_dbg_assert_(rowCount >= 0);
|
||||
clipper.Begin(rowCount);
|
||||
while (clipper.Step()) {
|
||||
for (int i = clipper.DisplayStart; i < clipper.DisplayEnd; i++) {
|
||||
int index = indices.empty() ? i : indices[i];
|
||||
int index = indices.empty() ? i : (indices[i] - indexOffset);
|
||||
ImGui::PushID(i);
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::PushID(i);
|
||||
ImGui::Text("%d", index);
|
||||
for (int column = 0; column < VERTEXLIST_COL_COUNT; column++) {
|
||||
for (int column = 0; column < colCount; column++) {
|
||||
ImGui::TableNextColumn();
|
||||
char temp[36];
|
||||
if (raw) {
|
||||
FormatVertColRaw(&decoder, temp, sizeof(temp), index, column);
|
||||
if (transformed) {
|
||||
FormatVertColTransformed(temp, sizeof(temp), vertices[index], (VertexListTransformedCol)column);
|
||||
} else {
|
||||
FormatVertCol(temp, sizeof(temp), vertices[index], column);
|
||||
FormatVertColDecoded(temp, sizeof(temp), vertices[index], (VertexListDecodedCol)column);
|
||||
}
|
||||
ImGui::TextUnformatted(temp);
|
||||
}
|
||||
@@ -1800,13 +1806,12 @@ void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebug)
|
||||
}
|
||||
};
|
||||
|
||||
if (ImGui::BeginTabItem("Raw")) {
|
||||
buildVertexTable(true);
|
||||
if (ImGui::BeginTabItem("Decoded")) {
|
||||
buildVertexTable(false);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
if (ImGui::BeginTabItem("Transformed")) {
|
||||
ImGui::Text("Culled far: %d near: %d Clipped: %d", stats.culledTrianglesFar, stats.culledTrianglesNear, stats.clippedTriangles);
|
||||
buildVertexTable(false);
|
||||
buildVertexTable(true);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
// TODO: Let's not include columns for which we have no data.
|
||||
|
||||
@@ -138,19 +138,18 @@ void CtrlVertexList::GetColumnText(wchar_t *dest, size_t destSize, int row, int
|
||||
swprintf(dest, destSize, L"Invalid index %d", row);
|
||||
return;
|
||||
}
|
||||
row = indices[row];
|
||||
row = indices[row - previewIndexOffset_];
|
||||
}
|
||||
|
||||
char temp[256];
|
||||
if (raw_) {
|
||||
FormatVertColRaw(decoder, temp, sizeof(temp), row, col);
|
||||
FormatVertColDecoded(temp, sizeof(temp), vertices[row], (VertexListDecodedCol)col);
|
||||
} else {
|
||||
if (row >= (int)vertices.size()) {
|
||||
swprintf(dest, destSize, L"Invalid vertex %d", row);
|
||||
return;
|
||||
}
|
||||
|
||||
FormatVertCol(temp, sizeof(temp), vertices[row], col);
|
||||
FormatVertColTransformed(temp, sizeof(temp), vertices[row], (VertexListTransformedCol)col);
|
||||
}
|
||||
ConvertUTF8ToWString(dest, destSize, temp);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user