GFX3D: Remove POLY struct members that don't need to be swapped. This results in less buffer copying for all POLY lists.

- Also remove Viewer3D_State.indexList. This member is obsolete since Viewer3D_State.gList.clippedPolyList is generated in the same order described by indexList.
- Encapsulate and rename some more lists to make their intended purpose more descriptive.
This commit is contained in:
rogerman 2023-02-09 00:27:45 -08:00
parent 23400431a1
commit 242cb63327
2 changed files with 48 additions and 45 deletions

View File

@ -348,10 +348,6 @@ static CACHE_ALIGN s32 cacheHalfVector[4][4];
#define RENDER_FRONT_SURFACE 0x80
#define RENDER_BACK_SURFACE 0X40
//-------------working polygon lists
static PAGE_ALIGN CPoly _clippedPolyUnsortedList[POLYLIST_SIZE];
static int polygonListCompleted = 0;
static u8 triStripToggle;
@ -419,9 +415,6 @@ void GFX3D_SaveStatePOLY(const POLY &p, EMUFILE &os)
os.write_32LE(p.attribute.value);
os.write_32LE(p.texParam.value);
os.write_32LE(p.texPalette);
os.write_32LE(p.viewportLegacySave.value);
os.write_floatLE(p.miny);
os.write_floatLE(p.maxy);
}
void GFX3D_LoadStatePOLY(POLY &p, EMUFILE &is)
@ -437,11 +430,6 @@ void GFX3D_LoadStatePOLY(POLY &p, EMUFILE &is)
is.read_32LE(p.attribute.value);
is.read_32LE(p.texParam.value);
is.read_32LE(p.texPalette);
is.read_32LE(p.viewportLegacySave.value);
is.read_floatLE(p.miny);
is.read_floatLE(p.maxy);
p.viewport = GFX3D_ViewportParse(p.viewportLegacySave.value);
}
void GFX3D_SaveStateVERT(const VERT &vtx, EMUFILE &os)
@ -872,7 +860,7 @@ static void SetVertex()
poly.texParam = currentPolyTexParam;
poly.texPalette = currentPolyTexPalette;
poly.viewport = gfx3d.viewport;
poly.viewportLegacySave = _GFX3D_IORegisterMap->VIEWPORT;
gfx3d.rawPolyViewportLegacySave[pendingGList.rawPolyCount] = _GFX3D_IORegisterMap->VIEWPORT;
pendingGList.rawPolyCount++;
}
}
@ -2284,17 +2272,21 @@ void gfx3d_glFlush(u32 v)
static bool gfx3d_ysort_compare(const u16 idx1, const u16 idx2)
{
const CPoly &cp1 = _clippedPolyUnsortedList[idx1];
const CPoly &cp2 = _clippedPolyUnsortedList[idx2];
const POLY &poly1 = gfx3d.gList[gfx3d.appliedListIndex].rawPolyList[cp1.index];
const POLY &poly2 = gfx3d.gList[gfx3d.appliedListIndex].rawPolyList[cp2.index];
const CPoly &cp1 = gfx3d.clippedPolyUnsortedList[idx1];
const CPoly &cp2 = gfx3d.clippedPolyUnsortedList[idx2];
const float &y1Max = gfx3d.rawPolySortYMax[cp1.index];
const float &y2Max = gfx3d.rawPolySortYMax[cp2.index];
const float &y1Min = gfx3d.rawPolySortYMin[cp1.index];
const float &y2Min = gfx3d.rawPolySortYMin[cp2.index];
//this may be verified by checking the game create menus in harvest moon island of happiness
//also the buttons in the knights in the nightmare frontend depend on this and the perspective division
if (poly1.maxy != poly2.maxy)
return (poly1.maxy < poly2.maxy);
if (poly1.miny != poly2.miny)
return (poly1.miny < poly2.miny);
if (y1Max != y2Max)
return (y1Max < y2Max);
if (y1Min != y2Min)
return (y1Min < y2Min);
//notably, the main shop interface in harvest moon will not have a correct RTN button
//i think this is due to a math error rounding its position to one pixel too high and it popping behind
@ -2341,15 +2333,15 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
switch (clippingMode)
{
case ClipperMode_Full:
outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_Full>(outGList, _clippedPolyUnsortedList);
outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_Full>(outGList, gfx3d.clippedPolyUnsortedList);
break;
case ClipperMode_FullColorInterpolate:
outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_FullColorInterpolate>(outGList, _clippedPolyUnsortedList);
outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_FullColorInterpolate>(outGList, gfx3d.clippedPolyUnsortedList);
break;
case ClipperMode_DetermineClipOnly:
outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_DetermineClipOnly>(outGList, _clippedPolyUnsortedList);
outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_DetermineClipOnly>(outGList, gfx3d.clippedPolyUnsortedList);
break;
}
@ -2365,18 +2357,18 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
size_t ctr = 0;
for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{
const CPoly &clippedPoly = _clippedPolyUnsortedList[i];
const CPoly &clippedPoly = gfx3d.clippedPolyUnsortedList[i];
if ( !GFX3D_IsPolyTranslucent(outGList.rawPolyList[clippedPoly.index]) )
gfx3d.polyWorkingIndexList[ctr++] = i;
gfx3d.indexOfClippedPolyUnsortedList[ctr++] = i;
}
outGList.clippedPolyOpaqueCount = ctr;
//then look for translucent polys
for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{
const CPoly &clippedPoly = _clippedPolyUnsortedList[i];
const CPoly &clippedPoly = gfx3d.clippedPolyUnsortedList[i];
if ( GFX3D_IsPolyTranslucent(outGList.rawPolyList[clippedPoly.index]) )
gfx3d.polyWorkingIndexList[ctr++] = i;
gfx3d.indexOfClippedPolyUnsortedList[ctr++] = i;
}
//find the min and max y values for each poly.
@ -2387,7 +2379,8 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
//2. most geometry is opaque which is always sorted anyway
for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{
POLY &poly = outGList.rawPolyList[_clippedPolyUnsortedList[i].index];
const u16 rawPolyIndex = gfx3d.clippedPolyUnsortedList[i].index;
const POLY &poly = outGList.rawPolyList[rawPolyIndex];
// TODO: Possible divide by zero with the w-coordinate.
// Is the vertex being read correctly? Is 0 a valid value for w?
@ -2396,28 +2389,29 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
float verty = appliedVertList[poly.vertIndexes[0]].y;
float vertw = (appliedVertList[poly.vertIndexes[0]].w != 0.0f) ? appliedVertList[poly.vertIndexes[0]].w : 0.00000001f;
verty = 1.0f-(verty+vertw)/(2*vertw);
poly.miny = poly.maxy = verty;
gfx3d.rawPolySortYMin[rawPolyIndex] = verty;
gfx3d.rawPolySortYMax[rawPolyIndex] = verty;
for (size_t j = 1; j < (size_t)poly.type; j++)
{
verty = appliedVertList[poly.vertIndexes[j]].y;
vertw = (appliedVertList[poly.vertIndexes[j]].w != 0.0f) ? appliedVertList[poly.vertIndexes[j]].w : 0.00000001f;
verty = 1.0f-(verty+vertw)/(2*vertw);
poly.miny = min(poly.miny, verty);
poly.maxy = max(poly.maxy, verty);
gfx3d.rawPolySortYMin[rawPolyIndex] = min(gfx3d.rawPolySortYMin[rawPolyIndex], verty);
gfx3d.rawPolySortYMax[rawPolyIndex] = max(gfx3d.rawPolySortYMax[rawPolyIndex], verty);
}
}
//now we have to sort the opaque polys by y-value.
//(test case: harvest moon island of happiness character creator UI)
//should this be done after clipping??
std::sort(gfx3d.polyWorkingIndexList, gfx3d.polyWorkingIndexList + outGList.clippedPolyOpaqueCount, gfx3d_ysort_compare);
std::sort(gfx3d.indexOfClippedPolyUnsortedList, gfx3d.indexOfClippedPolyUnsortedList + outGList.clippedPolyOpaqueCount, gfx3d_ysort_compare);
if (inState.SWAP_BUFFERS.YSortMode == 0)
{
//if we are autosorting translucent polys, we need to do this also
//TODO - this is unverified behavior. need a test case
std::sort(gfx3d.polyWorkingIndexList + outGList.clippedPolyOpaqueCount, gfx3d.polyWorkingIndexList + outGList.clippedPolyCount, gfx3d_ysort_compare);
std::sort(gfx3d.indexOfClippedPolyUnsortedList + outGList.clippedPolyOpaqueCount, gfx3d.indexOfClippedPolyUnsortedList + outGList.clippedPolyCount, gfx3d_ysort_compare);
}
// Reorder the clipped polygon list to match our sorted index list.
@ -2425,14 +2419,14 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
{
for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{
outGList.clippedPolyList[i].index = _clippedPolyUnsortedList[gfx3d.polyWorkingIndexList[i]].index;
outGList.clippedPolyList[i].index = gfx3d.clippedPolyUnsortedList[gfx3d.indexOfClippedPolyUnsortedList[i]].index;
}
}
else
{
for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{
outGList.clippedPolyList[i] = _clippedPolyUnsortedList[gfx3d.polyWorkingIndexList[i]];
outGList.clippedPolyList[i] = gfx3d.clippedPolyUnsortedList[gfx3d.indexOfClippedPolyUnsortedList[i]];
}
}
}
@ -2472,7 +2466,6 @@ static void gfx3d_doFlush()
memcpy(viewer3D.gList.rawVertList, appliedGList.rawVertList, appliedGList.rawVertCount * sizeof(VERT));
memcpy(viewer3D.gList.rawPolyList, appliedGList.rawPolyList, appliedGList.rawPolyCount * sizeof(POLY));
memcpy(viewer3D.gList.clippedPolyList, appliedGList.clippedPolyList, appliedGList.clippedPolyCount * sizeof(CPoly));
memcpy(viewer3D.indexList, gfx3d.polyWorkingIndexList, appliedGList.clippedPolyCount * sizeof(int));
driver->view3d->NewFrame();
}
@ -2908,6 +2901,9 @@ void gfx3d_savestate(EMUFILE &os)
for (size_t i = 0; i < gfx3d.gList[gfx3d.pendingListIndex].rawPolyCount; i++)
{
GFX3D_SaveStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].rawPolyList[i], os);
os.write_32LE(gfx3d.rawPolyViewportLegacySave[i].value);
os.write_floatLE(gfx3d.rawPolySortYMin[i]);
os.write_floatLE(gfx3d.rawPolySortYMax[i]);
}
// Write matrix stack data
@ -3000,8 +2996,16 @@ bool gfx3d_loadstate(EMUFILE &is, int size)
gfx3d.gList[gfx3d.appliedListIndex].rawPolyCount = polyListCount32;
for (size_t i = 0; i < gfx3d.gList[gfx3d.appliedListIndex].rawPolyCount; i++)
{
GFX3D_LoadStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].rawPolyList[i], is);
gfx3d.gList[gfx3d.appliedListIndex].rawPolyList[i] = gfx3d.gList[gfx3d.pendingListIndex].rawPolyList[i];
POLY &p = gfx3d.gList[gfx3d.pendingListIndex].rawPolyList[i];
GFX3D_LoadStatePOLY(p, is);
is.read_32LE(gfx3d.rawPolyViewportLegacySave[i].value);
is.read_floatLE(gfx3d.rawPolySortYMin[i]);
is.read_floatLE(gfx3d.rawPolySortYMax[i]);
p.viewport = GFX3D_ViewportParse(gfx3d.rawPolyViewportLegacySave[i].value);
gfx3d.gList[gfx3d.appliedListIndex].rawPolyList[i] = p;
}
}

