Add support for 32-bit indices.

Not clear how often these are used by games.  Let's find out.
This commit is contained in:
Unknown W. Brackets 2016-04-10 01:52:51 -07:00
parent d85dce0c21
commit 1e0051a792
14 changed files with 181 additions and 97 deletions

View File

@ -201,23 +201,32 @@ bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector<GPUDebugV
if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) {
const u8 *inds = Memory::GetPointer(gstate_c.indexAddr);
const u16 *inds16 = (const u16 *)inds;
const u32 *inds32 = (const u32 *)inds;
if (inds) {
GetIndexBounds(inds, count, gstate.vertType, &indexLowerBound, &indexUpperBound);
indices.resize(count);
switch (gstate.vertType & GE_VTYPE_IDX_MASK) {
case GE_VTYPE_IDX_16BIT:
for (int i = 0; i < count; ++i) {
indices[i] = inds16[i];
}
break;
case GE_VTYPE_IDX_8BIT:
for (int i = 0; i < count; ++i) {
indices[i] = inds[i];
}
break;
default:
return false;
case GE_VTYPE_IDX_16BIT:
for (int i = 0; i < count; ++i) {
indices[i] = inds16[i];
}
break;
case GE_VTYPE_IDX_32BIT:
WARN_LOG_REPORT_ONCE(simpleIndexes32, G3D, "SimpleVertices: Decoding 32-bit indexes");
for (int i = 0; i < count; ++i) {
// These aren't documented and should be rare. Let's bounds check each one.
if (inds32[i] != (u16)inds32[i]) {
ERROR_LOG_REPORT_ONCE(simpleIndexes32Bounds, G3D, "SimpleVertices: Index outside 16-bit range");
}
indices[i] = (u16)inds32[i];
}
break;
}
} else {
indices.clear();

View File

@ -62,6 +62,16 @@ protected:
VertexDecoder *GetVertexDecoder(u32 vtype);
inline int IndexSize(u32 vtype) const {
const u32 indexType = (vtype & GE_VTYPE_IDX_MASK);
if (indexType == GE_VTYPE_IDX_16BIT) {
return 2;
} else if (indexType == GE_VTYPE_IDX_32BIT) {
return 4;
}
return 1;
}
// Vertex collector buffers
u8 *decoded;
u16 *decIndex;

View File

@ -112,7 +112,7 @@ void IndexGenerator::AddStrip(int numVerts) {
inds_ = outInds;
index_ += numVerts;
if (numTris > 0)
count_ += numTris * 3;
count_ += numTris * 3;
// This is so we can detect one single strip by just looking at seenPrims_.
if (!seenPrims_) {
seenPrims_ = 1 << GE_PRIM_TRIANGLE_STRIP;
@ -187,10 +187,9 @@ void IndexGenerator::AddRectangles(int numVerts) {
seenPrims_ |= 1 << GE_PRIM_RECTANGLES;
}
template <class IType, class ITypeLE, int flag>
void IndexGenerator::TranslatePoints(int numInds, const IType *_inds, int indexOffset) {
template <class ITypeLE, int flag>
void IndexGenerator::TranslatePoints(int numInds, const ITypeLE *inds, int indexOffset) {
indexOffset = index_ - indexOffset;
const ITypeLE *inds = (const IType *)_inds;
u16 *outInds = inds_;
for (int i = 0; i < numInds; i++)
*outInds++ = indexOffset + inds[i];
@ -200,10 +199,9 @@ void IndexGenerator::TranslatePoints(int numInds, const IType *_inds, int indexO
seenPrims_ |= (1 << GE_PRIM_POINTS) | flag;
}
template <class IType, class ITypeLE, int flag>
void IndexGenerator::TranslateLineList(int numInds, const IType *_inds, int indexOffset) {
template <class ITypeLE, int flag>
void IndexGenerator::TranslateLineList(int numInds, const ITypeLE *inds, int indexOffset) {
indexOffset = index_ - indexOffset;
const ITypeLE *inds = (ITypeLE*)_inds;
u16 *outInds = inds_;
numInds = numInds & ~1;
for (int i = 0; i < numInds; i += 2) {
@ -216,10 +214,9 @@ void IndexGenerator::TranslateLineList(int numInds, const IType *_inds, int inde
seenPrims_ |= (1 << GE_PRIM_LINES) | flag;
}
template <class IType, class ITypeLE, int flag>
void IndexGenerator::TranslateLineStrip(int numInds, const IType *_inds, int indexOffset) {
template <class ITypeLE, int flag>
void IndexGenerator::TranslateLineStrip(int numInds, const ITypeLE *inds, int indexOffset) {
indexOffset = index_ - indexOffset;
const ITypeLE *inds = (const ITypeLE*)_inds;
int numLines = numInds - 1;
u16 *outInds = inds_;
for (int i = 0; i < numLines; i++) {
@ -232,9 +229,8 @@ void IndexGenerator::TranslateLineStrip(int numInds, const IType *_inds, int ind
seenPrims_ |= (1 << GE_PRIM_LINE_STRIP) | flag;
}
template <class IType, class ITypeLE, int flag>
void IndexGenerator::TranslateList(int numInds, const IType *_inds, int indexOffset) {
const ITypeLE *inds = (const IType *)_inds;
template <class ITypeLE, int flag>
void IndexGenerator::TranslateList(int numInds, const ITypeLE *inds, int indexOffset) {
indexOffset = index_ - indexOffset;
u16 *outInds = inds_;
int numTris = numInds / 3; // Round to whole triangles
@ -250,9 +246,8 @@ void IndexGenerator::TranslateList(int numInds, const IType *_inds, int indexOff
seenPrims_ |= (1 << GE_PRIM_TRIANGLES) | flag;
}
template <class IType, class ITypeLE, int flag>
void IndexGenerator::TranslateStrip(int numInds, const IType *_inds, int indexOffset) {
const IType *inds = (ITypeLE*)_inds;
template <class ITypeLE, int flag>
void IndexGenerator::TranslateStrip(int numInds, const ITypeLE *inds, int indexOffset) {
int wind = 1;
indexOffset = index_ - indexOffset;
int numTris = numInds - 2;
@ -269,9 +264,8 @@ void IndexGenerator::TranslateStrip(int numInds, const IType *_inds, int indexOf
seenPrims_ |= (1 << GE_PRIM_TRIANGLE_STRIP) | flag;
}
template <class IType, class ITypeLE, int flag>
void IndexGenerator::TranslateFan(int numInds, const IType *_inds, int indexOffset) {
const ITypeLE *inds = (IType*)_inds;
template <class ITypeLE, int flag>
void IndexGenerator::TranslateFan(int numInds, const ITypeLE *inds, int indexOffset) {
if (numInds <= 0) return;
indexOffset = index_ - indexOffset;
int numTris = numInds - 2;
@ -287,10 +281,9 @@ void IndexGenerator::TranslateFan(int numInds, const IType *_inds, int indexOffs
seenPrims_ |= (1 << GE_PRIM_TRIANGLE_FAN) | flag;
}
template <class IType, class ITypeLE, int flag>
inline void IndexGenerator::TranslateRectangles(int numInds, const IType *_inds, int indexOffset) {
template <class ITypeLE, int flag>
inline void IndexGenerator::TranslateRectangles(int numInds, const ITypeLE *inds, int indexOffset) {
indexOffset = index_ - indexOffset;
const ITypeLE *inds = (const ITypeLE*)_inds;
u16 *outInds = inds_;
//rectangles always need 2 vertices, disregard the last one if there's an odd number
numInds = numInds & ~1;
@ -307,36 +300,36 @@ inline void IndexGenerator::TranslateRectangles(int numInds, const IType *_inds,
// Could template this too, but would have to define in header.
void IndexGenerator::TranslatePrim(int prim, int numInds, const u8 *inds, int indexOffset) {
switch (prim) {
case GE_PRIM_POINTS: TranslatePoints<u8, u8, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_LINES: TranslateLineList<u8, u8, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_LINE_STRIP: TranslateLineStrip<u8, u8, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLES: TranslateList<u8, u8, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_STRIP: TranslateStrip<u8, u8, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_FAN: TranslateFan<u8, u8, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_RECTANGLES: TranslateRectangles<u8, u8, SEEN_INDEX16>(numInds, inds, indexOffset); break; // Same
case GE_PRIM_POINTS: TranslatePoints<u8, SEEN_INDEX8>(numInds, inds, indexOffset); break;
case GE_PRIM_LINES: TranslateLineList<u8, SEEN_INDEX8>(numInds, inds, indexOffset); break;
case GE_PRIM_LINE_STRIP: TranslateLineStrip<u8, SEEN_INDEX8>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLES: TranslateList<u8, SEEN_INDEX8>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_STRIP: TranslateStrip<u8, SEEN_INDEX8>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_FAN: TranslateFan<u8, SEEN_INDEX8>(numInds, inds, indexOffset); break;
case GE_PRIM_RECTANGLES: TranslateRectangles<u8, SEEN_INDEX8>(numInds, inds, indexOffset); break; // Same
}
}
void IndexGenerator::TranslatePrim(int prim, int numInds, const u16 *inds, int indexOffset) {
switch (prim) {
case GE_PRIM_POINTS: TranslatePoints<u16, u16_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_LINES: TranslateLineList<u16, u16_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_LINE_STRIP: TranslateLineStrip<u16, u16_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLES: TranslateList<u16, u16_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_STRIP: TranslateStrip<u16, u16_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_FAN: TranslateFan<u16, u16_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_RECTANGLES: TranslateRectangles<u16, u16_le, SEEN_INDEX16>(numInds, inds, indexOffset); break; // Same
case GE_PRIM_POINTS: TranslatePoints<u16_le, SEEN_INDEX16>(numInds, (const u16_le *)inds, indexOffset); break;
case GE_PRIM_LINES: TranslateLineList<u16_le, SEEN_INDEX16>(numInds, (const u16_le *)inds, indexOffset); break;
case GE_PRIM_LINE_STRIP: TranslateLineStrip<u16_le, SEEN_INDEX16>(numInds, (const u16_le *)inds, indexOffset); break;
case GE_PRIM_TRIANGLES: TranslateList<u16_le, SEEN_INDEX16>(numInds, (const u16_le *)inds, indexOffset); break;
case GE_PRIM_TRIANGLE_STRIP: TranslateStrip<u16_le, SEEN_INDEX16>(numInds, (const u16_le *)inds, indexOffset); break;
case GE_PRIM_TRIANGLE_FAN: TranslateFan<u16_le, SEEN_INDEX16>(numInds, (const u16_le *)inds, indexOffset); break;
case GE_PRIM_RECTANGLES: TranslateRectangles<u16_le, SEEN_INDEX16>(numInds, (const u16_le *)inds, indexOffset); break; // Same
}
}
void IndexGenerator::TranslatePrim(int prim, int numInds, const u32 *inds, int indexOffset) {
switch (prim) {
case GE_PRIM_POINTS: TranslatePoints<u32, u32_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_LINES: TranslateLineList<u32, u32_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_LINE_STRIP: TranslateLineStrip<u32, u32_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLES: TranslateList<u32, u32_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_STRIP: TranslateStrip<u32, u32_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_TRIANGLE_FAN: TranslateFan<u32, u32_le, SEEN_INDEX16>(numInds, inds, indexOffset); break;
case GE_PRIM_RECTANGLES: TranslateRectangles<u32, u32_le, SEEN_INDEX16>(numInds, inds, indexOffset); break; // Same
case GE_PRIM_POINTS: TranslatePoints<u32_le, SEEN_INDEX32>(numInds, (const u32_le *)inds, indexOffset); break;
case GE_PRIM_LINES: TranslateLineList<u32_le, SEEN_INDEX32>(numInds, (const u32_le *)inds, indexOffset); break;
case GE_PRIM_LINE_STRIP: TranslateLineStrip<u32_le, SEEN_INDEX32>(numInds, (const u32_le *)inds, indexOffset); break;
case GE_PRIM_TRIANGLES: TranslateList<u32_le, SEEN_INDEX32>(numInds, (const u32_le *)inds, indexOffset); break;
case GE_PRIM_TRIANGLE_STRIP: TranslateStrip<u32_le, SEEN_INDEX32>(numInds, (const u32_le *)inds, indexOffset); break;
case GE_PRIM_TRIANGLE_FAN: TranslateFan<u32_le, SEEN_INDEX32>(numInds, (const u32_le *)inds, indexOffset); break;
case GE_PRIM_RECTANGLES: TranslateRectangles<u32_le, SEEN_INDEX32>(numInds, (const u32_le *)inds, indexOffset); break; // Same
}
}
}

View File

@ -66,26 +66,27 @@ private:
void AddRectangles(int numVerts);
// These translate already indexed lists
template <class IType, class ITypeLE, int flag>
void TranslatePoints(int numVerts, const IType *inds, int indexOffset);
template <class IType, class ITypeLE, int flag>
void TranslateList(int numVerts, const IType *_inds, int indexOffset);
template <class IType, class ITypeLE, int flag>
inline void TranslateLineList(int numVerts, const IType *inds, int indexOffset);
template <class IType, class ITypeLE, int flag>
inline void TranslateLineStrip(int numVerts, const IType *inds, int indexOffset);
template <class ITypeLE, int flag>
void TranslatePoints(int numVerts, const ITypeLE *inds, int indexOffset);
template <class ITypeLE, int flag>
void TranslateList(int numVerts, const ITypeLE *inds, int indexOffset);
template <class ITypeLE, int flag>
inline void TranslateLineList(int numVerts, const ITypeLE *inds, int indexOffset);
template <class ITypeLE, int flag>
inline void TranslateLineStrip(int numVerts, const ITypeLE *inds, int indexOffset);
template <class IType, class ITypeLE, int flag>
void TranslateStrip(int numVerts, const IType *inds, int indexOffset);
template <class IType, class ITypeLE, int flag>
void TranslateFan(int numVerts, const IType *inds, int indexOffset);
template <class ITypeLE, int flag>
void TranslateStrip(int numVerts, const ITypeLE *inds, int indexOffset);
template <class ITypeLE, int flag>
void TranslateFan(int numVerts, const ITypeLE *inds, int indexOffset);
template <class IType, class ITypeLE, int flag>
inline void TranslateRectangles(int numVerts, const IType *inds, int indexOffset);
template <class ITypeLE, int flag>
inline void TranslateRectangles(int numVerts, const ITypeLE *inds, int indexOffset);
enum {
SEEN_INDEX8 = 1 << 16,
SEEN_INDEX16 = 1 << 17
SEEN_INDEX16 = 1 << 17,
SEEN_INDEX32 = 1 << 18,
};
u16 *indsBase_;

View File

@ -791,10 +791,12 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
bool indices_32bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT;
const u8 *indices8 = (const u8 *)indices;
const u16 *indices16 = (const u16 *)indices;
const u32 *indices32 = (const u32 *)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
GetIndexBounds(indices, count_u * count_v, vertType, &index_lower_bound, &index_upper_bound);
// Simplify away bones and morph before proceeding
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
@ -815,10 +817,19 @@ void DrawEngineCommon::SubmitSpline(const void *control_points, const void *indi
// Make an array of pointers to the control points, to get rid of indices.
for (int idx = 0; idx < count_u * count_v; idx++) {
if (indices)
points[idx] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
if (indices) {
u32 ind;
if (indices_32bit) {
ind = indices32[idx];
} else if (indices_16bit) {
ind = indices16[idx];
} else {
ind = indices8[idx];
}
points[idx] = simplified_control_points + ind;
} else {
points[idx] = simplified_control_points + idx;
}
}
int count = 0;
@ -876,8 +887,10 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
const u8* indices8 = (const u8*)indices;
const u16* indices16 = (const u16*)indices;
bool indices_32bit = (vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT;
const u8 *indices8 = (const u8 *)indices;
const u16 *indices16 = (const u16 *)indices;
const u32 *indices32 = (const u32 *)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertType, &index_lower_bound, &index_upper_bound);
@ -905,10 +918,19 @@ void DrawEngineCommon::SubmitBezier(const void *control_points, const void *indi
BezierPatch& patch = patches[patch_u + patch_v * num_patches_u];
for (int point = 0; point < 16; ++point) {
int idx = (patch_u * 3 + point % 4) + (patch_v * 3 + point / 4) * count_u;
if (indices)
patch.points[point] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
else
if (indices) {
u32 ind;
if (indices_32bit) {
ind = indices32[idx];
} else if (indices_16bit) {
ind = indices16[idx];
} else {
ind = indices8[idx];
}
patch.points[point] = simplified_control_points + ind;
} else {
patch.points[point] = simplified_control_points + idx;
}
}
patch.u_index = patch_u * 3;
patch.v_index = patch_v * 3;

View File

@ -95,7 +95,7 @@ void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBo
lowerBound = value;
}
} else if (idx == GE_VTYPE_IDX_16BIT) {
const u16 *ind16 = (const u16*)inds;
const u16 *ind16 = (const u16 *)inds;
for (int i = 0; i < count; i++) {
u16 value = ind16[i];
if (value > upperBound)
@ -103,6 +103,20 @@ void GetIndexBounds(const void *inds, int count, u32 vertType, u16 *indexLowerBo
if (value < lowerBound)
lowerBound = value;
}
} else if (idx == GE_VTYPE_IDX_32BIT) {
WARN_LOG_REPORT_ONCE(indexBounds32, G3D, "GetIndexBounds: Decoding 32-bit indexes");
const u32 *ind32 = (const u32 *)inds;
for (int i = 0; i < count; i++) {
u16 value = (u16)ind32[i];
// These aren't documented and should be rare. Let's bounds check each one.
if (ind32[i] != value) {
ERROR_LOG_REPORT_ONCE(indexBounds32Bounds, G3D, "GetIndexBounds: Index outside 16-bit range");
}
if (value > upperBound)
upperBound = value;
if (value < lowerBound)
lowerBound = value;
}
} else {
lowerBound = 0;
upperBound = count - 1;

View File

@ -462,7 +462,7 @@ inline u32 ComputeMiniHashRange(const void *ptr, size_t sz) {
u32 DrawEngineDX9::ComputeMiniHash() {
u32 fullhash = 0;
const int vertexSize = dec_->GetDecVtxFmt().stride;
const int indexSize = (dec_->VertexType() & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT ? 2 : 1;
const int indexSize = IndexSize(dec_->VertexType());
int step;
if (numDrawCalls < 3) {
@ -501,7 +501,7 @@ void DrawEngineDX9::MarkUnreliable(VertexArrayInfoDX9 *vai) {
ReliableHashType DrawEngineDX9::ComputeHash() {
ReliableHashType fullhash = 0;
const int vertexSize = dec_->GetDecVtxFmt().stride;
const int indexSize = (dec_->VertexType() & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT ? 2 : 1;
const int indexSize = IndexSize(dec_->VertexType());
// TODO: Add some caps both for numDrawCalls and num verts to check?
// It is really very expensive to check all the vertex data so often.

View File

@ -840,6 +840,8 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) {
int indexSize = 1;
if ((vertexType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT)
indexSize = 2;
else if ((vertexType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT)
indexSize = 4;
gstate_c.indexAddr += count * indexSize;
} else {
gstate_c.vertexAddr += bytesRead;

View File

@ -471,7 +471,7 @@ inline u32 ComputeMiniHashRange(const void *ptr, size_t sz) {
u32 DrawEngineGLES::ComputeMiniHash() {
u32 fullhash = 0;
const int vertexSize = dec_->GetDecVtxFmt().stride;
const int indexSize = (dec_->VertexType() & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT ? 2 : 1;
const int indexSize = IndexSize(dec_->VertexType());
int step;
if (numDrawCalls < 3) {
@ -510,7 +510,7 @@ void DrawEngineGLES::MarkUnreliable(VertexArrayInfo *vai) {
ReliableHashType DrawEngineGLES::ComputeHash() {
ReliableHashType fullhash = 0;
const int vertexSize = dec_->GetDecVtxFmt().stride;
const int indexSize = (dec_->VertexType() & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT ? 2 : 1;
const int indexSize = IndexSize(dec_->VertexType());
// TODO: Add some caps both for numDrawCalls and num verts to check?
// It is really very expensive to check all the vertex data so often.

View File

@ -1009,6 +1009,8 @@ void GPU_GLES::Execute_Prim(u32 op, u32 diff) {
int indexSize = 1;
if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT)
indexSize = 2;
else if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT)
indexSize = 4;
gstate_c.indexAddr += count * indexSize;
} else {
gstate_c.vertexAddr += bytesRead;

View File

@ -48,6 +48,12 @@ void GeDescribeVertexType(u32 op, char *buffer, int len) {
"u16",
"float",
};
static const char *typeNamesI[] = {
NULL,
"u8",
"u16",
"u32",
};
static const char *typeNamesS[] = {
NULL,
"s8",
@ -72,8 +78,8 @@ void GeDescribeVertexType(u32 op, char *buffer, int len) {
w += snprintf(w, end - w, "unknown weights (%d), ", weightCount);
if (morphCount > 0 && w < end)
w += snprintf(w, end - w, "%d morphs, ", morphCount);
if (typeNames[idx] && w < end)
w += snprintf(w, end - w, "%s indexes, ", typeNames[idx]);
if (typeNamesI[idx] && w < end)
w += snprintf(w, end - w, "%s indexes, ", typeNamesI[idx]);
if (w < buffer + 2)
snprintf(buffer, len, "none");

View File

@ -336,6 +336,8 @@ void SoftGPU::ExecuteOp(u32 op, u32 diff)
int indexSize = 1;
if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT)
indexSize = 2;
else if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT)
indexSize = 4;
gstate_c.indexAddr += count * indexSize;
} else {
gstate_c.vertexAddr += bytesRead;

View File

@ -227,8 +227,10 @@ void TransformUnit::SubmitSpline(void* control_points, void* indices, int count_
u16 index_lower_bound = 0;
u16 index_upper_bound = count_u * count_v - 1;
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
u8* indices8 = (u8*)indices;
u16* indices16 = (u16*)indices;
bool indices_32bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT;
u8 *indices8 = (u8 *)indices;
u16 *indices16 = (u16 *)indices;
u32 *indices32 = (u32 *)indices;
if (indices)
GetIndexBounds(indices, count_u*count_v, vertex_type, &index_lower_bound, &index_upper_bound);
vdecoder.DecodeVerts(buf, control_points, index_lower_bound, index_upper_bound);
@ -253,10 +255,17 @@ void TransformUnit::SubmitSpline(void* control_points, void* indices, int count_
for (int point = 0; point < 16; ++point) {
int idx = (patch_u + point%4) + (patch_v + point/4) * count_u;
if (indices)
vreader.Goto(indices_16bit ? indices16[idx] : indices8[idx]);
else
if (indices) {
if (indices_32bit) {
vreader.Goto(indices32[idx]);
} else if (indices_16bit) {
vreader.Goto(indices16[idx]);
} else {
vreader.Goto(indices8[idx]);
}
} else {
vreader.Goto(idx);
}
patch.points[point] = ReadVertex(vreader);
}
@ -318,8 +327,10 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type
u16 index_lower_bound = 0;
u16 index_upper_bound = vertex_count - 1;
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
u8* indices8 = (u8*)indices;
u16* indices16 = (u16*)indices;
bool indices_32bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT;
u8 *indices8 = (u8 *)indices;
u16 *indices16 = (u16 *)indices;
u32 *indices32 = (u32 *)indices;
if (indices)
GetIndexBounds(indices, vertex_count, vertex_type, &index_lower_bound, &index_upper_bound);
vdecoder.DecodeVerts(buf, vertices, index_lower_bound, index_upper_bound);
@ -349,10 +360,17 @@ void TransformUnit::SubmitPrimitive(void* vertices, void* indices, u32 prim_type
{
for (int vtx = 0; vtx < vertex_count; vtx += vtcs_per_prim) {
for (int i = 0; i < vtcs_per_prim; ++i) {
if (indices)
vreader.Goto(indices_16bit ? indices16[vtx+i] : indices8[vtx+i]);
else
if (indices) {
if (indices_32bit) {
vreader.Goto(indices32[vtx + i]);
} else if (indices_16bit) {
vreader.Goto(indices16[vtx + i]);
} else {
vreader.Goto(indices8[vtx + i]);
}
} else {
vreader.Goto(vtx+i);
}
data[i] = ReadVertex(vreader);
if (outside_range_flag)
@ -528,12 +546,15 @@ bool TransformUnit::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVert
}
break;
case GE_VTYPE_IDX_32BIT:
WARN_LOG_REPORT_ONCE(simpleIndexes32, G3D, "SimpleVertices: Decoding 32-bit indexes");
for (int i = 0; i < count; ++i) {
indices[i] = inds32[i];
// These aren't documented and should be rare. Let's bounds check each one.
if (inds32[i] != (u16)inds32[i]) {
ERROR_LOG_REPORT_ONCE(simpleIndexes32Bounds, G3D, "SimpleVertices: Index outside 16-bit range");
}
indices[i] = (u16)inds32[i];
}
break;
default:
return false;
}
} else {
indices.clear();

View File

@ -884,6 +884,8 @@ void GPU_Vulkan::Execute_Prim(u32 op, u32 diff) {
int indexSize = 1;
if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT)
indexSize = 2;
else if ((gstate.vertType & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_32BIT)
indexSize = 4;
gstate_c.indexAddr += count * indexSize;
} else {
gstate_c.vertexAddr += bytesRead;