mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-14 15:00:30 +02:00
Visualize bounding boxes in ImGe debugger by drawing their corners
This commit is contained in:
1 parent
1624a6da83
commit
d0f4e5c2d1
12 files changed
+386
-103
No files matched your search
@@ -37,7 +37,7 @@
|
||||
|
||||
static bool ExpandRectangles(int vertexCount, int &numDecodedVerts, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int *drawIndexCount, bool throughmode, bool *pixelMappedExactly);
|
||||
static bool ExpandLines(int vertexCount, int &numDecodedVerts, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int *drawIndexCount, bool throughmode);
|
||||
static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int *drawIndexCount, bool throughmode);
|
||||
static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int *drawIndexCount, bool throughmode, float pointScale);
|
||||
static SoftwareTransformAction ProjectClipAndExpand(SoftwareTransformParams ¶ms, int prim, int vertexCount, u32 vertType, u16 *&inds, int indsSize, int &numDecodedVerts, int vertsSize, SoftwareTransformResult *result);
|
||||
|
||||
// This is the software transform pipeline, which is necessary for supporting RECT
|
||||
@@ -636,7 +636,7 @@ static SoftwareTransformAction ProjectClipAndExpand(SoftwareTransformParams &par
|
||||
}
|
||||
|
||||
result->pixelMapped = false;
|
||||
if (!ExpandPoints(vertexCount, numDecodedVerts, vertsSize, inds, indsSize, transformed, transformedExpanded, &drawIndexCount, throughmode)) {
|
||||
if (!ExpandPoints(vertexCount, numDecodedVerts, vertsSize, inds, indsSize, transformed, transformedExpanded, &drawIndexCount, throughmode, params.pointScale)) {
|
||||
result->drawVertexCount = 0;
|
||||
result->drawIndexCount = 0;
|
||||
result->drawBuffer = nullptr;
|
||||
@@ -1104,7 +1104,7 @@ static bool ExpandLines(int vertexCount, int &numDecodedVerts, int vertsSize, u1
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int *drawIndexCount, bool throughmode) {
|
||||
static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&inds, int indsSize, const TransformedVertex *transformed, TransformedVertex *transformedExpanded, int *drawIndexCount, bool throughmode, float pointScale) {
|
||||
// Before we start, do a sanity check - does the output fit?
|
||||
if (vertexCount * 6 > indsSize) {
|
||||
// Won't fit, kill the draw.
|
||||
@@ -1121,17 +1121,22 @@ static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&in
|
||||
u16 *newInds = inds + vertexCount;
|
||||
u16 *indsOut = newInds;
|
||||
|
||||
float dx = 1.0f;
|
||||
float dy = 1.0f;
|
||||
const float offset = pointScale != 1.0f ? -pointScale * 0.5f : 0.0f;
|
||||
|
||||
float du = 1.0f / gstate_c.curTextureWidth;
|
||||
float dv = 1.0f / gstate_c.curTextureHeight;
|
||||
const float dx = 1.0f * pointScale;
|
||||
const float dy = 1.0f * pointScale;
|
||||
|
||||
const float du = 1.0f / gstate_c.curTextureWidth;
|
||||
const float dv = 1.0f / gstate_c.curTextureHeight;
|
||||
|
||||
maxIndex = 4 * vertexCount;
|
||||
for (int i = 0; i < vertexCount; ++i) {
|
||||
const TransformedVertex &transVtxTL = transformed[indsIn[i]];
|
||||
TransformedVertex transVtxTL = transformed[indsIn[i]];
|
||||
// Centering, if the logic below enables it.
|
||||
transVtxTL.x += offset;
|
||||
transVtxTL.y += offset;
|
||||
|
||||
// Create the bottom right version.
|
||||
// Create the bottom right corner.
|
||||
TransformedVertex transVtxBR = transVtxTL;
|
||||
transVtxBR.x += dx;
|
||||
transVtxBR.y += dy;
|
||||
@@ -1311,7 +1316,7 @@ static Vec3f ScreenToDrawing(const Vec3f& coords) {
|
||||
// This is really just for vertex preview in the debugger, not for actual rendering!
|
||||
// TODO: Support tessellation!! That's currently entirely broken (I guess maybe we'll draw the control points as something).
|
||||
// count is the input vertex count (describes the draw together with prim).
|
||||
bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> &debugVertices, std::vector<u16> &debugIndices, int *outLowerIndexBound, TransformStats *stats, DebugVertexFlags flags) {
|
||||
bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GECommand cmd, GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> *debugVertices, std::vector<u16> *debugIndices, int *outLowerIndexBound, TransformStats *stats, DebugVertexFlags flags) {
|
||||
// This is always for the current vertices.
|
||||
u16 indexLowerBound = 0;
|
||||
u16 indexUpperBound = count - 1;
|
||||
@@ -1374,7 +1379,7 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
if (!(flags & DebugVertexFlags::Transformed)) {
|
||||
// Output the untransformed vertices (although with skinning and morph baked-in from decode),
|
||||
// and the original indices. Might be interesting to look at.
|
||||
debugVertices.resize(verticesToDecode);
|
||||
debugVertices->resize(verticesToDecode);
|
||||
VertexReader reader(vertsTemp.data(), dec->GetDecVtxFmt(), vertTypeID);
|
||||
|
||||
const u8 defaultColor[4] = {
|
||||
@@ -1386,7 +1391,7 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
|
||||
for (int i = 0; i < verticesToDecode; i++) {
|
||||
reader.Goto(i);
|
||||
GPUDebugVertex &sv = debugVertices[i];
|
||||
GPUDebugVertex &sv = (*debugVertices)[i];
|
||||
sv = {};
|
||||
if (vertTypeID & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(&sv.u);
|
||||
@@ -1418,24 +1423,24 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
// Output the indices straight
|
||||
switch (vertTypeID & GE_VTYPE_IDX_MASK) {
|
||||
case GE_VTYPE_IDX_NONE:
|
||||
debugIndices.clear(); // it's just a sequence, effectively.
|
||||
debugIndices->clear(); // it's just a sequence, effectively.
|
||||
break;
|
||||
case GE_VTYPE_IDX_8BIT:
|
||||
debugIndices.resize(verticesToDecode);
|
||||
debugIndices->resize(verticesToDecode);
|
||||
for (int i = 0; i < verticesToDecode; i++) {
|
||||
debugIndices[i] = ((const u8 *)indsPtr)[i];
|
||||
(*debugIndices)[i] = ((const u8 *)indsPtr)[i];
|
||||
}
|
||||
break;
|
||||
case GE_VTYPE_IDX_16BIT:
|
||||
debugIndices.resize(verticesToDecode);
|
||||
debugIndices->resize(verticesToDecode);
|
||||
for (int i = 0; i < verticesToDecode; i++) {
|
||||
debugIndices[i] = ((const u16_le *)indsPtr)[i];
|
||||
(*debugIndices)[i] = ((const u16_le *)indsPtr)[i];
|
||||
}
|
||||
break;
|
||||
case GE_VTYPE_IDX_32BIT:
|
||||
debugIndices.resize(verticesToDecode);
|
||||
debugIndices->resize(verticesToDecode);
|
||||
for (int i = 0; i < verticesToDecode; i++) {
|
||||
debugIndices[i] = ((const u32_le *)indsPtr)[i];
|
||||
(*debugIndices)[i] = ((const u32_le *)indsPtr)[i];
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1466,7 +1471,7 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
break;
|
||||
}
|
||||
|
||||
// After this, strips and fans have been collapsed to triangles.
|
||||
// After index generation, strips and fans have been collapsed to triangles.
|
||||
switch (prim) {
|
||||
case GE_PRIM_LINE_STRIP:
|
||||
prim = GE_PRIM_LINES;
|
||||
@@ -1489,14 +1494,15 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
params.decoded = vertsTemp.data();
|
||||
params.transformed = transformed.data();
|
||||
params.transformedExpanded = transformedExpanded.data();
|
||||
params.pointScale = cmd == GE_CMD_BOUNDINGBOX ? 4.0f : 1.0f; // Just make them more visible, for eas of debugging.
|
||||
|
||||
RunSoftwareTransform(params, prim, vertTypeID, dec->GetDecVtxFmt(), numDecodedVerts, 65536, generatedIndices, inds, (int)indexTemp.size(), &result);
|
||||
|
||||
// Output of software transform is always an indexed triangle list (or nothing).
|
||||
if (result.drawIndexCount == 0) {
|
||||
// Not a failue, but everything got culled.
|
||||
debugVertices.clear();
|
||||
debugIndices.clear();
|
||||
debugVertices->clear();
|
||||
debugIndices->clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1510,18 +1516,18 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType
|
||||
gstate_c.vertexFullAlpha = savedVertexFullAlpha;
|
||||
|
||||
// Supply indices in a correctly-sized vector.
|
||||
debugIndices.resize(result.drawIndexCount);
|
||||
memcpy(debugIndices.data(), inds, result.drawIndexCount * sizeof(u16));
|
||||
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);
|
||||
debugVertices->resize(result.drawVertexCount);
|
||||
for (int i = 0; i < result.drawVertexCount; i++) {
|
||||
const TransformedVertex &vtx = result.drawBuffer[i];
|
||||
GPUDebugVertex &dv = debugVertices[i];
|
||||
GPUDebugVertex &dv = (*debugVertices)[i];
|
||||
dv.x = vtx.x + offsetX;
|
||||
dv.y = vtx.y + offsetY;
|
||||
dv.z = vtx.z;
|
||||
|
||||
@@ -65,6 +65,7 @@ struct SoftwareTransformParams {
|
||||
bool allowClear;
|
||||
bool allowSeparateAlphaClear;
|
||||
bool everUsedEqualDepth;
|
||||
float pointScale = 1.0f; // Useful to increase these for debug views of bounding box corners.
|
||||
};
|
||||
|
||||
// Converts an index buffer to make the provoking vertex the last.
|
||||
@@ -86,4 +87,4 @@ u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int low
|
||||
// In the returned data, you should subtract the value of lowerIndexBound from the indices to get the actual vertex index in the vertices array.
|
||||
// This is because some draws in some games use very large indices, but they only use a small range of them in each PRIM submission.
|
||||
// Additionally, if the transformed flag is set in flags, the indices will be transformed into "generic" types (triangles instead of strips), etc.
|
||||
bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int *lowerIndexBound, TransformStats *stats, DebugVertexFlags flags);
|
||||
bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GECommand cmd, GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> *vertices, std::vector<u16> *indices, int *lowerIndexBound, TransformStats *stats, DebugVertexFlags flags);
|
||||
+33
-32
@@ -805,26 +805,28 @@ static void ExpandSpline(int &count, int op, const std::vector<SimpleVertex> &si
|
||||
FreeAlignedMemory(cpoints.col);
|
||||
}
|
||||
|
||||
bool GetPrimPreview(u32 op, GEPrimitiveType &prim, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int *lowerIndexBound, bool transformed) {
|
||||
u32 prim_type = GE_PRIM_INVALID;
|
||||
bool GetPrimPreview(u32 op, GEPrimitiveType *prim, std::vector<GPUDebugVertex> *vertices, std::vector<u16> *indices, int *lowerIndexBound, bool transformed) {
|
||||
int count_u = 0;
|
||||
int count_v = 0;
|
||||
|
||||
int count = 0;
|
||||
|
||||
const u32 cmd = op >> 24;
|
||||
const GECommand cmd = static_cast<GECommand>(op >> 24);
|
||||
if (cmd == GE_CMD_PRIM) {
|
||||
prim_type = (op >> 16) & 0x7;
|
||||
*prim = static_cast<GEPrimitiveType>((op >> 16) & 0x7); // irrelevant for bbox
|
||||
count = op & 0xFFFF;
|
||||
} else if (cmd == GE_CMD_BOUNDINGBOX) {
|
||||
*prim = GE_PRIM_POINTS; // There's no set order for these, so drawing lines might look strange. Maybe if we draw lines from every vertex to every other...
|
||||
count = op & 0xFFFF;
|
||||
} else {
|
||||
constexpr GEPrimitiveType primLookup[] = { GE_PRIM_TRIANGLES, GE_PRIM_LINES, GE_PRIM_POINTS, GE_PRIM_POINTS };
|
||||
prim_type = primLookup[gstate.getPatchPrimitiveType()];
|
||||
*prim = primLookup[gstate.getPatchPrimitiveType()];
|
||||
count_u = (op & 0x00FF) >> 0;
|
||||
count_v = (op & 0xFF00) >> 8;
|
||||
count = count_u * count_v;
|
||||
}
|
||||
|
||||
if (prim_type >= 7) {
|
||||
if (*prim >= 7) {
|
||||
ERROR_LOG(Log::G3D, "Unsupported prim type: %x", op);
|
||||
return false;
|
||||
}
|
||||
@@ -836,8 +838,6 @@ bool GetPrimPreview(u32 op, GEPrimitiveType &prim, std::vector<GPUDebugVertex> &
|
||||
return false;
|
||||
}
|
||||
|
||||
prim = static_cast<GEPrimitiveType>(prim_type);
|
||||
|
||||
DebugVertexFlags flags = DebugVertexFlags::DrawCoords;
|
||||
if (cmd == GE_CMD_PRIM) {
|
||||
flags |= DebugVertexFlags::Clipped;
|
||||
@@ -845,57 +845,58 @@ bool GetPrimPreview(u32 op, GEPrimitiveType &prim, std::vector<GPUDebugVertex> &
|
||||
flags |= DebugVertexFlags::Transformed;
|
||||
}
|
||||
} else {
|
||||
flags = DebugVertexFlags::Transformed;
|
||||
flags |= DebugVertexFlags::Transformed;
|
||||
}
|
||||
|
||||
GEPrimitiveType outPrim;
|
||||
if (!gpu->GetCurrentDrawAsDebugVertices(prim, &outPrim, count, vertices, indices, lowerIndexBound, nullptr, flags)) {
|
||||
if (!gpu->GetCurrentDrawAsDebugVertices(cmd, *prim, &outPrim, count, vertices, indices, lowerIndexBound, nullptr, flags)) {
|
||||
ERROR_LOG(Log::G3D, "Vertex preview not yet supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sanity check the output (for debugging)
|
||||
if (indices.size()) {
|
||||
for (int i = 0; i < indices.size(); ++i) {
|
||||
int offsetIndex = indices[i] - *lowerIndexBound;
|
||||
if (offsetIndex >= vertices.size() || offsetIndex < 0) {
|
||||
ERROR_LOG(Log::G3D, "Invalid vertex index %d (%d) (vertex count %d)", indices[i], offsetIndex, (int)vertices.size());
|
||||
if (indices->size()) {
|
||||
for (int i = 0; i < indices->size(); ++i) {
|
||||
int offsetIndex = (*indices)[i] - *lowerIndexBound;
|
||||
if (offsetIndex >= vertices->size() || offsetIndex < 0) {
|
||||
ERROR_LOG(Log::G3D, "Invalid vertex index %d (%d) (vertex count %d)", (*indices)[i], offsetIndex, (int)vertices->size());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
prim = outPrim;
|
||||
*prim = outPrim;
|
||||
|
||||
if (cmd != GE_CMD_PRIM) {
|
||||
if (cmd != GE_CMD_PRIM && cmd != GE_CMD_BOUNDINGBOX) {
|
||||
static std::vector<SimpleVertex> generatedVerts;
|
||||
static std::vector<u16> generatedInds;
|
||||
|
||||
static std::vector<SimpleVertex> simpleVerts;
|
||||
simpleVerts.resize(vertices.size());
|
||||
for (size_t i = 0; i < vertices.size(); ++i) {
|
||||
simpleVerts.resize(vertices->size());
|
||||
for (size_t i = 0; i < vertices->size(); ++i) {
|
||||
// For now, let's just copy back so we can use TessellateBezierPatch/TessellateSplinePatch...
|
||||
simpleVerts[i].uv[0] = vertices[i].u;
|
||||
simpleVerts[i].uv[1] = vertices[i].v;
|
||||
simpleVerts[i].pos = Vec3Packedf(vertices[i].x, vertices[i].y, vertices[i].z);
|
||||
simpleVerts[i].uv[0] = (*vertices)[i].u;
|
||||
simpleVerts[i].uv[1] = (*vertices)[i].v;
|
||||
simpleVerts[i].pos = Vec3Packedf((*vertices)[i].x, (*vertices)[i].y, (*vertices)[i].z);
|
||||
}
|
||||
|
||||
*lowerIndexBound = 0;
|
||||
if (cmd == GE_CMD_BEZIER) {
|
||||
ExpandBezier(count, op, simpleVerts, indices, generatedVerts, generatedInds);
|
||||
ExpandBezier(count, op, simpleVerts, *indices, generatedVerts, generatedInds);
|
||||
} else if (cmd == GE_CMD_SPLINE) {
|
||||
ExpandSpline(count, op, simpleVerts, indices, generatedVerts, generatedInds);
|
||||
ExpandSpline(count, op, simpleVerts, *indices, generatedVerts, generatedInds);
|
||||
}
|
||||
|
||||
vertices.resize(generatedVerts.size());
|
||||
for (size_t i = 0; i < vertices.size(); ++i) {
|
||||
vertices[i].u = generatedVerts[i].uv[0];
|
||||
vertices[i].v = generatedVerts[i].uv[1];
|
||||
vertices[i].x = generatedVerts[i].pos.x;
|
||||
vertices[i].y = generatedVerts[i].pos.y;
|
||||
vertices[i].z = generatedVerts[i].pos.z;
|
||||
vertices->resize(generatedVerts.size());
|
||||
for (size_t i = 0; i < vertices->size(); ++i) {
|
||||
auto vertex = &(*vertices)[i];
|
||||
vertex->u = generatedVerts[i].uv[0];
|
||||
vertex->v = generatedVerts[i].uv[1];
|
||||
vertex->x = generatedVerts[i].pos.x;
|
||||
vertex->y = generatedVerts[i].pos.y;
|
||||
vertex->z = generatedVerts[i].pos.z;
|
||||
}
|
||||
indices = generatedInds;
|
||||
*indices = generatedInds;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -68,6 +68,6 @@ void FormatVertColDecoded(char *dest, size_t destSize, const GPUDebugVertex &ver
|
||||
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);
|
||||
bool GetPrimPreview(u32 op, GEPrimitiveType *prim, std::vector<GPUDebugVertex> *vertices, std::vector<u16> *indices, int *lowerIndexBound, bool transformed);
|
||||
void DescribePixel(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]);
|
||||
void DescribePixelRGBA(u32 pix, GPUDebugBufferFormat fmt, int x, int y, char desc[256]);
|
||||
+22
-13
@@ -1579,23 +1579,29 @@ bool GPUCommon::GetCurrentDisplayList(DisplayList &list) const {
|
||||
return true;
|
||||
}
|
||||
|
||||
int GPUCommon::GetCurrentPrimCount(GEPrimitiveType *prim) const {
|
||||
int GPUCommon::GetCurrentPrim(GEPrimitiveType *prim, GECommand *outCmd) const {
|
||||
DisplayList list;
|
||||
u32 cmd;
|
||||
u32 cmdWord;
|
||||
if (GetCurrentDisplayList(list)) {
|
||||
cmd = Memory::Read_U32(list.pc);
|
||||
cmdWord = Memory::Read_U32(list.pc);
|
||||
} else {
|
||||
// Current prim value.
|
||||
cmd = gstate.cmdmem[GE_CMD_PRIM];
|
||||
cmdWord = gstate.cmdmem[GE_CMD_PRIM];
|
||||
}
|
||||
|
||||
if ((cmd >> 24) == GE_CMD_PRIM || (cmd >> 24) == GE_CMD_BOUNDINGBOX) {
|
||||
*prim = GEPrimitiveType((cmd >> 16) & 7);
|
||||
return cmd & 0xFFFF;
|
||||
} else if ((cmd >> 24) == GE_CMD_BEZIER || (cmd >> 24) == GE_CMD_SPLINE) {
|
||||
GECommand cmd = static_cast<GECommand>(cmdWord >> 24);
|
||||
*outCmd = cmd;
|
||||
|
||||
if (cmd == GE_CMD_PRIM) {
|
||||
*prim = GEPrimitiveType((cmdWord >> 16) & 7);
|
||||
return cmdWord & 0xFFFF;
|
||||
} else if (cmd == GE_CMD_BOUNDINGBOX) {
|
||||
*prim = GE_PRIM_POINTS;
|
||||
return cmdWord & 0xFFFF;
|
||||
} else if (cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE) {
|
||||
*prim = GE_PRIM_TRIANGLES; // no correct answer
|
||||
u32 u = (cmd & 0x00FF) >> 0;
|
||||
u32 v = (cmd & 0xFF00) >> 8;
|
||||
u32 u = (cmdWord & 0x00FF) >> 0;
|
||||
u32 v = (cmdWord & 0xFF00) >> 8;
|
||||
return u * v;
|
||||
} else {
|
||||
// Unknown primitive.
|
||||
@@ -2028,8 +2034,8 @@ bool GPUCommon::PerformWriteStencilFromMemory(u32 dest, int size, WriteStencil f
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GPUCommon::GetCurrentDrawAsDebugVertices(GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int *lowerIndexBound, TransformStats *stats, DebugVertexFlags flags) const {
|
||||
return ::GetCurrentDrawAsDebugVertices(drawEngineCommon_, prim, outPrim, count, vertices, indices, lowerIndexBound, stats, flags);
|
||||
bool GPUCommon::GetCurrentDrawAsDebugVertices(GECommand cmd, GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> *vertices, std::vector<u16> *indices, int *lowerIndexBound, TransformStats *stats, DebugVertexFlags flags) const {
|
||||
return ::GetCurrentDrawAsDebugVertices(drawEngineCommon_, cmd, prim, outPrim, count, vertices, indices, lowerIndexBound, stats, flags);
|
||||
}
|
||||
|
||||
bool GPUCommon::DescribeCodePtr(const u8 *ptr, std::string &name) {
|
||||
@@ -2057,6 +2063,7 @@ void GPUCommon::SetBreakNext(GPUDebug::BreakNext next) {
|
||||
break;
|
||||
case GPUDebug::BreakNext::PRIM:
|
||||
case GPUDebug::BreakNext::COUNT:
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_BOUNDINGBOX, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_PRIM, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_BEZIER, true);
|
||||
breakpoints_.AddCmdBreakpoint(GE_CMD_SPLINE, true);
|
||||
@@ -2106,7 +2113,9 @@ GPUDebug::NotifyResult GPUCommon::NotifyCommand(u32 pc, GPUBreakpoints *breakpoi
|
||||
bool isPrim = false;
|
||||
|
||||
bool process = true; // Process is only for the restrictPrimRanges functionality
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_VAP || cmd == GE_CMD_TRANSFERSTART) { // VAP is immediate mode prims.
|
||||
|
||||
// NOTE: We now consider BBOX a PRIM command.
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BEZIER || cmd == GE_CMD_SPLINE || cmd == GE_CMD_VAP || cmd == GE_CMD_TRANSFERSTART || cmd == GE_CMD_BOUNDINGBOX) { // VAP is immediate mode prims.
|
||||
isPrim = true;
|
||||
primsThisFrame_++;
|
||||
|
||||
|
||||
+3
-2
@@ -75,8 +75,8 @@ public:
|
||||
virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer) { return false; }
|
||||
|
||||
bool GetCurrentDisplayList(DisplayList &list) const;
|
||||
bool GetCurrentDrawAsDebugVertices(GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices, int *lowerIndexBound, TransformStats *stats, DebugVertexFlags flags) const;
|
||||
int GetCurrentPrimCount(GEPrimitiveType *prim) const;
|
||||
bool GetCurrentDrawAsDebugVertices(GECommand cmd, GEPrimitiveType prim, GEPrimitiveType *outPrim, int count, std::vector<GPUDebugVertex> *vertices, std::vector<u16> *indices, int *lowerIndexBound, TransformStats *stats, DebugVertexFlags flags) const;
|
||||
int GetCurrentPrim(GEPrimitiveType *prim, GECommand *outCmd) const; // Return value has the count.
|
||||
|
||||
// FinishInitOnMainThread runs on the main thread, of course.
|
||||
virtual void FinishInitOnMainThread() {}
|
||||
@@ -201,6 +201,7 @@ public:
|
||||
|
||||
virtual FramebufferManagerCommon *GetFramebufferManagerCommon() { return nullptr; }
|
||||
virtual TextureCacheCommon *GetTextureCacheCommon() { return nullptr; }
|
||||
const DrawEngineCommon *GetDrawEngineCommon() const { return drawEngineCommon_; }
|
||||
|
||||
virtual std::vector<std::string> DebugGetShaderIDs(DebugShaderType shader) { return std::vector<std::string>(); };
|
||||
virtual std::string DebugGetShaderString(std::string id, DebugShaderType shader, DebugShaderStringType stringType) {
|
||||
|
||||
@@ -1,5 +1,268 @@
|
||||
#include "GPU/ge_constants.h"
|
||||
|
||||
const char *GeCmdToString(GECommand cmd) {
|
||||
switch (cmd) {
|
||||
case GE_CMD_NOP: return "NOP";
|
||||
case GE_CMD_VADDR: return "VADDR";
|
||||
case GE_CMD_IADDR: return "IADDR";
|
||||
case GE_CMD_PRIM: return "PRIM";
|
||||
case GE_CMD_BEZIER: return "BEZIER";
|
||||
case GE_CMD_SPLINE: return "SPLINE";
|
||||
case GE_CMD_BOUNDINGBOX: return "BOUNDINGBOX";
|
||||
case GE_CMD_JUMP: return "JUMP";
|
||||
case GE_CMD_BJUMP: return "BJUMP";
|
||||
case GE_CMD_CALL: return "CALL";
|
||||
case GE_CMD_RET: return "RET";
|
||||
case GE_CMD_END: return "END";
|
||||
case GE_CMD_SIGNAL: return "SIGNAL";
|
||||
case GE_CMD_FINISH: return "FINISH";
|
||||
case GE_CMD_BASE: return "BASE";
|
||||
case GE_CMD_VERTEXTYPE: return "VERTEXTYPE";
|
||||
case GE_CMD_OFFSETADDR: return "OFFSETADDR";
|
||||
case GE_CMD_ORIGIN: return "ORIGIN";
|
||||
case GE_CMD_REGION1: return "REGION1";
|
||||
case GE_CMD_REGION2: return "REGION2";
|
||||
case GE_CMD_LIGHTINGENABLE: return "LIGHTINGENABLE";
|
||||
case GE_CMD_LIGHTENABLE0: return "LIGHTENABLE0";
|
||||
case GE_CMD_LIGHTENABLE1: return "LIGHTENABLE1";
|
||||
case GE_CMD_LIGHTENABLE2: return "LIGHTENABLE2";
|
||||
case GE_CMD_LIGHTENABLE3: return "LIGHTENABLE3";
|
||||
case GE_CMD_DEPTHCLIPENABLE: return "DEPTHCLIPENABLE";
|
||||
case GE_CMD_CULLFACEENABLE: return "CULLFACEENABLE";
|
||||
case GE_CMD_TEXTUREMAPENABLE: return "TEXTUREMAPENABLE";
|
||||
case GE_CMD_FOGENABLE: return "FOGENABLE";
|
||||
case GE_CMD_DITHERENABLE: return "DITHERENABLE";
|
||||
case GE_CMD_ALPHABLENDENABLE: return "ALPHABLENDENABLE";
|
||||
case GE_CMD_ALPHATESTENABLE: return "ALPHATESTENABLE";
|
||||
case GE_CMD_ZTESTENABLE: return "ZTESTENABLE";
|
||||
case GE_CMD_STENCILTESTENABLE: return "STENCILTESTENABLE";
|
||||
case GE_CMD_ANTIALIASENABLE: return "ANTIALIASENABLE";
|
||||
case GE_CMD_PATCHCULLENABLE: return "PATCHCULLENABLE";
|
||||
case GE_CMD_COLORTESTENABLE: return "COLORTESTENABLE";
|
||||
case GE_CMD_LOGICOPENABLE: return "LOGICOPENABLE";
|
||||
case GE_CMD_BONEMATRIXNUMBER: return "BONEMATRIXNUMBER";
|
||||
case GE_CMD_BONEMATRIXDATA: return "BONEMATRIXDATA";
|
||||
case GE_CMD_MORPHWEIGHT0: return "MORPHWEIGHT0";
|
||||
case GE_CMD_MORPHWEIGHT1: return "MORPHWEIGHT1";
|
||||
case GE_CMD_MORPHWEIGHT2: return "MORPHWEIGHT2";
|
||||
case GE_CMD_MORPHWEIGHT3: return "MORPHWEIGHT3";
|
||||
case GE_CMD_MORPHWEIGHT4: return "MORPHWEIGHT4";
|
||||
case GE_CMD_MORPHWEIGHT5: return "MORPHWEIGHT5";
|
||||
case GE_CMD_MORPHWEIGHT6: return "MORPHWEIGHT6";
|
||||
case GE_CMD_MORPHWEIGHT7: return "MORPHWEIGHT7";
|
||||
case GE_CMD_PATCHDIVISION: return "PATCHDIVISION";
|
||||
case GE_CMD_PATCHPRIMITIVE: return "PATCHPRIMITIVE";
|
||||
case GE_CMD_PATCHFACING: return "PATCHFACING";
|
||||
case GE_CMD_WORLDMATRIXNUMBER: return "WORLDMATRIXNUMBER";
|
||||
case GE_CMD_WORLDMATRIXDATA: return "WORLDMATRIXDATA";
|
||||
case GE_CMD_VIEWMATRIXNUMBER: return "VIEWMATRIXNUMBER";
|
||||
case GE_CMD_VIEWMATRIXDATA: return "VIEWMATRIXDATA";
|
||||
case GE_CMD_PROJMATRIXNUMBER: return "PROJMATRIXNUMBER";
|
||||
case GE_CMD_PROJMATRIXDATA: return "PROJMATRIXDATA";
|
||||
case GE_CMD_TGENMATRIXNUMBER: return "TGENMATRIXNUMBER";
|
||||
case GE_CMD_TGENMATRIXDATA: return "TGENMATRIXDATA";
|
||||
case GE_CMD_VIEWPORTXSCALE: return "VIEWPORTXSCALE";
|
||||
case GE_CMD_VIEWPORTYSCALE: return "VIEWPORTYSCALE";
|
||||
case GE_CMD_VIEWPORTZSCALE: return "VIEWPORTZSCALE";
|
||||
case GE_CMD_VIEWPORTXCENTER: return "VIEWPORTXCENTER";
|
||||
case GE_CMD_VIEWPORTYCENTER: return "VIEWPORTYCENTER";
|
||||
case GE_CMD_VIEWPORTZCENTER: return "VIEWPORTZCENTER";
|
||||
case GE_CMD_TEXSCALEU: return "TEXSCALEU";
|
||||
case GE_CMD_TEXSCALEV: return "TEXSCALEV";
|
||||
case GE_CMD_TEXOFFSETU: return "TEXOFFSETU";
|
||||
case GE_CMD_TEXOFFSETV: return "TEXOFFSETV";
|
||||
case GE_CMD_OFFSETX: return "OFFSETX";
|
||||
case GE_CMD_OFFSETY: return "OFFSETY";
|
||||
case GE_CMD_SHADEMODE: return "SHADEMODE"; // flat or gouraud
|
||||
case GE_CMD_REVERSENORMAL: return "REVERSENORMAL";
|
||||
case GE_CMD_MATERIALUPDATE: return "MATERIALUPDATE";
|
||||
case GE_CMD_MATERIALEMISSIVE: return "MATERIALEMISSIVE"; //not sure about these but this makes sense
|
||||
case GE_CMD_MATERIALAMBIENT: return "MATERIALAMBIENT"; //gotta try enabling lighting and check :)
|
||||
case GE_CMD_MATERIALDIFFUSE: return "MATERIALDIFFUSE";
|
||||
case GE_CMD_MATERIALSPECULAR: return "MATERIALSPECULAR";
|
||||
case GE_CMD_MATERIALALPHA: return "MATERIALALPHA";
|
||||
case GE_CMD_MATERIALSPECULARCOEF: return "MATERIALSPECULARCOEF";
|
||||
case GE_CMD_AMBIENTCOLOR: return "AMBIENTCOLOR";
|
||||
case GE_CMD_AMBIENTALPHA: return "AMBIENTALPHA";
|
||||
case GE_CMD_LIGHTMODE: return "LIGHTMODE";
|
||||
case GE_CMD_LIGHTTYPE0: return "LIGHTTYPE0";
|
||||
case GE_CMD_LIGHTTYPE1: return "LIGHTTYPE1";
|
||||
case GE_CMD_LIGHTTYPE2: return "LIGHTTYPE2";
|
||||
case GE_CMD_LIGHTTYPE3: return "LIGHTTYPE3";
|
||||
case GE_CMD_LX0: return "LX0";
|
||||
case GE_CMD_LY0: return "LY0";
|
||||
case GE_CMD_LZ0: return "LZ0";
|
||||
case GE_CMD_LX1: return "LX1";
|
||||
case GE_CMD_LY1: return "LY1";
|
||||
case GE_CMD_LZ1: return "LZ1";
|
||||
case GE_CMD_LX2: return "LX2";
|
||||
case GE_CMD_LY2: return "LY2";
|
||||
case GE_CMD_LZ2: return "LZ2";
|
||||
case GE_CMD_LX3: return "LX3";
|
||||
case GE_CMD_LY3: return "LY3";
|
||||
case GE_CMD_LZ3: return "LZ3";
|
||||
case GE_CMD_LDX0: return "LDX0";
|
||||
case GE_CMD_LDY0: return "LDY0";
|
||||
case GE_CMD_LDZ0: return "LDZ0";
|
||||
case GE_CMD_LDX1: return "LDX1";
|
||||
case GE_CMD_LDY1: return "LDY1";
|
||||
case GE_CMD_LDZ1: return "LDZ1";
|
||||
case GE_CMD_LDX2: return "LDX2";
|
||||
case GE_CMD_LDY2: return "LDY2";
|
||||
case GE_CMD_LDZ2: return "LDZ2";
|
||||
case GE_CMD_LDX3: return "LDX3";
|
||||
case GE_CMD_LDY3: return "LDY3";
|
||||
case GE_CMD_LDZ3: return "LDZ3";
|
||||
case GE_CMD_LKA0: return "LKA0";
|
||||
case GE_CMD_LKB0: return "LKB0";
|
||||
case GE_CMD_LKC0: return "LKC0";
|
||||
case GE_CMD_LKA1: return "LKA1";
|
||||
case GE_CMD_LKB1: return "LKB1";
|
||||
case GE_CMD_LKC1: return "LKC1";
|
||||
case GE_CMD_LKA2: return "LKA2";
|
||||
case GE_CMD_LKB2: return "LKB2";
|
||||
case GE_CMD_LKC2: return "LKC2";
|
||||
case GE_CMD_LKA3: return "LKA3";
|
||||
case GE_CMD_LKB3: return "LKB3";
|
||||
case GE_CMD_LKC3: return "LKC3";
|
||||
case GE_CMD_LKS0: return "LKS0";
|
||||
case GE_CMD_LKS1: return "LKS1";
|
||||
case GE_CMD_LKS2: return "LKS2";
|
||||
case GE_CMD_LKS3: return "LKS3";
|
||||
case GE_CMD_LKO0: return "LKO0";
|
||||
case GE_CMD_LKO1: return "LKO1";
|
||||
case GE_CMD_LKO2: return "LKO2";
|
||||
case GE_CMD_LKO3: return "LKO3";
|
||||
case GE_CMD_LAC0: return "LAC0";
|
||||
case GE_CMD_LDC0: return "LDC0";
|
||||
case GE_CMD_LSC0: return "LSC0";
|
||||
case GE_CMD_LAC1: return "LAC1";
|
||||
case GE_CMD_LDC1: return "LDC1";
|
||||
case GE_CMD_LSC1: return "LSC1";
|
||||
case GE_CMD_LAC2: return "LAC2";
|
||||
case GE_CMD_LDC2: return "LDC2";
|
||||
case GE_CMD_LSC2: return "LSC2";
|
||||
case GE_CMD_LAC3: return "LAC3";
|
||||
case GE_CMD_LDC3: return "LDC3";
|
||||
case GE_CMD_LSC3: return "LSC3";
|
||||
case GE_CMD_CULL: return "CULL";
|
||||
case GE_CMD_FRAMEBUFPTR: return "FRAMEBUFPTR";
|
||||
case GE_CMD_FRAMEBUFWIDTH: return "FRAMEBUFWIDTH";
|
||||
case GE_CMD_ZBUFPTR: return "ZBUFPTR";
|
||||
case GE_CMD_ZBUFWIDTH: return "ZBUFWIDTH";
|
||||
case GE_CMD_TEXADDR0: return "TEXADDR0";
|
||||
case GE_CMD_TEXADDR1: return "TEXADDR1";
|
||||
case GE_CMD_TEXADDR2: return "TEXADDR2";
|
||||
case GE_CMD_TEXADDR3: return "TEXADDR3";
|
||||
case GE_CMD_TEXADDR4: return "TEXADDR4";
|
||||
case GE_CMD_TEXADDR5: return "TEXADDR5";
|
||||
case GE_CMD_TEXADDR6: return "TEXADDR6";
|
||||
case GE_CMD_TEXADDR7: return "TEXADDR7";
|
||||
case GE_CMD_TEXBUFWIDTH0: return "TEXBUFWIDTH0";
|
||||
case GE_CMD_TEXBUFWIDTH1: return "TEXBUFWIDTH1";
|
||||
case GE_CMD_TEXBUFWIDTH2: return "TEXBUFWIDTH2";
|
||||
case GE_CMD_TEXBUFWIDTH3: return "TEXBUFWIDTH3";
|
||||
case GE_CMD_TEXBUFWIDTH4: return "TEXBUFWIDTH4";
|
||||
case GE_CMD_TEXBUFWIDTH5: return "TEXBUFWIDTH5";
|
||||
case GE_CMD_TEXBUFWIDTH6: return "TEXBUFWIDTH6";
|
||||
case GE_CMD_TEXBUFWIDTH7: return "TEXBUFWIDTH7";
|
||||
case GE_CMD_CLUTADDR: return "CLUTADDR";
|
||||
case GE_CMD_CLUTADDRUPPER: return "CLUTADDRUPPER";
|
||||
case GE_CMD_TRANSFERSRC: return "TRANSFERSRC";
|
||||
case GE_CMD_TRANSFERSRCW: return "TRANSFERSRCW";
|
||||
case GE_CMD_TRANSFERDST: return "TRANSFERDST";
|
||||
case GE_CMD_TRANSFERDSTW: return "TRANSFERDSTW";
|
||||
case GE_CMD_TEXSIZE0: return "TEXSIZE0";
|
||||
case GE_CMD_TEXSIZE1: return "TEXSIZE1";
|
||||
case GE_CMD_TEXSIZE2: return "TEXSIZE2";
|
||||
case GE_CMD_TEXSIZE3: return "TEXSIZE3";
|
||||
case GE_CMD_TEXSIZE4: return "TEXSIZE4";
|
||||
case GE_CMD_TEXSIZE5: return "TEXSIZE5";
|
||||
case GE_CMD_TEXSIZE6: return "TEXSIZE6";
|
||||
case GE_CMD_TEXSIZE7: return "TEXSIZE7";
|
||||
case GE_CMD_TEXMAPMODE: return "TEXMAPMODE";
|
||||
case GE_CMD_TEXSHADELS: return "TEXSHADELS";
|
||||
case GE_CMD_TEXMODE: return "TEXMODE";
|
||||
case GE_CMD_TEXFORMAT: return "TEXFORMAT";
|
||||
case GE_CMD_LOADCLUT: return "LOADCLUT";
|
||||
case GE_CMD_CLUTFORMAT: return "CLUTFORMAT";
|
||||
case GE_CMD_TEXFILTER: return "TEXFILTER";
|
||||
case GE_CMD_TEXWRAP: return "TEXWRAP";
|
||||
case GE_CMD_TEXLEVEL: return "TEXLEVEL";
|
||||
case GE_CMD_TEXFUNC: return "TEXFUNC";
|
||||
case GE_CMD_TEXENVCOLOR: return "TEXENVCOLOR";
|
||||
case GE_CMD_TEXFLUSH: return "TEXFLUSH";
|
||||
case GE_CMD_TEXSYNC: return "TEXSYNC";
|
||||
case GE_CMD_FOG1: return "FOG1";
|
||||
case GE_CMD_FOG2: return "FOG2";
|
||||
case GE_CMD_FOGCOLOR: return "FOGCOLOR";
|
||||
case GE_CMD_TEXLODSLOPE: return "TEXLODSLOPE";
|
||||
case GE_CMD_FRAMEBUFPIXFORMAT: return "FRAMEBUFPIXFORMAT";
|
||||
case GE_CMD_CLEARMODE: return "CLEARMODE";
|
||||
case GE_CMD_SCISSOR1: return "SCISSOR1";
|
||||
case GE_CMD_SCISSOR2: return "SCISSOR2";
|
||||
case GE_CMD_MINZ: return "MINZ";
|
||||
case GE_CMD_MAXZ: return "MAXZ";
|
||||
case GE_CMD_COLORTEST: return "COLORTEST";
|
||||
case GE_CMD_COLORREF: return "COLORREF";
|
||||
case GE_CMD_COLORTESTMASK: return "COLORTESTMASK";
|
||||
case GE_CMD_ALPHATEST: return "ALPHATEST";
|
||||
case GE_CMD_STENCILTEST: return "STENCILTEST";
|
||||
case GE_CMD_STENCILOP: return "STENCILOP";
|
||||
case GE_CMD_ZTEST: return "ZTEST";
|
||||
case GE_CMD_BLENDMODE: return "BLENDMODE";
|
||||
case GE_CMD_BLENDFIXEDA: return "BLENDFIXEDA";
|
||||
case GE_CMD_BLENDFIXEDB: return "BLENDFIXEDB";
|
||||
case GE_CMD_DITH0: return "DITH0";
|
||||
case GE_CMD_DITH1: return "DITH1";
|
||||
case GE_CMD_DITH2: return "DITH2";
|
||||
case GE_CMD_DITH3: return "DITH3";
|
||||
case GE_CMD_LOGICOP: return "LOGICOP";
|
||||
case GE_CMD_ZWRITEDISABLE: return "ZWRITEDISABLE";
|
||||
case GE_CMD_MASKRGB: return "MASKRGB";
|
||||
case GE_CMD_MASKALPHA: return "MASKALPHA";
|
||||
case GE_CMD_TRANSFERSTART: return "TRANSFERSTART";
|
||||
case GE_CMD_TRANSFERSRCPOS: return "TRANSFERSRCPOS";
|
||||
case GE_CMD_TRANSFERDSTPOS: return "TRANSFERDSTPOS";
|
||||
case GE_CMD_TRANSFERSIZE: return "TRANSFERSIZE";
|
||||
case GE_CMD_VSCX: return "VSCX";
|
||||
case GE_CMD_VSCY: return "VSCY";
|
||||
case GE_CMD_VSCZ: return "VSCZ";
|
||||
case GE_CMD_VTCS: return "VTCS";
|
||||
case GE_CMD_VTCT: return "VTCT";
|
||||
case GE_CMD_VTCQ: return "VTCQ";
|
||||
case GE_CMD_VCV: return "VCV";
|
||||
case GE_CMD_VAP: return "VAP";
|
||||
case GE_CMD_VFC: return "VFC";
|
||||
case GE_CMD_VSCV: return "VSCV";
|
||||
case GE_CMD_UNKNOWN_03: return "UNKNOWN_03";
|
||||
case GE_CMD_UNKNOWN_0D: return "UNKNOWN_0D";
|
||||
case GE_CMD_UNKNOWN_11: return "UNKNOWN_11";
|
||||
case GE_CMD_UNKNOWN_29: return "UNKNOWN_29";
|
||||
case GE_CMD_UNKNOWN_34: return "UNKNOWN_34";
|
||||
case GE_CMD_UNKNOWN_35: return "UNKNOWN_35";
|
||||
case GE_CMD_UNKNOWN_39: return "UNKNOWN_39";
|
||||
case GE_CMD_UNKNOWN_4E: return "UNKNOWN_4E";
|
||||
case GE_CMD_UNKNOWN_4F: return "UNKNOWN_4F";
|
||||
case GE_CMD_UNKNOWN_52: return "UNKNOWN_52";
|
||||
case GE_CMD_UNKNOWN_59: return "UNKNOWN_59";
|
||||
case GE_CMD_UNKNOWN_5A: return "UNKNOWN_5A";
|
||||
case GE_CMD_UNKNOWN_B6: return "UNKNOWN_B6";
|
||||
case GE_CMD_UNKNOWN_B7: return "UNKNOWN_B7";
|
||||
case GE_CMD_UNKNOWN_D1: return "UNKNOWN_D1";
|
||||
case GE_CMD_UNKNOWN_ED: return "UNKNOWN_ED";
|
||||
case GE_CMD_UNKNOWN_EF: return "UNKNOWN_EF";
|
||||
case GE_CMD_UNKNOWN_FA: return "UNKNOWN_FA";
|
||||
case GE_CMD_UNKNOWN_FB: return "UNKNOWN_FB";
|
||||
case GE_CMD_UNKNOWN_FC: return "UNKNOWN_FC";
|
||||
case GE_CMD_UNKNOWN_FD: return "UNKNOWN_FD";
|
||||
case GE_CMD_UNKNOWN_FE: return "UNKNOWN_FE";
|
||||
case GE_CMD_NOP_FF: return "NOP_FF";
|
||||
default:
|
||||
return "INVALID";
|
||||
}
|
||||
}
|
||||
|
||||
const char *GePrimTypeToString(GEPrimitiveType prim) {
|
||||
static constexpr const char * primTypes[8] = {
|
||||
"POINTS",
|
||||
|
||||
@@ -278,6 +278,8 @@ enum GECommand : uint8_t {
|
||||
GE_CMD_NOP_FF = 0xFF,
|
||||
};
|
||||
|
||||
const char *GeCmdToString(GECommand cmd);
|
||||
|
||||
#define GE_VTYPE_TRANSFORM (0<<23)
|
||||
#define GE_VTYPE_THROUGH (1<<23)
|
||||
#define GE_VTYPE_THROUGH_MASK (1<<23)
|
||||
|
||||
+23
-25
@@ -11,6 +11,7 @@
|
||||
#include "GPU/Common/TextureCacheCommon.h"
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SoftwareTransformCommon.h"
|
||||
#include "GPU/Common/DrawEngineCommon.h"
|
||||
|
||||
#include "Core/HLE/sceDisplay.h"
|
||||
#include "Core/HW/Display.h"
|
||||
@@ -891,7 +892,7 @@ static const char *DLStateToString(DisplayListState state) {
|
||||
}
|
||||
|
||||
// TODO: Backport this to the Win32 debugger (ugh).
|
||||
static void DrawPreviewPrimitive(ImDrawList *drawList, ImVec2 p0, GEPrimitiveType prim, const std::vector<u16> &indices, const std::vector<GPUDebugVertex> &verts, int indexOffset, bool transformed, bool uvToPos, float sx, float sy) {
|
||||
static void DrawPreviewPrimitive(ImDrawList *drawList, ImVec2 p0, GECommand cmd, GEPrimitiveType prim, const std::vector<u16> &indices, const std::vector<GPUDebugVertex> &verts, int indexOffset, bool transformed, bool uvToPos, float sx, float sy) {
|
||||
// These wrappers are to either draw using the positions or the UV coordinates.
|
||||
auto x = [sx, uvToPos](const GPUDebugVertex &vert) {
|
||||
return sx * (uvToPos ? vert.u : vert.x);
|
||||
@@ -1208,34 +1209,25 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuD
|
||||
|
||||
u32 op = 0;
|
||||
DisplayList list;
|
||||
bool isOnBlockTransfer = false;
|
||||
if (gpuDebug->GetCurrentDisplayList(list)) {
|
||||
_dbg_assert_(Memory::IsValid4AlignedAddress(list.pc));
|
||||
op = Memory::ReadUnchecked_U32(list.pc);
|
||||
|
||||
GECommand cmd = static_cast<GECommand>(op >> 24);
|
||||
previewCmd_ = cmd;
|
||||
// TODO: Also add support for block transfer previews!
|
||||
|
||||
bool isOnPrim = false;
|
||||
switch (op >> 24) {
|
||||
case GE_CMD_PRIM:
|
||||
isOnPrim = true;
|
||||
if (cmd == GE_CMD_PRIM || cmd == GE_CMD_BOUNDINGBOX) {
|
||||
if (reloadPreview_) {
|
||||
GetPrimPreview(op, previewPrim_, previewVertices_, previewIndices_, &previewIndexOffset_, previewTransformed_);
|
||||
GetPrimPreview(op, &previewPrim_, &previewVertices_, &previewIndices_, &previewIndexOffset_, previewTransformed_);
|
||||
reloadPreview_ = false;
|
||||
}
|
||||
break;
|
||||
case GE_CMD_TRANSFERSTART:
|
||||
isOnBlockTransfer = true;
|
||||
break;
|
||||
default:
|
||||
} else {
|
||||
// Disable the current preview.
|
||||
previewVertices_.clear();
|
||||
previewIndices_.clear();
|
||||
previewIndexOffset_ = 0;
|
||||
previewTransformed_ = true;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ImGui::BeginChild("texture/fb view");
|
||||
@@ -1243,7 +1235,7 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuD
|
||||
ImDrawList *drawList = ImGui::GetWindowDrawList();
|
||||
|
||||
if (coreState == CORE_STEPPING_GE) {
|
||||
if (isOnBlockTransfer) {
|
||||
if (previewCmd_ == GE_CMD_TRANSFERSTART) {
|
||||
ImGui::Text("Block transfer! Proper preview coming in the future.\n");
|
||||
ImGui::Text("%08x -> %08x, %d bpp (strides: %d, %d)", gstate.getTransferSrcAddress(), gstate.getTransferDstAddress(), gstate.getTransferBpp(), gstate.getTransferSrcStride(), gstate.getTransferDstStride());
|
||||
ImGui::Text("%dx%d pixels", gstate.getTransferWidth(), gstate.getTransferHeight());
|
||||
@@ -1318,7 +1310,7 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuD
|
||||
|
||||
// Draw vertex preview on top!
|
||||
if (!previewVertices_.empty()) {
|
||||
DrawPreviewPrimitive(drawList, p0, previewPrim_, previewIndices_, previewVertices_, previewIndexOffset_, previewTransformed_, false, scale * previewZoom_, scale * previewZoom_);
|
||||
DrawPreviewPrimitive(drawList, p0, previewCmd_, previewPrim_, previewIndices_, previewVertices_, previewIndexOffset_, previewTransformed_, false, scale * previewZoom_, scale * previewZoom_);
|
||||
}
|
||||
|
||||
drawList->PopClipRect();
|
||||
@@ -1347,7 +1339,7 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuD
|
||||
ImGui::Text("(clear mode - texturing not used)");
|
||||
} else if (!gstate.isTextureMapEnabled()) {
|
||||
ImGui::Text("(texturing not enabled");
|
||||
} else {
|
||||
} else { // We don't bother with the texture if previewCmd is BOUNDING_BOX - no texturing happens there.
|
||||
TextureCacheCommon *texcache = gpuDebug->GetTextureCacheCommon();
|
||||
TexCacheEntry *tex = texcache ? texcache->SetTexture() : nullptr;
|
||||
if (tex) {
|
||||
@@ -1369,8 +1361,11 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuD
|
||||
|
||||
ImGui::Image(texId, ImVec2(texW, texH));
|
||||
|
||||
// Show the preview as texcoords. TODO: We should probably use unclipped data here?
|
||||
DrawPreviewPrimitive(drawList, p0, previewPrim_, previewIndices_, previewVertices_, previewIndexOffset_, previewTransformed_, true, texW, texH);
|
||||
// Don't bother with trying to preview bounding box here, it only has positions, no texcoords.
|
||||
if (previewCmd_ == GE_CMD_PRIM || previewCmd_ == GE_CMD_BEZIER || previewCmd_ == GE_CMD_SPLINE) {
|
||||
// Show the preview as texcoords. TODO: We should probably use unclipped data here?
|
||||
DrawPreviewPrimitive(drawList, p0, previewCmd_, previewPrim_, previewIndices_, previewVertices_, previewIndexOffset_, previewTransformed_, true, texW, texH);
|
||||
}
|
||||
|
||||
drawList->PopClipRect();
|
||||
|
||||
@@ -1705,7 +1700,7 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebu
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebug) {
|
||||
void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUCommon *gpu) {
|
||||
ImGui::SetNextWindowSize(ImVec2(300, 500), ImGuiCond_FirstUseEver);
|
||||
if (!ImGui::Begin("GE Vertices", &cfg.geVertsOpen)) {
|
||||
ImGui::End();
|
||||
@@ -1724,7 +1719,7 @@ void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebug)
|
||||
ImGuiTableFlags_Resizable | ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersOuter | ImGuiTableFlags_BordersV | ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_ScrollY;
|
||||
|
||||
if (ImGui::BeginTabBar("vertexmode", ImGuiTabBarFlags_None)) {
|
||||
auto state = gpuDebug->GetGState();
|
||||
auto state = gpu->GetGState();
|
||||
auto buildVertexTable = [&](bool transformed) {
|
||||
// Let's see if it's fast enough to just do all this each frame.
|
||||
GEPrimitiveType prim;
|
||||
@@ -1740,11 +1735,14 @@ void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebug)
|
||||
flags |= DebugVertexFlags::Clipped;
|
||||
}
|
||||
|
||||
int inputVertexCount = gpuDebug->GetCurrentPrimCount(&prim);
|
||||
GECommand cmd;
|
||||
int inputVertexCount = gpu->GetCurrentPrim(&prim, &cmd);
|
||||
|
||||
// TODO: If cmd is BOUNDING_BOX, actually test the bounding box here and show the result.
|
||||
|
||||
// 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)) {
|
||||
if (!gpu->GetCurrentDrawAsDebugVertices(cmd, prim, &prim, inputVertexCount, &vertices, &indices, &indexOffset, &stats, flags)) {
|
||||
inputVertexCount = 0;
|
||||
}
|
||||
|
||||
@@ -1752,7 +1750,7 @@ void DrawImGeVertsWindow(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebug)
|
||||
|
||||
char statusLine[256];
|
||||
StringWriter w(statusLine);
|
||||
w.F("%s: ", GePrimTypeToString(prim));
|
||||
w.F("%s - %s: ", GeCmdToString(cmd), GePrimTypeToString(prim));
|
||||
char fmtTemp[256];
|
||||
FormatStateRow(fmtTemp, sizeof(fmtTemp), CMD_FMT_VERTEXTYPE, state.vertType, true, false, false);
|
||||
w.F("%s", fmtTemp);
|
||||
|
||||
@@ -158,6 +158,7 @@ private:
|
||||
ImGePixelViewer swViewer_;
|
||||
int showBannerInFrames_ = 0;
|
||||
bool reloadPreview_ = false;
|
||||
GECommand previewCmd_{};
|
||||
GEPrimitiveType previewPrim_ = GEPrimitiveType::GE_PRIM_TRIANGLES;
|
||||
std::vector<u16> previewIndices_;
|
||||
std::vector<GPUDebugVertex> previewVertices_;
|
||||
|
||||
@@ -200,7 +200,8 @@ int CtrlVertexList::GetRowCount() {
|
||||
auto state = gpu->GetGState();
|
||||
|
||||
GEPrimitiveType prim;
|
||||
rowCount_ = gpu->GetCurrentPrimCount(&prim);
|
||||
GECommand cmd;
|
||||
rowCount_ = gpu->GetCurrentPrim(&prim, &cmd);
|
||||
|
||||
previewIndexOffset_ = 0;
|
||||
|
||||
@@ -213,7 +214,7 @@ int CtrlVertexList::GetRowCount() {
|
||||
}
|
||||
|
||||
TransformStats stats;
|
||||
if (!gpu->GetCurrentDrawAsDebugVertices(prim, &prim, rowCount_, vertices, indices, &previewIndexOffset_, &stats, flags)) {
|
||||
if (!gpu->GetCurrentDrawAsDebugVertices(cmd, prim, &prim, rowCount_, &vertices, &indices, &previewIndexOffset_, &stats, flags)) {
|
||||
rowCount_ = 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ void CGEDebugger::UpdatePrimPreview(u32 op, int which) {
|
||||
GEPrimitiveType prim;
|
||||
int previewIndexOffset;
|
||||
bool previewTransformed;
|
||||
if (!GetPrimPreview(op, prim, vertices, indices, &previewIndexOffset, &previewTransformed)) {
|
||||
if (!GetPrimPreview(op, &prim, &vertices, &indices, &previewIndexOffset, &previewTransformed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user