View File

@ -531,10 +531,6 @@ struct POLY
TEXIMAGE_PARAM texParam;
u32 texPalette; //the hardware rendering params
GFX3D_Viewport viewport;
IOREG_VIEWPORT viewportLegacySave; // Exists for save state compatibility.
float miny;
float maxy;
};
typedef struct POLY POLY;
@ -711,7 +707,6 @@ struct Viewer3D_State
int frameNumber;
GFX3D_State state;
GFX3D_GeometryList gList;
int indexList[INDEXLIST_SIZE];
};
typedef struct Viewer3D_State Viewer3D_State;
@ -730,10 +725,14 @@ struct GFX3D
u32 render3DFrameCount; // Increments when gfx3d_doFlush() is called. Resets every 60 video frames.
// Working lists for rendering.
PAGE_ALIGN u16 polyWorkingIndexList[POLYLIST_SIZE * 2];
CACHE_ALIGN CPoly clippedPolyUnsortedList[POLYLIST_SIZE * 2]; // Records clipped polygon info on first pass
CACHE_ALIGN u16 indexOfClippedPolyUnsortedList[POLYLIST_SIZE * 2];
CACHE_ALIGN float rawPolySortYMin[POLYLIST_SIZE]; // Temp buffer used for processing polygon Y-sorting
CACHE_ALIGN float rawPolySortYMax[POLYLIST_SIZE]; // Temp buffer used for processing polygon Y-sorting
// Everything below is for save state compatibility.
IOREG_VIEWPORT viewportLegacySave; // Historically, the viewport was stored as its raw register value.
IOREG_VIEWPORT rawPolyViewportLegacySave[POLYLIST_SIZE]; // Historically, pending polygons kept a copy of the current viewport as a raw register value.
float PTcoordsLegacySave[4]; // Historically, PTcoords were stored as floating point values, not as integers.
PAGE_ALIGN FragmentColor framebufferNativeSave[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; // Rendered 3D framebuffer that is saved in RGBA8888 color format at the native size.
};