GPU: Correct bounding box for larger counts.

Matches tests on a PSP with float/transform format.
This commit is contained in:
Unknown W. Brackets 2022-10-22 09:06:33 -07:00
parent 299033929a
commit 6ddf22487b
3 changed files with 20 additions and 11 deletions

View File

@ -244,7 +244,7 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex
//
// It does the simplest and safest test possible: If all points of a bbox is outside a single of
// our clipping planes, we reject the box. Tighter bounds would be desirable but would take more calculations.
bool DrawEngineCommon::TestBoundingBox(const void* control_points, int vertexCount, u32 vertType, int *bytesRead) {
bool DrawEngineCommon::TestBoundingBox(const void* control_points, int vertexCount, u32 vertType) {
SimpleVertex *corners = (SimpleVertex *)(decoded + 65536 * 12);
float *verts = (float *)(decoded + 65536 * 18);
@ -252,19 +252,16 @@ bool DrawEngineCommon::TestBoundingBox(const void* control_points, int vertexCou
// and a large vertex format.
if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_FLOAT) {
verts = (float *)control_points;
*bytesRead = 3 * sizeof(float) * vertexCount;
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_8BIT) {
const s8 *vtx = (const s8 *)control_points;
for (int i = 0; i < vertexCount * 3; i++) {
verts[i] = vtx[i] * (1.0f / 128.0f);
}
*bytesRead = 3 * sizeof(s8) * vertexCount;
} else if ((vertType & 0xFFFFFF) == GE_VTYPE_POS_16BIT) {
const s16 *vtx = (const s16*)control_points;
for (int i = 0; i < vertexCount * 3; i++) {
verts[i] = vtx[i] * (1.0f / 32768.0f);
}
*bytesRead = 3 * sizeof(s16) * vertexCount;
} else {
// Simplify away bones and morph before proceeding
u8 *temp_buffer = decoded + 65536 * 24;
@ -275,7 +272,6 @@ bool DrawEngineCommon::TestBoundingBox(const void* control_points, int vertexCou
verts[i * 3 + 1] = corners[i].pos.y;
verts[i * 3 + 2] = corners[i].pos.z;
}
*bytesRead = vertexSize * vertexCount;
}
Plane planes[6];

View File

@ -92,7 +92,7 @@ public:
virtual void DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex *buffer, int vertexCount, int cullMode, bool continuation);
bool TestBoundingBox(const void* control_points, int vertexCount, u32 vertType, int *bytesRead);
bool TestBoundingBox(const void* control_points, int vertexCount, u32 vertType);
void SubmitPrim(const void *verts, const void *inds, GEPrimitiveType prim, int vertexCount, u32 vertTypeID, int cullMode, int *bytesRead);
template<class Surface>

View File

@ -2153,13 +2153,17 @@ void GPUCommon::Execute_Spline(u32 op, u32 diff) {
void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) {
// Just resetting, nothing to check bounds for.
const u32 count = op & 0xFFFFFF;
const u32 count = op & 0xFFFF;
if (count == 0) {
currentList->bboxResult = false;
return;
}
if (((count & 7) == 0) && count <= 64) { // Sanity check
const void *control_points = Memory::GetPointer(gstate_c.vertexAddr);
VertexDecoder *dec = drawEngineCommon_->GetVertexDecoder(gstate.vertType);
int bytesRead = dec->VertexSize() * count;
if (Memory::IsValidRange(gstate_c.vertexAddr, bytesRead)) {
const void *control_points = Memory::GetPointerUnchecked(gstate_c.vertexAddr);
if (!control_points) {
ERROR_LOG_REPORT_ONCE(boundingbox, G3D, "Invalid verts in bounding box check");
currentList->bboxResult = true;
@ -2174,8 +2178,17 @@ void GPUCommon::Execute_BoundingBox(u32 op, u32 diff) {
}
// Test if the bounding box is within the drawing region.
int bytesRead;
currentList->bboxResult = drawEngineCommon_->TestBoundingBox(control_points, count, gstate.vertType, &bytesRead);
// The PSP only seems to vary the result based on a single range of 0x100.
if (count > 0x200) {
// The second to last set of 0x100 is checked (even for odd counts.)
size_t skipSize = (count - 0x200) * dec->VertexSize();
currentList->bboxResult = drawEngineCommon_->TestBoundingBox((const uint8_t *)control_points + skipSize, 0x100, gstate.vertType);
} else if (count > 0x100) {
int checkSize = count - 0x100;
currentList->bboxResult = drawEngineCommon_->TestBoundingBox(control_points, checkSize, gstate.vertType);
} else {
currentList->bboxResult = drawEngineCommon_->TestBoundingBox(control_points, count, gstate.vertType);
}
AdvanceVerts(gstate.vertType, count, bytesRead);
} else {
ERROR_LOG_REPORT_ONCE(boundingbox, G3D, "Bad bounding box data: %06x", count);