diff --git a/Common/Data/Text/StringWriter.h b/Common/Data/Text/StringWriter.h index c571fb5fb3..42d29998ce 100644 --- a/Common/Data/Text/StringWriter.h +++ b/Common/Data/Text/StringWriter.h @@ -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_; diff --git a/GPU/Common/GPUDebugInterface.h b/GPU/Common/GPUDebugInterface.h index ec75baaddb..a11a2e6537 100644 --- a/GPU/Common/GPUDebugInterface.h +++ b/GPU/Common/GPUDebugInterface.h @@ -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); diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index a88cca06c3..155a6e1680 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -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 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; diff --git a/GPU/Debugger/State.cpp b/GPU/Debugger/State.cpp index e2ff8aed15..b7719a36aa 100644 --- a/GPU/Debugger/State.cpp +++ b/GPU/Debugger/State.cpp @@ -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; diff --git a/GPU/Debugger/State.h b/GPU/Debugger/State.h index 0e0e2d4063..6f44a0e8f9 100644 --- a/GPU/Debugger/State.h +++ b/GPU/Debugger/State.h @@ -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 &vertices, std::vector &indices, int *lowerIndexBound, bool transformed); diff --git a/GPU/GeConstants.cpp b/GPU/GeConstants.cpp index b093d96d56..95c9ffdf8d 100644 --- a/GPU/GeConstants.cpp +++ b/GPU/GeConstants.cpp @@ -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(prim); + if (p < 0 || p >= 8) + return "INVALID"; + return primTypes[p]; +} + const char *GeBufferFormatToString(GEBufferFormat fmt) { switch (fmt) { case GE_FORMAT_4444: return "4444"; diff --git a/GPU/GeDisasm.cpp b/GPU/GeDisasm.cpp index ad7a672d68..054a6d25e1 100644 --- a/GPU/GeDisasm.cpp +++ b/GPU/GeDisasm.cpp @@ -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(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(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((data >> 8) & 7))); if (antialias) p += snprintf(p, bufsize - (p - buffer), ", antialias"); if (clip != 0) diff --git a/GPU/Software/TransformUnit.cpp b/GPU/Software/TransformUnit.cpp index 49b8bae762..268014e8c4 100644 --- a/GPU/Software/TransformUnit.cpp +++ b/GPU/Software/TransformUnit.cpp @@ -1016,9 +1016,9 @@ bool TransformUnit::GetCurrentDrawAsDebugVertices(int count, std::vectorGetGState(); - 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 vertices; + std::vector 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 vertices; - std::vector 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. diff --git a/Windows/GEDebugger/TabVertices.cpp b/Windows/GEDebugger/TabVertices.cpp index a92ca6faf4..3b4ade673e 100644 --- a/Windows/GEDebugger/TabVertices.cpp +++ b/Windows/GEDebugger/TabVertices.cpp @@ -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); }