mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #21771 from hrydgard/bbox-debug
Fix culling for draws with 8-bit positions, visualize bbox corners in the ImGe debugger
This commit is contained in:
@@ -203,7 +203,8 @@ struct Vec4F32 {
|
||||
static Vec4F32 LoadAligned(const float *src) { return Vec4F32{ _mm_load_ps(src) }; }
|
||||
static Vec4F32 LoadS8Norm(const int8_t *src) {
|
||||
__m128i value = _mm_set1_epi32(*((uint32_t *)src));
|
||||
__m128i value32 = _mm_unpacklo_epi16(_mm_unpacklo_epi8(value, value), value);
|
||||
__m128i value16 = _mm_unpacklo_epi8(value, value);
|
||||
__m128i value32 = _mm_unpacklo_epi16(value16, value16);
|
||||
// Sign extension. A bit ugly without SSE4.
|
||||
value32 = _mm_srai_epi32(value32, 24);
|
||||
return Vec4F32 { _mm_mul_ps(_mm_cvtepi32_ps(value32), _mm_set1_ps(1.0f / 128.0f)) };
|
||||
|
||||
@@ -179,19 +179,15 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex
|
||||
// - Only requires six plane evaluations then.
|
||||
bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int vertexCount, const VertexDecoder *dec, u32 vertType) {
|
||||
// Grab temp buffer space from large offsets in decoded_. Not exactly safe for large draws.
|
||||
if (vertexCount > 1024) {
|
||||
// Although this may lead to drawing that shouldn't happen, the viewport is more complex on VR.
|
||||
// Let's always say objects are within bounds.
|
||||
if (vertexCount > 1024 || gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SimpleVertex *corners = (SimpleVertex *)(decoded_ + 65536 * 12);
|
||||
float *verts = (float *)(decoded_ + 65536 * 18);
|
||||
|
||||
// Although this may lead to drawing that shouldn't happen, the viewport is more complex on VR.
|
||||
// Let's always say objects are within bounds.
|
||||
if (gstate_c.Use(GPU_USE_VIRTUAL_REALITY)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to skip NormalizeVertices if it's pure positions. No need to bother with a vertex decoder
|
||||
// and a large vertex format.
|
||||
|
||||
@@ -333,6 +329,7 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int
|
||||
|
||||
for (int i = 0; i < countToCheck; i++) {
|
||||
if (insideCount[i] == 0) {
|
||||
// All verts were outside one side.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -347,8 +344,8 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int
|
||||
//
|
||||
// NOTE: This doesn't handle through-mode or indexing (morph or skinning can be handled if they're implemented in software during decode).
|
||||
template<u32 posFmt>
|
||||
static bool TestBoundingBoxFast(const float *worldViewProj, const void *vdata, int vertexCount, const VertexDecoder *dec, u8 *decoded, ClipInfoFlags *clipInfoFlags) {
|
||||
Mat4F32 worldViewProjMat(worldViewProj);
|
||||
static bool TestBoundingBoxFast(const float *cullMatrix, const void *vdata, int vertexCount, const VertexDecoder *dec, ClipInfoFlags *clipInfoFlags) {
|
||||
Mat4F32 cullMat(cullMatrix);
|
||||
alignas(16) static const float planesXYData[4] = { 1, -1, 1, -1 };
|
||||
Vec4F32 planesXY = Vec4F32::LoadAligned(planesXYData);
|
||||
Vec4S32 insideMaskXY = Vec4S32::Zero();
|
||||
@@ -358,10 +355,8 @@ static bool TestBoundingBoxFast(const float *worldViewProj, const void *vdata, i
|
||||
// Used to reduce the Z precision. This effectively implements the small offsets where Z can be very slightly outside -1..1.
|
||||
// In reality we should probably affect X and Y too, but meh.
|
||||
alignas(16) static const u32 vertexMaskData[4] = {0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFF00, 0xFFFFFFFF};
|
||||
Vec4S32 vertexMask = Vec4S32::LoadAligned((const int *)vertexMaskData);
|
||||
const int stride = dec->VertexSize();
|
||||
const int offset = dec->posoff;
|
||||
const s8 *data = (const s8 *)vdata + offset;
|
||||
const s8 *data = (const s8 *)vdata + dec->posoff;
|
||||
|
||||
const float vpZScale = gstate.getViewportZScale();
|
||||
|
||||
@@ -381,7 +376,7 @@ static bool TestBoundingBoxFast(const float *worldViewProj, const void *vdata, i
|
||||
objPos = Vec4F32::Load((const float *)data);
|
||||
break;
|
||||
}
|
||||
Vec4F32 clipPos = objPos.AsVec3ByMatrix44(worldViewProjMat) & vertexMask; // Not sure we should do the vertex mask thing.
|
||||
Vec4F32 clipPos = objPos.AsVec3ByMatrix44(cullMat);
|
||||
Vec4F32 posW = clipPos.ShuffleWWWW();
|
||||
Vec4F32 posXY = clipPos.ShuffleXXYY();
|
||||
Vec4F32 planeDistXY = posXY * planesXY + posW;
|
||||
@@ -457,11 +452,11 @@ bool DrawEngineCommon::TestBoundingBoxFast(const float *cullMatrix, const void *
|
||||
|
||||
switch (vertType & GE_VTYPE_POS_MASK) {
|
||||
case GE_VTYPE_POS_8BIT:
|
||||
return ::TestBoundingBoxFast<GE_VTYPE_POS_8BIT>(cullMatrix, vdata, vertexCount, dec, decoded_, flags);
|
||||
return ::TestBoundingBoxFast<GE_VTYPE_POS_8BIT>(cullMatrix, vdata, vertexCount, dec, flags);
|
||||
case GE_VTYPE_POS_16BIT:
|
||||
return ::TestBoundingBoxFast<GE_VTYPE_POS_16BIT>(cullMatrix, vdata, vertexCount, dec, decoded_, flags);
|
||||
return ::TestBoundingBoxFast<GE_VTYPE_POS_16BIT>(cullMatrix, vdata, vertexCount, dec, flags);
|
||||
case GE_VTYPE_POS_FLOAT:
|
||||
return ::TestBoundingBoxFast<GE_VTYPE_POS_FLOAT>(cullMatrix, vdata, vertexCount, dec, decoded_, flags);
|
||||
return ::TestBoundingBoxFast<GE_VTYPE_POS_FLOAT>(cullMatrix, vdata, vertexCount, dec, flags);
|
||||
default:
|
||||
// Shouldn't end up here with the checks outside this function.
|
||||
_dbg_assert_(false);
|
||||
|
||||
@@ -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,21 +1121,22 @@ static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&in
|
||||
u16 *newInds = inds + vertexCount;
|
||||
u16 *indsOut = newInds;
|
||||
|
||||
float dx = 1.0f * gstate_c.vpWidthScale * (1.0f / gstate.getViewportXScale());
|
||||
float dy = 1.0f * gstate_c.vpHeightScale * (1.0f / gstate.getViewportYScale());
|
||||
float du = 1.0f / gstate_c.curTextureWidth;
|
||||
float dv = 1.0f / gstate_c.curTextureHeight;
|
||||
const float offset = pointScale != 1.0f ? -pointScale * 0.5f : 0.0f;
|
||||
|
||||
if (throughmode) {
|
||||
dx = 1.0f;
|
||||
dy = 1.0f;
|
||||
}
|
||||
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;
|
||||
@@ -1173,6 +1174,7 @@ static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&in
|
||||
indsOut[3] = i * 4 + 3;
|
||||
indsOut[4] = i * 4 + 0;
|
||||
indsOut[5] = i * 4 + 2;
|
||||
|
||||
trans += 4;
|
||||
indsOut += 6;
|
||||
}
|
||||
@@ -1314,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;
|
||||
@@ -1377,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] = {
|
||||
@@ -1389,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);
|
||||
@@ -1421,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;
|
||||
}
|
||||
@@ -1469,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;
|
||||
@@ -1492,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;
|
||||
}
|
||||
|
||||
@@ -1513,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]);
|
||||
|
||||
@@ -310,23 +310,6 @@ static void SetMatrix4x3(GLRenderManager *render, GLint *uniform, const float *m
|
||||
render->SetUniformM4x4(uniform, m4x4);
|
||||
}
|
||||
|
||||
static inline void FlipProjMatrix(Matrix4x4 &in) {
|
||||
const bool invertedY = gstate_c.vpHeight < 0;
|
||||
if (invertedY) {
|
||||
in[1] = -in[1];
|
||||
in[5] = -in[5];
|
||||
in[9] = -in[9];
|
||||
in[13] = -in[13];
|
||||
}
|
||||
const bool invertedX = gstate_c.vpWidth < 0;
|
||||
if (invertedX) {
|
||||
in[0] = -in[0];
|
||||
in[4] = -in[4];
|
||||
in[8] = -in[8];
|
||||
in[12] = -in[12];
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool GuessVRDrawingHUD(bool is2D, bool flatScreen) {
|
||||
|
||||
bool hud = true;
|
||||
|
||||
+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) {
|
||||
|
||||
+8
-5
@@ -116,7 +116,7 @@ void GPUgstate::Reset() {
|
||||
|
||||
savedContextVersion = 1;
|
||||
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX);
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX | DIRTY_CULL_MATRIX);
|
||||
}
|
||||
|
||||
void GPUgstate::Save(u32_le *ptr) {
|
||||
@@ -248,7 +248,7 @@ void GPUgstate::Restore(const u32_le *ptr) {
|
||||
if (gpu)
|
||||
gpu->ResetMatrices();
|
||||
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX);
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX | DIRTY_CULL_MATRIX);
|
||||
}
|
||||
|
||||
bool vertTypeIsSkinningEnabled(u32 vertType) {
|
||||
@@ -341,8 +341,11 @@ void GPUStateCache::DoState(PointerWrap &p) {
|
||||
Do(p, actualTextureHeight);
|
||||
// curTextureXOffset and curTextureYOffset don't need to be saved. Well, the above don't either...
|
||||
|
||||
Do(p, vpWidth);
|
||||
Do(p, vpHeight);
|
||||
// previously vpWidth, vpHeight. Remove in future versions.
|
||||
float dummy = 0.0f;
|
||||
Do(p, dummy);
|
||||
Do(p, dummy);
|
||||
|
||||
if (s == 4) {
|
||||
float oldDepth = 1.0f;
|
||||
Do(p, oldDepth);
|
||||
@@ -359,7 +362,7 @@ void GPUStateCache::DoState(PointerWrap &p) {
|
||||
}
|
||||
|
||||
if (p.GetMode() == PointerWrap::MODE_READ) {
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX);
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX | DIRTY_CULL_MATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -651,16 +651,6 @@ public:
|
||||
int curTextureYOffset;
|
||||
bool curTextureIs3D;
|
||||
|
||||
float vpWidth;
|
||||
float vpHeight;
|
||||
|
||||
float vpXOffset;
|
||||
float vpYOffset;
|
||||
float vpZOffset;
|
||||
float vpWidthScale;
|
||||
float vpHeightScale;
|
||||
float vpDepthScale;
|
||||
|
||||
// Cached 4x4 products of the matrices.
|
||||
// Useful for culling and extracing the final Z from vertices (so we can check if clipping is needed).
|
||||
// Most often, world changes the most.
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -1082,7 +1082,7 @@ void SoftGPU::Execute_WorldMtxData(u32 op, u32 diff) {
|
||||
if (newVal != *target) {
|
||||
*target = newVal;
|
||||
dirtyFlags_ |= SoftDirty::TRANSFORM_MATRIX;
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX);
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX | DIRTY_CULL_MATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1103,7 +1103,7 @@ void SoftGPU::Execute_ViewMtxData(u32 op, u32 diff) {
|
||||
if (newVal != *target) {
|
||||
*target = newVal;
|
||||
dirtyFlags_ |= SoftDirty::TRANSFORM_MATRIX;
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX);
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX | DIRTY_CULL_MATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -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)
|
||||
@@ -304,7 +306,7 @@ enum GECommand : uint8_t {
|
||||
#define GE_VTYPE_NRM_MASK (3<<5)
|
||||
#define GE_VTYPE_NRM_SHIFT 5
|
||||
|
||||
//#define GE_VTYPE_POSITION_NONE (0<<5)
|
||||
// No NONE, there is always a position.
|
||||
#define GE_VTYPE_POS_8BIT (1<<7)
|
||||
#define GE_VTYPE_POS_16BIT (2<<7)
|
||||
#define GE_VTYPE_POS_FLOAT (3<<7)
|
||||
|
||||
+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;
|
||||
}
|
||||
|
||||
|
||||
@@ -1219,6 +1219,14 @@ bool TestCrossSIMD() {
|
||||
return false;
|
||||
}
|
||||
|
||||
s8 values[4] = {-1, -128, 127, 45};
|
||||
float fvalues[4];
|
||||
Vec4F32::LoadS8Norm(values).Store(fvalues);
|
||||
static const float known_s8norm_result[4] = {(float)values[0]/128.0f, (float)values[1]/128.0f, (float)values[2]/128.0f, (float)values[3]/128.0f,};
|
||||
if (!CompareFloats(fvalues, known_s8norm_result, ARRAY_SIZE(known_s8norm_result), __LINE__)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// PrintFloats(result, 16);
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user