GFX3D: Various minor tweaks and optimizations, plus code cleanup.

- Most importantly, refactor the GFX3D_Clipper::ClipPoly() method into the standalone GFX3D_GenerateClippedPoly() function, which drops all class member dependencies and is much more straightforward to use.
- Remove the GFX3D_Clipper class. It has been slowly gutted over the years, but the loss of the ClipPoly() method makes the class obsolete, putting the final nail in its coffin.
- Using the new GFX3D_GenerateClippedPoly() function, gfx3d_PerformClipping() operates on the unsorted clipped polygon list directly. This means that the polygon clipping step requires one less buffer copy.
- Clipped polygons no longer retain direct pointers to POLY structs, instead using their index member to reference a POLY struct at a POLY array location. All 3D renderers have been updated to reflect this change.
- Rename a bunch of variables that reference POLY, CPoly, and VERT structs to clearly differentiate them between raw NDS data and our own internally processed data.
- Fix a potential bug in GFX3D_GenerateRenderLists() where sorting clipped polygons would reorder their polygon indices without reordering their other data members along with the indices, causing the data members to desync. OpenGL rendering was immune to this bug, but SoftRasterizer might have possibly seen it. In any case, this fix is the correct behavior.
This commit is contained in:
rogerman 2023-02-06 17:50:42 -08:00
parent 628eb6596a
commit 9554595948
10 changed files with 286 additions and 339 deletions

View File

@ -1743,7 +1743,7 @@ OpenGLTexture* OpenGLRenderer::GetLoadedTextureFromPolygon(const POLY &thePoly,
} }
template <OGLPolyDrawMode DRAWMODE> template <OGLPolyDrawMode DRAWMODE>
size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr) size_t OpenGLRenderer::DrawPolygonsForIndexRange(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr)
{ {
OGLRenderRef &OGLRef = *this->ref; OGLRenderRef &OGLRef = *this->ref;
@ -1774,7 +1774,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
}; };
// Set up the initial polygon // Set up the initial polygon
const POLY &initialPoly = *clippedPolyList[firstIndex].poly; const POLY &initialPoly = rawPolyList[clippedPolyList[firstIndex].index];
TEXIMAGE_PARAM lastTexParams = initialPoly.texParam; TEXIMAGE_PARAM lastTexParams = initialPoly.texParam;
u32 lastTexPalette = initialPoly.texPalette; u32 lastTexPalette = initialPoly.texPalette;
GFX3D_Viewport lastViewport = initialPoly.viewport; GFX3D_Viewport lastViewport = initialPoly.viewport;
@ -1788,28 +1788,28 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
for (size_t i = firstIndex; i <= lastIndex; i++) for (size_t i = firstIndex; i <= lastIndex; i++)
{ {
const POLY &thePoly = *clippedPolyList[i].poly; const POLY &rawPoly = rawPolyList[clippedPolyList[i].index];
// Set up the polygon if it changed // Set up the polygon if it changed
if (lastPolyAttr.value != thePoly.attribute.value) if (lastPolyAttr.value != rawPoly.attribute.value)
{ {
lastPolyAttr = thePoly.attribute; lastPolyAttr = rawPoly.attribute;
this->SetupPolygon(thePoly, (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys), (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass)); this->SetupPolygon(rawPoly, (DRAWMODE != OGLPolyDrawMode_DrawOpaquePolys), (DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass));
} }
// Set up the texture if it changed // Set up the texture if it changed
if (lastTexParams.value != thePoly.texParam.value || lastTexPalette != thePoly.texPalette) if (lastTexParams.value != rawPoly.texParam.value || lastTexPalette != rawPoly.texPalette)
{ {
lastTexParams = thePoly.texParam; lastTexParams = rawPoly.texParam;
lastTexPalette = thePoly.texPalette; lastTexPalette = rawPoly.texPalette;
this->SetupTexture(thePoly, i); this->SetupTexture(rawPoly, i);
} }
// Set up the viewport if it changed // Set up the viewport if it changed
if (lastViewport.value != thePoly.viewport.value) if (lastViewport.value != rawPoly.viewport.value)
{ {
lastViewport = thePoly.viewport; lastViewport = rawPoly.viewport;
this->SetupViewport(thePoly.viewport); this->SetupViewport(rawPoly.viewport);
} }
// In wireframe mode, redefine all primitives as GL_LINE_LOOP rather than // In wireframe mode, redefine all primitives as GL_LINE_LOOP rather than
@ -1817,7 +1817,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
// drawing more accurate this way, but it also allows GFX3D_QUADS and // drawing more accurate this way, but it also allows GFX3D_QUADS and
// GFX3D_QUAD_STRIP primitives to properly draw as wireframe without the // GFX3D_QUAD_STRIP primitives to properly draw as wireframe without the
// extra diagonal line. // extra diagonal line.
const size_t LUTIndex = (!GFX3D_IsPolyWireframe(thePoly)) ? thePoly.vtxFormat : (0x08 | thePoly.vtxFormat); const size_t LUTIndex = (!GFX3D_IsPolyWireframe(rawPoly)) ? rawPoly.vtxFormat : (0x08 | rawPoly.vtxFormat);
const GLenum polyPrimitive = oglPrimitiveType[LUTIndex]; const GLenum polyPrimitive = oglPrimitiveType[LUTIndex];
// Increment the vertex count // Increment the vertex count
@ -1828,7 +1828,7 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
// the same and we're not drawing a line loop or line strip. // the same and we're not drawing a line loop or line strip.
if (i+1 <= lastIndex) if (i+1 <= lastIndex)
{ {
const POLY &nextPoly = *clippedPolyList[i+1].poly; const POLY &nextPoly = rawPolyList[clippedPolyList[i+1].index];
if (lastPolyAttr.value == nextPoly.attribute.value && if (lastPolyAttr.value == nextPoly.attribute.value &&
lastTexParams.value == nextPoly.texParam.value && lastTexParams.value == nextPoly.texParam.value &&
@ -1848,33 +1848,38 @@ size_t OpenGLRenderer::DrawPolygonsForIndexRange(const CPoly *clippedPolyList, c
// Render the polygons // Render the polygons
this->SetPolygonIndex(i); this->SetPolygonIndex(i);
if (thePoly.attribute.Mode == POLYGON_MODE_SHADOW) if (rawPoly.attribute.Mode == POLYGON_MODE_SHADOW)
{ {
if ((DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass) && this->_emulateShadowPolygon) if ((DRAWMODE != OGLPolyDrawMode_ZeroAlphaPass) && this->_emulateShadowPolygon)
{ {
this->DrawShadowPolygon(polyPrimitive, vertIndexCount, indexBufferPtr, thePoly.attribute.DepthEqualTest_Enable, thePoly.attribute.TranslucentDepthWrite_Enable, (DRAWMODE == OGLPolyDrawMode_DrawTranslucentPolys), thePoly.attribute.PolygonID); this->DrawShadowPolygon(polyPrimitive,
vertIndexCount,
indexBufferPtr,
rawPoly.attribute.DepthEqualTest_Enable,
rawPoly.attribute.TranslucentDepthWrite_Enable,
(DRAWMODE == OGLPolyDrawMode_DrawTranslucentPolys), rawPoly.attribute.PolygonID);
} }
} }
else if ( (thePoly.texParam.PackedFormat == TEXMODE_A3I5) || (thePoly.texParam.PackedFormat == TEXMODE_A5I3) ) else if ( (rawPoly.texParam.PackedFormat == TEXMODE_A3I5) || (rawPoly.texParam.PackedFormat == TEXMODE_A5I3) )
{ {
this->DrawAlphaTexturePolygon<DRAWMODE>(polyPrimitive, this->DrawAlphaTexturePolygon<DRAWMODE>(polyPrimitive,
vertIndexCount, vertIndexCount,
indexBufferPtr, indexBufferPtr,
thePoly.attribute.DepthEqualTest_Enable, rawPoly.attribute.DepthEqualTest_Enable,
thePoly.attribute.TranslucentDepthWrite_Enable, rawPoly.attribute.TranslucentDepthWrite_Enable,
GFX3D_IsPolyWireframe(thePoly) || GFX3D_IsPolyOpaque(thePoly), GFX3D_IsPolyWireframe(rawPoly) || GFX3D_IsPolyOpaque(rawPoly),
thePoly.attribute.PolygonID, rawPoly.attribute.PolygonID,
this->_isPolyFrontFacing[i]); this->_isPolyFrontFacing[i]);
} }
else else
{ {
this->DrawOtherPolygon<DRAWMODE>(polyPrimitive, this->DrawOtherPolygon<DRAWMODE>(polyPrimitive,
vertIndexCount, vertIndexCount,
indexBufferPtr, indexBufferPtr,
thePoly.attribute.DepthEqualTest_Enable, rawPoly.attribute.DepthEqualTest_Enable,
thePoly.attribute.TranslucentDepthWrite_Enable, rawPoly.attribute.TranslucentDepthWrite_Enable,
thePoly.attribute.PolygonID, rawPoly.attribute.PolygonID,
this->_isPolyFrontFacing[i]); this->_isPolyFrontFacing[i]);
} }
indexBufferPtr += vertIndexCount; indexBufferPtr += vertIndexCount;
@ -3874,7 +3879,7 @@ Render3DError OpenGLRenderer_1_2::DisableVertexAttributes()
return OGLERROR_NOERR; return OGLERROR_NOERR;
} }
Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr) Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{ {
OGLRenderRef &OGLRef = *this->ref; OGLRenderRef &OGLRef = *this->ref;
@ -3957,7 +3962,7 @@ Render3DError OpenGLRenderer_1_2::ZeroDstAlphaPass(const CPoly *clippedPolyList,
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr); this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(rawPolyList, clippedPolyList, clippedPolyCount, clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
// Restore OpenGL states back to normal. // Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags; this->_geometryProgramFlags = oldGProgramFlags;
@ -4169,6 +4174,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
this->_clippedPolyCount = renderGList.clippedPolyCount; this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount; this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList; this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList;
this->_rawPolyList = (POLY *)renderGList.rawPolyList;
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false; this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
@ -4178,14 +4184,14 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID); glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, OGLRef.iboGeometryIndexID);
// Only copy as much vertex data as we need to, since this can be a potentially large upload size. // Only copy as much vertex data as we need to, since this can be a potentially large upload size.
glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * renderGList.vertListCount, renderGList.vertList); glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(VERT) * renderGList.rawVertCount, renderGList.rawVertList);
} }
else else
{ {
// If VBOs aren't supported, we need to use the client-side buffers here. // If VBOs aren't supported, we need to use the client-side buffers here.
OGLRef.vtxPtrPosition = (GLvoid *)&renderGList.vertList[0].coord; OGLRef.vtxPtrPosition = (GLvoid *)&renderGList.rawVertList[0].coord;
OGLRef.vtxPtrTexCoord = (GLvoid *)&renderGList.vertList[0].texcoord; OGLRef.vtxPtrTexCoord = (GLvoid *)&renderGList.rawVertList[0].texcoord;
OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)&renderGList.vertList[0].color : OGLRef.color4fBuffer; OGLRef.vtxPtrColor = (this->isShaderSupported) ? (GLvoid *)&renderGList.rawVertList[0].color : OGLRef.color4fBuffer;
} }
// Generate the clipped polygon list. // Generate the clipped polygon list.
@ -4193,28 +4199,28 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++) for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
{ {
const POLY &thePoly = *this->_clippedPolyList[i].poly; const POLY &rawPoly = this->_rawPolyList[this->_clippedPolyList[i].index];
const size_t polyType = thePoly.type; const size_t polyType = rawPoly.type;
const VERT vert[4] = { const VERT vert[4] = {
renderGList.vertList[thePoly.vertIndexes[0]], renderGList.rawVertList[rawPoly.vertIndexes[0]],
renderGList.vertList[thePoly.vertIndexes[1]], renderGList.rawVertList[rawPoly.vertIndexes[1]],
renderGList.vertList[thePoly.vertIndexes[2]], renderGList.rawVertList[rawPoly.vertIndexes[2]],
renderGList.vertList[thePoly.vertIndexes[3]] renderGList.rawVertList[rawPoly.vertIndexes[3]]
}; };
if (this->isShaderSupported) if (this->isShaderSupported)
{ {
for (size_t j = 0; j < polyType; j++) for (size_t j = 0; j < polyType; j++)
{ {
const GLushort vertIndex = thePoly.vertIndexes[j]; const GLushort vertIndex = rawPoly.vertIndexes[j];
// While we're looping through our vertices, add each vertex index to // While we're looping through our vertices, add each vertex index to
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
// vertices here to convert them to GL_TRIANGLES, which are much easier // vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions. // to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex; OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
{ {
if (j == 2) if (j == 2)
{ {
@ -4222,23 +4228,23 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
} }
else if (j == 3) else if (j == 3)
{ {
OGLRef.vertIndexBuffer[vertIndexCount++] = thePoly.vertIndexes[0]; OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
} }
} }
} }
} }
else else
{ {
const GLfloat thePolyAlpha = (GFX3D_IsPolyWireframe(thePoly)) ? 1.0f : divide5bitBy31_LUT[thePoly.attribute.Alpha]; const GLfloat thePolyAlpha = (GFX3D_IsPolyWireframe(rawPoly)) ? 1.0f : divide5bitBy31_LUT[rawPoly.attribute.Alpha];
for (size_t j = 0; j < polyType; j++) for (size_t j = 0; j < polyType; j++)
{ {
const GLushort vertIndex = thePoly.vertIndexes[j]; const GLushort vertIndex = rawPoly.vertIndexes[j];
const size_t colorIndex = vertIndex * 4; const size_t colorIndex = vertIndex * 4;
// Consolidate the vertex color and the poly alpha to our internal color buffer // Consolidate the vertex color and the poly alpha to our internal color buffer
// so that OpenGL can use it. // so that OpenGL can use it.
const VERT *vertForAlpha = &renderGList.vertList[vertIndex]; const VERT *vertForAlpha = &renderGList.rawVertList[vertIndex];
OGLRef.color4fBuffer[colorIndex+0] = divide6bitBy63_LUT[vertForAlpha->color[0]]; OGLRef.color4fBuffer[colorIndex+0] = divide6bitBy63_LUT[vertForAlpha->color[0]];
OGLRef.color4fBuffer[colorIndex+1] = divide6bitBy63_LUT[vertForAlpha->color[1]]; OGLRef.color4fBuffer[colorIndex+1] = divide6bitBy63_LUT[vertForAlpha->color[1]];
OGLRef.color4fBuffer[colorIndex+2] = divide6bitBy63_LUT[vertForAlpha->color[2]]; OGLRef.color4fBuffer[colorIndex+2] = divide6bitBy63_LUT[vertForAlpha->color[2]];
@ -4249,7 +4255,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
// vertices here to convert them to GL_TRIANGLES, which are much easier // vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions. // to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex; OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
{ {
if (j == 2) if (j == 2)
{ {
@ -4257,7 +4263,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
} }
else if (j == 3) else if (j == 3)
{ {
OGLRef.vertIndexBuffer[vertIndexCount++] = thePoly.vertIndexes[0]; OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
} }
} }
} }
@ -4274,11 +4280,11 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State &renderState, co
facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x); facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x);
} }
renderNeedsToonTable = (renderNeedsToonTable || (thePoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT)) && this->isShaderSupported; renderNeedsToonTable = (renderNeedsToonTable || (rawPoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT)) && this->isShaderSupported;
this->_isPolyFrontFacing[i] = (facing < 0); this->_isPolyFrontFacing[i] = (facing < 0);
// Get the texture that is to be attached to this polygon. // Get the texture that is to be attached to this polygon.
this->_textureList[i] = this->GetLoadedTextureFromPolygon(thePoly, this->_enableTextureSampling); this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
} }
if (this->isVBOSupported) if (this->isVBOSupported)
@ -4406,13 +4412,14 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
size_t indexOffset = 0; size_t indexOffset = 0;
const POLY &firstPoly = *this->_clippedPolyList[0].poly; const POLY *rawPolyList = this->_rawPolyList;
const POLY &firstPoly = rawPolyList[this->_clippedPolyList[0].index];
POLYGON_ATTR lastPolyAttr = firstPoly.attribute; POLYGON_ATTR lastPolyAttr = firstPoly.attribute;
if (this->_clippedPolyOpaqueCount > 0) if (this->_clippedPolyOpaqueCount > 0)
{ {
this->SetupPolygon(firstPoly, false, true); this->SetupPolygon(firstPoly, false, true);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(this->_clippedPolyList, this->_clippedPolyCount, 0, this->_clippedPolyOpaqueCount - 1, indexOffset, lastPolyAttr); this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, 0, this->_clippedPolyOpaqueCount - 1, indexOffset, lastPolyAttr);
} }
if (this->_clippedPolyOpaqueCount < this->_clippedPolyCount) if (this->_clippedPolyOpaqueCount < this->_clippedPolyCount)
@ -4426,11 +4433,11 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
this->SetupPolygon(firstPoly, true, false); this->SetupPolygon(firstPoly, true, false);
} }
this->ZeroDstAlphaPass(this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_enableAlphaBlending, indexOffset, lastPolyAttr); this->ZeroDstAlphaPass(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_enableAlphaBlending, indexOffset, lastPolyAttr);
if (this->_clippedPolyOpaqueCount > 0) if (this->_clippedPolyOpaqueCount > 0)
{ {
const POLY &lastOpaquePoly = *this->_clippedPolyList[this->_clippedPolyOpaqueCount - 1].poly; const POLY &lastOpaquePoly = rawPolyList[this->_clippedPolyList[this->_clippedPolyOpaqueCount - 1].index];
lastPolyAttr = lastOpaquePoly.attribute; lastPolyAttr = lastOpaquePoly.attribute;
this->SetupPolygon(lastOpaquePoly, false, true); this->SetupPolygon(lastOpaquePoly, false, true);
} }
@ -4456,7 +4463,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry()
this->_ResolveWorkingBackFacing(); this->_ResolveWorkingBackFacing();
} }
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr); this->DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(rawPolyList, this->_clippedPolyList, this->_clippedPolyCount, this->_clippedPolyOpaqueCount, this->_clippedPolyCount - 1, indexOffset, lastPolyAttr);
} }
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
@ -5450,6 +5457,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co
this->_clippedPolyCount = renderGList.clippedPolyCount; this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount; this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList; this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList;
this->_rawPolyList = (POLY *)renderGList.rawPolyList;
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false; this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
@ -5457,33 +5465,33 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, OGLRef.iboGeometryIndexID);
// Only copy as much vertex data as we need to, since this can be a potentially large upload size. // Only copy as much vertex data as we need to, since this can be a potentially large upload size.
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * renderGList.vertListCount, renderGList.vertList); glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(VERT) * renderGList.rawVertCount, renderGList.rawVertList);
// Generate the clipped polygon list. // Generate the clipped polygon list.
bool renderNeedsToonTable = false; bool renderNeedsToonTable = false;
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++) for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
{ {
const POLY &thePoly = *this->_clippedPolyList[i].poly; const POLY &rawPoly = this->_rawPolyList[this->_clippedPolyList[i].index];
const size_t polyType = thePoly.type; const size_t polyType = rawPoly.type;
const VERT vert[4] = { const VERT vert[4] = {
renderGList.vertList[thePoly.vertIndexes[0]], renderGList.rawVertList[rawPoly.vertIndexes[0]],
renderGList.vertList[thePoly.vertIndexes[1]], renderGList.rawVertList[rawPoly.vertIndexes[1]],
renderGList.vertList[thePoly.vertIndexes[2]], renderGList.rawVertList[rawPoly.vertIndexes[2]],
renderGList.vertList[thePoly.vertIndexes[3]] renderGList.rawVertList[rawPoly.vertIndexes[3]]
}; };
for (size_t j = 0; j < polyType; j++) for (size_t j = 0; j < polyType; j++)
{ {
const GLushort vertIndex = thePoly.vertIndexes[j]; const GLushort vertIndex = rawPoly.vertIndexes[j];
// While we're looping through our vertices, add each vertex index to // While we're looping through our vertices, add each vertex index to
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
// vertices here to convert them to GL_TRIANGLES, which are much easier // vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions. // to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex; OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
{ {
if (j == 2) if (j == 2)
{ {
@ -5491,7 +5499,7 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co
} }
else if (j == 3) else if (j == 3)
{ {
OGLRef.vertIndexBuffer[vertIndexCount++] = thePoly.vertIndexes[0]; OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
} }
} }
} }
@ -5507,11 +5515,11 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State &renderState, co
facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x); facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x);
} }
renderNeedsToonTable = renderNeedsToonTable || (thePoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT); renderNeedsToonTable = renderNeedsToonTable || (rawPoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT);
this->_isPolyFrontFacing[i] = (facing < 0); this->_isPolyFrontFacing[i] = (facing < 0);
// Get the texture that is to be attached to this polygon. // Get the texture that is to be attached to this polygon.
this->_textureList[i] = this->GetLoadedTextureFromPolygon(thePoly, this->_enableTextureSampling); this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
} }
// Replace the entire index buffer as a hint to the driver that we can orphan the index buffer and // Replace the entire index buffer as a hint to the driver that we can orphan the index buffer and
@ -5677,6 +5685,6 @@ Render3DError OpenGLRenderer_2_1::RenderFlush(bool willFlushBuffer32, bool willF
return RENDER3DERROR_NOERR; return RENDER3DERROR_NOERR;
} }
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawOpaquePolys>(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_DrawTranslucentPolys>(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); template size_t OpenGLRenderer::DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);

View File

@ -742,7 +742,7 @@ protected:
Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16); Render3DError FlushFramebuffer(const FragmentColor *__restrict srcFramebuffer, FragmentColor *__restrict dstFramebufferMain, u16 *__restrict dstFramebuffer16);
OpenGLTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing); OpenGLTexture* GetLoadedTextureFromPolygon(const POLY &thePoly, bool enableTexturing);
template<OGLPolyDrawMode DRAWMODE> size_t DrawPolygonsForIndexRange(const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr); template<OGLPolyDrawMode DRAWMODE> size_t DrawPolygonsForIndexRange(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, size_t firstIndex, size_t lastIndex, size_t &indexOffset, POLYGON_ATTR &lastPolyAttr);
template<OGLPolyDrawMode DRAWMODE> Render3DError DrawAlphaTexturePolygon(const GLenum polyPrimitive, template<OGLPolyDrawMode DRAWMODE> Render3DError DrawAlphaTexturePolygon(const GLenum polyPrimitive,
const GLsizei vertIndexCount, const GLsizei vertIndexCount,
const GLushort *indexBufferPtr, const GLushort *indexBufferPtr,
@ -874,7 +874,7 @@ protected:
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags); virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes(); virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes(); virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing(); virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry(); virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels(); virtual Render3DError ReadBackPixels();

View File

@ -1758,7 +1758,7 @@ Render3DError OpenGLRenderer_3_2::DisableVertexAttributes()
return OGLERROR_NOERR; return OGLERROR_NOERR;
} }
Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr) Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr)
{ {
OGLRenderRef &OGLRef = *this->ref; OGLRenderRef &OGLRef = *this->ref;
@ -1816,7 +1816,7 @@ Render3DError OpenGLRenderer_3_2::ZeroDstAlphaPass(const CPoly *clippedPolyList,
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
glStencilFunc(GL_NOTEQUAL, 0x40, 0x40); glStencilFunc(GL_NOTEQUAL, 0x40, 0x40);
this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(clippedPolyList, clippedPolyCount, clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr); this->DrawPolygonsForIndexRange<OGLPolyDrawMode_ZeroAlphaPass>(rawPolyList, clippedPolyList, clippedPolyCount, clippedPolyOpaqueCount, clippedPolyCount - 1, indexOffset, lastPolyAttr);
// Restore OpenGL states back to normal. // Restore OpenGL states back to normal.
this->_geometryProgramFlags = oldGProgramFlags; this->_geometryProgramFlags = oldGProgramFlags;
@ -1985,6 +1985,7 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
this->_clippedPolyCount = renderGList.clippedPolyCount; this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount; this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList; this->_clippedPolyList = (CPoly *)renderGList.clippedPolyList;
this->_rawPolyList = (POLY *)renderGList.rawPolyList;
this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false; this->_enableAlphaBlending = (renderState.DISP3DCNT.EnableAlphaBlending) ? true : false;
@ -1999,9 +2000,9 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
glDeleteSync(this->_syncBufferSetup); glDeleteSync(this->_syncBufferSetup);
} }
const size_t vtxBufferSize = sizeof(VERT) * renderGList.vertListCount; const size_t vtxBufferSize = sizeof(VERT) * renderGList.rawVertCount;
VERT *vtxPtr = (VERT *)glMapBufferRange(GL_ARRAY_BUFFER, 0, vtxBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT); VERT *vtxPtr = (VERT *)glMapBufferRange(GL_ARRAY_BUFFER, 0, vtxBufferSize, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
memcpy(vtxPtr, renderGList.vertList, vtxBufferSize); memcpy(vtxPtr, renderGList.rawVertList, vtxBufferSize);
glUnmapBuffer(GL_ARRAY_BUFFER); glUnmapBuffer(GL_ARRAY_BUFFER);
this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); this->_syncBufferSetup = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
@ -2021,26 +2022,26 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++) for (size_t i = 0, vertIndexCount = 0; i < this->_clippedPolyCount; i++)
{ {
const POLY &thePoly = *this->_clippedPolyList[i].poly; const POLY &rawPoly = this->_rawPolyList[this->_clippedPolyList[i].index];
const size_t polyType = thePoly.type; const size_t polyType = rawPoly.type;
const VERT vert[4] = { const VERT vert[4] = {
renderGList.vertList[thePoly.vertIndexes[0]], renderGList.rawVertList[rawPoly.vertIndexes[0]],
renderGList.vertList[thePoly.vertIndexes[1]], renderGList.rawVertList[rawPoly.vertIndexes[1]],
renderGList.vertList[thePoly.vertIndexes[2]], renderGList.rawVertList[rawPoly.vertIndexes[2]],
renderGList.vertList[thePoly.vertIndexes[3]] renderGList.rawVertList[rawPoly.vertIndexes[3]]
}; };
for (size_t j = 0; j < polyType; j++) for (size_t j = 0; j < polyType; j++)
{ {
const GLushort vertIndex = thePoly.vertIndexes[j]; const GLushort vertIndex = rawPoly.vertIndexes[j];
// While we're looping through our vertices, add each vertex index to // While we're looping through our vertices, add each vertex index to
// a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional // a buffer. For GFX3D_QUADS and GFX3D_QUAD_STRIP, we also add additional
// vertices here to convert them to GL_TRIANGLES, which are much easier // vertices here to convert them to GL_TRIANGLES, which are much easier
// to work with and won't be deprecated in future OpenGL versions. // to work with and won't be deprecated in future OpenGL versions.
OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex; OGLRef.vertIndexBuffer[vertIndexCount++] = vertIndex;
if (!GFX3D_IsPolyWireframe(thePoly) && (thePoly.vtxFormat == GFX3D_QUADS || thePoly.vtxFormat == GFX3D_QUAD_STRIP)) if (!GFX3D_IsPolyWireframe(rawPoly) && (rawPoly.vtxFormat == GFX3D_QUADS || rawPoly.vtxFormat == GFX3D_QUAD_STRIP))
{ {
if (j == 2) if (j == 2)
{ {
@ -2048,7 +2049,7 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
} }
else if (j == 3) else if (j == 3)
{ {
OGLRef.vertIndexBuffer[vertIndexCount++] = thePoly.vertIndexes[0]; OGLRef.vertIndexBuffer[vertIndexCount++] = rawPoly.vertIndexes[0];
} }
} }
} }
@ -2064,11 +2065,11 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x); facing += (vert[j+1].y + vert[j].y) * (vert[j+1].x - vert[j].x);
} }
renderNeedsToonTable = renderNeedsToonTable || (thePoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT); renderNeedsToonTable = renderNeedsToonTable || (rawPoly.attribute.Mode == POLYGON_MODE_TOONHIGHLIGHT);
this->_isPolyFrontFacing[i] = (facing < 0); this->_isPolyFrontFacing[i] = (facing < 0);
// Get the texture that is to be attached to this polygon. // Get the texture that is to be attached to this polygon.
this->_textureList[i] = this->GetLoadedTextureFromPolygon(thePoly, this->_enableTextureSampling); this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
} }
// Replace the entire buffer as a hint to the driver to orphan the buffer and avoid a synchronization cost. // Replace the entire buffer as a hint to the driver to orphan the buffer and avoid a synchronization cost.
@ -2143,24 +2144,24 @@ Render3DError OpenGLRenderer_3_2::BeginRender(const GFX3D_State &renderState, co
for (size_t i = 0; i < this->_clippedPolyCount; i++) for (size_t i = 0; i < this->_clippedPolyCount; i++)
{ {
const POLY &thePoly = *this->_clippedPolyList[i].poly; const POLY &rawPoly = this->_rawPolyList[this->_clippedPolyList[i].index];
// Get all of the polygon states that can be handled within the shader. // Get all of the polygon states that can be handled within the shader.
const NDSTextureFormat packFormat = this->_textureList[i]->GetPackFormat(); const NDSTextureFormat packFormat = this->_textureList[i]->GetPackFormat();
polyStates[i].packedState = 0; polyStates[i].packedState = 0;
polyStates[i].PolygonID = thePoly.attribute.PolygonID; polyStates[i].PolygonID = rawPoly.attribute.PolygonID;
polyStates[i].PolygonMode = thePoly.attribute.Mode; polyStates[i].PolygonMode = rawPoly.attribute.Mode;
polyStates[i].PolygonAlpha = (GFX3D_IsPolyWireframe(thePoly)) ? 0x1F : thePoly.attribute.Alpha; polyStates[i].PolygonAlpha = (GFX3D_IsPolyWireframe(rawPoly)) ? 0x1F : rawPoly.attribute.Alpha;
polyStates[i].IsWireframe = (GFX3D_IsPolyWireframe(thePoly)) ? 1 : 0; polyStates[i].IsWireframe = (GFX3D_IsPolyWireframe(rawPoly)) ? 1 : 0;
polyStates[i].EnableFog = (thePoly.attribute.Fog_Enable) ? 1 : 0; polyStates[i].EnableFog = (rawPoly.attribute.Fog_Enable) ? 1 : 0;
polyStates[i].SetNewDepthForTranslucent = (thePoly.attribute.TranslucentDepthWrite_Enable) ? 1 : 0; polyStates[i].SetNewDepthForTranslucent = (rawPoly.attribute.TranslucentDepthWrite_Enable) ? 1 : 0;
polyStates[i].EnableTexture = (this->_textureList[i]->IsSamplingEnabled()) ? 1 : 0; polyStates[i].EnableTexture = (this->_textureList[i]->IsSamplingEnabled()) ? 1 : 0;
polyStates[i].TexSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? 1 : 0; polyStates[i].TexSingleBitAlpha = (packFormat != TEXMODE_A3I5 && packFormat != TEXMODE_A5I3) ? 1 : 0;
polyStates[i].TexSizeShiftS = thePoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S polyStates[i].TexSizeShiftS = rawPoly.texParam.SizeShiftS; // Note that we are using the preshifted size of S
polyStates[i].TexSizeShiftT = thePoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T polyStates[i].TexSizeShiftT = rawPoly.texParam.SizeShiftT; // Note that we are using the preshifted size of T
} }
if (OGLRef.uboPolyStatesID != 0) if (OGLRef.uboPolyStatesID != 0)

View File

@ -98,7 +98,7 @@ protected:
virtual void _SetupGeometryShaders(const OGLGeometryFlags flags); virtual void _SetupGeometryShaders(const OGLGeometryFlags flags);
virtual Render3DError EnableVertexAttributes(); virtual Render3DError EnableVertexAttributes();
virtual Render3DError DisableVertexAttributes(); virtual Render3DError DisableVertexAttributes();
virtual Render3DError ZeroDstAlphaPass(const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr); virtual Render3DError ZeroDstAlphaPass(const POLY *rawPolyList, const CPoly *clippedPolyList, const size_t clippedPolyCount, const size_t clippedPolyOpaqueCount, bool enableAlphaBlending, size_t indexOffset, POLYGON_ATTR lastPolyAttr);
virtual void _ResolveWorkingBackFacing(); virtual void _ResolveWorkingBackFacing();
virtual void _ResolveGeometry(); virtual void _ResolveGeometry();
virtual Render3DError ReadBackPixels(); virtual Render3DError ReadBackPixels();

View File

@ -262,7 +262,6 @@ using std::min;
GFX3D gfx3d; GFX3D gfx3d;
static GFX3D_IOREG *_GFX3D_IORegisterMap = NULL; static GFX3D_IOREG *_GFX3D_IORegisterMap = NULL;
Viewer3D_State viewer3D; Viewer3D_State viewer3D;
static GFX3D_Clipper boxtestClipper;
static LegacyGFX3DStateSFormat legacyGFX3DStateSFormatPending; static LegacyGFX3DStateSFormat legacyGFX3DStateSFormatPending;
static LegacyGFX3DStateSFormat legacyGFX3DStateSFormatApplied; static LegacyGFX3DStateSFormat legacyGFX3DStateSFormatApplied;
@ -351,8 +350,6 @@ static CACHE_ALIGN s32 cacheHalfVector[4][4];
//-------------working polygon lists //-------------working polygon lists
static GFX3D_Clipper *_clipper = NULL;
static PAGE_ALIGN CPoly _clippedPolyWorkingList[POLYLIST_SIZE * 2];
static PAGE_ALIGN CPoly _clippedPolyUnsortedList[POLYLIST_SIZE]; static PAGE_ALIGN CPoly _clippedPolyUnsortedList[POLYLIST_SIZE];
static int polygonListCompleted = 0; static int polygonListCompleted = 0;
@ -483,9 +480,6 @@ void gfx3d_init()
{ {
_GFX3D_IORegisterMap = (GFX3D_IOREG *)(&MMU.ARM9_REG[0x0320]); _GFX3D_IORegisterMap = (GFX3D_IOREG *)(&MMU.ARM9_REG[0x0320]);
_clipper = new GFX3D_Clipper;
_clipper->SetClippedPolyBufferPtr(_clippedPolyWorkingList);
polyAttrInProcess.value = 0; polyAttrInProcess.value = 0;
currentPolyAttr.value = 0; currentPolyAttr.value = 0;
currentPolyTexParam.value = 0; currentPolyTexParam.value = 0;
@ -515,7 +509,6 @@ void gfx3d_init()
void gfx3d_deinit() void gfx3d_deinit()
{ {
Render3D_DeInit(); Render3D_DeInit();
delete _clipper;
} }
void gfx3d_reset() void gfx3d_reset()
@ -669,7 +662,7 @@ static void GEM_TransformVertex(const s32 (&__restrict mtx)[16], s32 (&__restric
//--------------- //---------------
#define SUBMITVERTEX(ii, nn) pendingGList.polyList[pendingGList.polyCount].vertIndexes[ii] = tempVertInfo.map[nn]; #define SUBMITVERTEX(ii, nn) pendingGList.rawPolyList[pendingGList.rawPolyCount].vertIndexes[ii] = tempVertInfo.map[nn];
//Submit a vertex to the GE //Submit a vertex to the GE
static void SetVertex() static void SetVertex()
{ {
@ -693,12 +686,12 @@ static void SetVertex()
//refuse to do anything if we have too many verts or polys //refuse to do anything if we have too many verts or polys
polygonListCompleted = 0; polygonListCompleted = 0;
if (pendingGList.vertListCount >= VERTLIST_SIZE) if (pendingGList.rawVertCount >= VERTLIST_SIZE)
{ {
return; return;
} }
if (pendingGList.polyCount >= POLYLIST_SIZE) if (pendingGList.rawPolyCount >= POLYLIST_SIZE)
{ {
return; return;
} }
@ -735,13 +728,13 @@ static void SetVertex()
continuation = 2; continuation = 2;
//record the vertex //record the vertex
const size_t vertIndex = pendingGList.vertListCount + tempVertInfo.count - continuation; const size_t vertIndex = pendingGList.rawVertCount + tempVertInfo.count - continuation;
if (vertIndex >= VERTLIST_SIZE) if (vertIndex >= VERTLIST_SIZE)
{ {
printf("wtf\n"); printf("wtf\n");
} }
VERT &vert = pendingGList.vertList[vertIndex]; VERT &vert = pendingGList.rawVertList[vertIndex];
//printf("%f %f %f\n",coordTransformed[0],coordTransformed[1],coordTransformed[2]); //printf("%f %f %f\n",coordTransformed[0],coordTransformed[1],coordTransformed[2]);
//if(coordTransformed[1] > 20) //if(coordTransformed[1] > 20)
@ -768,7 +761,7 @@ static void SetVertex()
vert.gf = (float)vert.g; vert.gf = (float)vert.g;
vert.bf = (float)vert.b; vert.bf = (float)vert.b;
vert.af = (float)vert.a; vert.af = (float)vert.a;
tempVertInfo.map[tempVertInfo.count] = (s32)pendingGList.vertListCount + tempVertInfo.count - continuation; tempVertInfo.map[tempVertInfo.count] = (s32)pendingGList.rawVertCount + tempVertInfo.count - continuation;
tempVertInfo.count++; tempVertInfo.count++;
//possibly complete a polygon //possibly complete a polygon
@ -783,8 +776,8 @@ static void SetVertex()
SUBMITVERTEX(0,0); SUBMITVERTEX(0,0);
SUBMITVERTEX(1,1); SUBMITVERTEX(1,1);
SUBMITVERTEX(2,2); SUBMITVERTEX(2,2);
gfx3d.gList[gfx3d.pendingListIndex].vertListCount += 3; gfx3d.gList[gfx3d.pendingListIndex].rawVertCount += 3;
pendingGList.polyList[pendingGList.polyCount].type = POLYGON_TYPE_TRIANGLE; pendingGList.rawPolyList[pendingGList.rawPolyCount].type = POLYGON_TYPE_TRIANGLE;
tempVertInfo.count = 0; tempVertInfo.count = 0;
break; break;
@ -796,8 +789,8 @@ static void SetVertex()
SUBMITVERTEX(1,1); SUBMITVERTEX(1,1);
SUBMITVERTEX(2,2); SUBMITVERTEX(2,2);
SUBMITVERTEX(3,3); SUBMITVERTEX(3,3);
gfx3d.gList[gfx3d.pendingListIndex].vertListCount += 4; gfx3d.gList[gfx3d.pendingListIndex].rawVertCount += 4;
pendingGList.polyList[pendingGList.polyCount].type = POLYGON_TYPE_QUAD; pendingGList.rawPolyList[pendingGList.rawPolyCount].type = POLYGON_TYPE_QUAD;
tempVertInfo.count = 0; tempVertInfo.count = 0;
break; break;
@ -808,17 +801,17 @@ static void SetVertex()
SUBMITVERTEX(0,0); SUBMITVERTEX(0,0);
SUBMITVERTEX(1,1); SUBMITVERTEX(1,1);
SUBMITVERTEX(2,2); SUBMITVERTEX(2,2);
pendingGList.polyList[pendingGList.polyCount].type = POLYGON_TYPE_TRIANGLE; pendingGList.rawPolyList[pendingGList.rawPolyCount].type = POLYGON_TYPE_TRIANGLE;
if(triStripToggle) if(triStripToggle)
tempVertInfo.map[1] = (s32)pendingGList.vertListCount + 2 - continuation; tempVertInfo.map[1] = (s32)pendingGList.rawVertCount + 2 - continuation;
else else
tempVertInfo.map[0] = (s32)pendingGList.vertListCount + 2 - continuation; tempVertInfo.map[0] = (s32)pendingGList.rawVertCount + 2 - continuation;
if(tempVertInfo.first) if(tempVertInfo.first)
pendingGList.vertListCount += 3; pendingGList.rawVertCount += 3;
else else
pendingGList.vertListCount += 1; pendingGList.rawVertCount += 1;
triStripToggle ^= 1; triStripToggle ^= 1;
tempVertInfo.first = false; tempVertInfo.first = false;
@ -833,12 +826,12 @@ static void SetVertex()
SUBMITVERTEX(1,1); SUBMITVERTEX(1,1);
SUBMITVERTEX(2,3); SUBMITVERTEX(2,3);
SUBMITVERTEX(3,2); SUBMITVERTEX(3,2);
pendingGList.polyList[pendingGList.polyCount].type = POLYGON_TYPE_QUAD; pendingGList.rawPolyList[pendingGList.rawPolyCount].type = POLYGON_TYPE_QUAD;
tempVertInfo.map[0] = (s32)pendingGList.vertListCount + 2 - continuation; tempVertInfo.map[0] = (s32)pendingGList.rawVertCount + 2 - continuation;
tempVertInfo.map[1] = (s32)pendingGList.vertListCount + 3 - continuation; tempVertInfo.map[1] = (s32)pendingGList.rawVertCount + 3 - continuation;
if(tempVertInfo.first) if(tempVertInfo.first)
pendingGList.vertListCount += 4; pendingGList.rawVertCount += 4;
else pendingGList.vertListCount += 2; else pendingGList.rawVertCount += 2;
tempVertInfo.first = false; tempVertInfo.first = false;
tempVertInfo.count = 2; tempVertInfo.count = 2;
break; break;
@ -849,7 +842,7 @@ static void SetVertex()
if (polygonListCompleted == 1) if (polygonListCompleted == 1)
{ {
POLY &poly = pendingGList.polyList[pendingGList.polyCount]; POLY &poly = pendingGList.rawPolyList[pendingGList.rawPolyCount];
poly.vtxFormat = vtxFormat; poly.vtxFormat = vtxFormat;
@ -858,9 +851,9 @@ static void SetVertex()
if (currentPolyTexParam.PackedFormat == TEXMODE_NONE) if (currentPolyTexParam.PackedFormat == TEXMODE_NONE)
{ {
bool duplicated = false; bool duplicated = false;
const VERT &vert0 = pendingGList.vertList[poly.vertIndexes[0]]; const VERT &vert0 = pendingGList.rawVertList[poly.vertIndexes[0]];
const VERT &vert1 = pendingGList.vertList[poly.vertIndexes[1]]; const VERT &vert1 = pendingGList.rawVertList[poly.vertIndexes[1]];
const VERT &vert2 = pendingGList.vertList[poly.vertIndexes[2]]; const VERT &vert2 = pendingGList.rawVertList[poly.vertIndexes[2]];
if ( (vert0.x == vert1.x) && (vert0.y == vert1.y) ) duplicated = true; if ( (vert0.x == vert1.x) && (vert0.y == vert1.y) ) duplicated = true;
else else
if ( (vert1.x == vert2.x) && (vert1.y == vert2.y) ) duplicated = true; if ( (vert1.x == vert2.x) && (vert1.y == vert2.y) ) duplicated = true;
@ -880,7 +873,7 @@ static void SetVertex()
poly.texPalette = currentPolyTexPalette; poly.texPalette = currentPolyTexPalette;
poly.viewport = gfx3d.viewport; poly.viewport = gfx3d.viewport;
poly.viewportLegacySave = _GFX3D_IORegisterMap->VIEWPORT; poly.viewportLegacySave = _GFX3D_IORegisterMap->VIEWPORT;
pendingGList.polyCount++; pendingGList.rawPolyCount++;
} }
} }
} }
@ -1686,14 +1679,14 @@ static BOOL gfx3d_glBoxTest(u32 v)
}; };
#define SET_VERT_INDICES(p, a,b,c,d) \ #define SET_VERT_INDICES(p, a,b,c,d) \
polys[p].type = POLYGON_TYPE_QUAD; \ tempRawPoly[p].type = POLYGON_TYPE_QUAD; \
polys[p].vertIndexes[0] = a; \ tempRawPoly[p].vertIndexes[0] = a; \
polys[p].vertIndexes[1] = b; \ tempRawPoly[p].vertIndexes[1] = b; \
polys[p].vertIndexes[2] = c; \ tempRawPoly[p].vertIndexes[2] = c; \
polys[p].vertIndexes[3] = d; tempRawPoly[p].vertIndexes[3] = d;
//craft the faces of the box (clockwise) //craft the faces of the box (clockwise)
POLY polys[6]; POLY tempRawPoly[6];
SET_VERT_INDICES(0, 7,6,5,4) // near SET_VERT_INDICES(0, 7,6,5,4) // near
SET_VERT_INDICES(1, 0,1,2,3) // far SET_VERT_INDICES(1, 0,1,2,3) // far
SET_VERT_INDICES(2, 0,3,7,4) // left SET_VERT_INDICES(2, 0,3,7,4) // left
@ -1704,8 +1697,6 @@ static BOOL gfx3d_glBoxTest(u32 v)
//setup the clipper //setup the clipper
CPoly tempClippedPoly; CPoly tempClippedPoly;
boxtestClipper.SetClippedPolyBufferPtr(&tempClippedPoly);
boxtestClipper.Reset();
////----------------------------- ////-----------------------------
////awesome hack: ////awesome hack:
@ -1753,26 +1744,23 @@ static BOOL gfx3d_glBoxTest(u32 v)
//clip each poly //clip each poly
for (size_t i = 0; i < 6; i++) for (size_t i = 0; i < 6; i++)
{ {
const POLY &thePoly = polys[i]; const POLY &rawPoly = tempRawPoly[i];
const VERT *vertTable[4] = { const VERT *vertTable[4] = {
&verts[thePoly.vertIndexes[0]], &verts[rawPoly.vertIndexes[0]],
&verts[thePoly.vertIndexes[1]], &verts[rawPoly.vertIndexes[1]],
&verts[thePoly.vertIndexes[2]], &verts[rawPoly.vertIndexes[2]],
&verts[thePoly.vertIndexes[3]] &verts[rawPoly.vertIndexes[3]]
}; };
const bool isPolyUnclipped = boxtestClipper.ClipPoly<ClipperMode_DetermineClipOnly>(0, thePoly, vertTable); const PolygonType cpType = GFX3D_GenerateClippedPoly<ClipperMode_DetermineClipOnly>(0, rawPoly.type, vertTable, tempClippedPoly);
//if any portion of this poly was retained, then the test passes. //if any portion of this poly was retained, then the test passes.
if (isPolyUnclipped) if (cpType != POLYGON_TYPE_UNDEFINED)
{ {
//printf("%06d PASS %d\n",gxFIFO.size, i); //printf("%06d PASS %d\n",gxFIFO.size, i);
MMU_new.gxstat.tr = 1; MMU_new.gxstat.tr = 1;
break; break;
} }
else
{
}
//if(i==5) printf("%06d FAIL\n",gxFIFO.size); //if(i==5) printf("%06d FAIL\n",gxFIFO.size);
} }
@ -1920,13 +1908,13 @@ template void gfx3d_glClearImageOffset<u16, 0>(const u16 val);
u32 gfx3d_GetNumPolys() u32 gfx3d_GetNumPolys()
{ {
//so is this in the currently-displayed or currently-built list? //so is this in the currently-displayed or currently-built list?
return (u32)(gfx3d.gList[gfx3d.pendingListIndex].polyCount); return (u32)(gfx3d.gList[gfx3d.pendingListIndex].rawPolyCount);
} }
u32 gfx3d_GetNumVertex() u32 gfx3d_GetNumVertex()
{ {
//so is this in the currently-displayed or currently-built list? //so is this in the currently-displayed or currently-built list?
return (u32)gfx3d.gList[gfx3d.pendingListIndex].vertListCount; return (u32)gfx3d.gList[gfx3d.pendingListIndex].rawVertCount;
} }
template <typename T> template <typename T>
@ -2294,10 +2282,12 @@ void gfx3d_glFlush(u32 v)
GFX_DELAY(1); GFX_DELAY(1);
} }
static bool gfx3d_ysort_compare(int num1, int num2) static bool gfx3d_ysort_compare(const u16 idx1, const u16 idx2)
{ {
const POLY &poly1 = *_clippedPolyUnsortedList[num1].poly; const CPoly &cp1 = _clippedPolyUnsortedList[idx1];
const POLY &poly2 = *_clippedPolyUnsortedList[num2].poly; 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];
//this may be verified by checking the game create menus in harvest moon island of happiness //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 //also the buttons in the knights in the nightmare frontend depend on this and the perspective division
@ -2314,73 +2304,59 @@ static bool gfx3d_ysort_compare(int num1, int num2)
//make sure we respect the game's ordering in cases of complete ties //make sure we respect the game's ordering in cases of complete ties
//this makes it a stable sort. //this makes it a stable sort.
//this must be a stable sort or else advance wars DOR will flicker in the main map mode //this must be a stable sort or else advance wars DOR will flicker in the main map mode
return (num1 < num2); return (idx1 < idx2);
} }
template <ClipperMode CLIPPERMODE> template <ClipperMode CLIPPERMODE>
void gfx3d_PerformClipping(const GFX3D_GeometryList &gList) size_t gfx3d_PerformClipping(const GFX3D_GeometryList &gList, CPoly *outCPolyUnsortedList)
{ {
bool isPolyUnclipped = false; size_t clipCount = 0;
_clipper->Reset(); PolygonType cpType = POLYGON_TYPE_UNDEFINED;
for (size_t polyIndex = 0, clipCount = 0; polyIndex < gList.polyCount; polyIndex++) for (size_t polyIndex = 0; polyIndex < gList.rawPolyCount; polyIndex++)
{ {
const POLY &poly = gList.polyList[polyIndex]; const POLY &rawPoly = gList.rawPolyList[polyIndex];
const VERT *clipVerts[4] = { const VERT *rawVerts[4] = {
&gList.vertList[poly.vertIndexes[0]], &gList.rawVertList[rawPoly.vertIndexes[0]],
&gList.vertList[poly.vertIndexes[1]], &gList.rawVertList[rawPoly.vertIndexes[1]],
&gList.vertList[poly.vertIndexes[2]], &gList.rawVertList[rawPoly.vertIndexes[2]],
(poly.type == POLYGON_TYPE_QUAD) ? &gList.vertList[poly.vertIndexes[3]] : NULL (rawPoly.type == POLYGON_TYPE_QUAD) ? &gList.rawVertList[rawPoly.vertIndexes[3]] : NULL
}; };
isPolyUnclipped = _clipper->ClipPoly<CLIPPERMODE>(polyIndex, poly, clipVerts); cpType = GFX3D_GenerateClippedPoly<CLIPPERMODE>(polyIndex, rawPoly.type, rawVerts, outCPolyUnsortedList[clipCount]);
if (cpType != POLYGON_TYPE_UNDEFINED)
if (CLIPPERMODE == ClipperMode_DetermineClipOnly)
{ {
if (isPolyUnclipped) clipCount++;
{
_clippedPolyUnsortedList[polyIndex].index = _clipper->GetClippedPolyByIndex(clipCount).index;
_clippedPolyUnsortedList[polyIndex].poly = _clipper->GetClippedPolyByIndex(clipCount).poly;
clipCount++;
}
}
else
{
if (isPolyUnclipped)
{
_clippedPolyUnsortedList[polyIndex] = _clipper->GetClippedPolyByIndex(clipCount);
clipCount++;
}
} }
} }
return clipCount;
} }
void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State &inState, GFX3D_GeometryList &outGList) void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State &inState, GFX3D_GeometryList &outGList)
{ {
const VERT *__restrict appliedVertList = outGList.vertList; const VERT *__restrict appliedVertList = outGList.rawVertList;
switch (clippingMode) switch (clippingMode)
{ {
case ClipperMode_Full: case ClipperMode_Full:
gfx3d_PerformClipping<ClipperMode_Full>(outGList); outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_Full>(outGList, _clippedPolyUnsortedList);
break; break;
case ClipperMode_FullColorInterpolate: case ClipperMode_FullColorInterpolate:
gfx3d_PerformClipping<ClipperMode_FullColorInterpolate>(outGList); outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_FullColorInterpolate>(outGList, _clippedPolyUnsortedList);
break; break;
case ClipperMode_DetermineClipOnly: case ClipperMode_DetermineClipOnly:
gfx3d_PerformClipping<ClipperMode_DetermineClipOnly>(outGList); outGList.clippedPolyCount = gfx3d_PerformClipping<ClipperMode_DetermineClipOnly>(outGList, _clippedPolyUnsortedList);
break; break;
} }
outGList.clippedPolyCount = _clipper->GetPolyCount();
#ifdef _SHOW_VTX_COUNTERS #ifdef _SHOW_VTX_COUNTERS
max_polys = max((u32)outGList.polyCount, max_polys); max_polys = max((u32)outGList.rawPolyCount, max_polys);
max_verts = max((u32)outGList.vertListCount, max_verts); max_verts = max((u32)outGList.rawVertCount, max_verts);
osd->addFixed(180, 20, "%i/%i", outGList.polyCount, outGList.vertListCount); // current osd->addFixed(180, 20, "%i/%i", outGList.rawPolyCount, outGList.rawVertCount); // current
osd->addFixed(180, 35, "%i/%i", max_polys, max_verts); // max osd->addFixed(180, 35, "%i/%i", max_polys, max_verts); // max
#endif #endif
@ -2389,18 +2365,18 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
size_t ctr = 0; size_t ctr = 0;
for (size_t i = 0; i < outGList.clippedPolyCount; i++) for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{ {
const CPoly &clippedPoly = _clipper->GetClippedPolyByIndex(i); const CPoly &clippedPoly = _clippedPolyUnsortedList[i];
if ( !GFX3D_IsPolyTranslucent(*clippedPoly.poly) ) if ( !GFX3D_IsPolyTranslucent(outGList.rawPolyList[clippedPoly.index]) )
gfx3d.polyWorkingIndexList[ctr++] = (int)clippedPoly.index; gfx3d.polyWorkingIndexList[ctr++] = i;
} }
outGList.clippedPolyOpaqueCount = ctr; outGList.clippedPolyOpaqueCount = ctr;
//then look for translucent polys //then look for translucent polys
for (size_t i = 0; i < outGList.clippedPolyCount; i++) for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{ {
const CPoly &clippedPoly = _clipper->GetClippedPolyByIndex(i); const CPoly &clippedPoly = _clippedPolyUnsortedList[i];
if ( GFX3D_IsPolyTranslucent(*clippedPoly.poly) ) if ( GFX3D_IsPolyTranslucent(outGList.rawPolyList[clippedPoly.index]) )
gfx3d.polyWorkingIndexList[ctr++] = (int)clippedPoly.index; gfx3d.polyWorkingIndexList[ctr++] = i;
} }
//find the min and max y values for each poly. //find the min and max y values for each poly.
@ -2411,11 +2387,12 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
//2. most geometry is opaque which is always sorted anyway //2. most geometry is opaque which is always sorted anyway
for (size_t i = 0; i < outGList.clippedPolyCount; i++) for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{ {
POLY &poly = outGList.rawPolyList[_clippedPolyUnsortedList[i].index];
// TODO: Possible divide by zero with the w-coordinate. // TODO: Possible divide by zero with the w-coordinate.
// Is the vertex being read correctly? Is 0 a valid value for w? // Is the vertex being read correctly? Is 0 a valid value for w?
// If both of these questions answer to yes, then how does the NDS handle a NaN? // If both of these questions answer to yes, then how does the NDS handle a NaN?
// For now, simply prevent w from being zero. // For now, simply prevent w from being zero.
POLY &poly = *_clipper->GetClippedPolyByIndex(i).poly;
float verty = appliedVertList[poly.vertIndexes[0]].y; float verty = appliedVertList[poly.vertIndexes[0]].y;
float vertw = (appliedVertList[poly.vertIndexes[0]].w != 0.0f) ? appliedVertList[poly.vertIndexes[0]].w : 0.00000001f; float vertw = (appliedVertList[poly.vertIndexes[0]].w != 0.0f) ? appliedVertList[poly.vertIndexes[0]].w : 0.00000001f;
verty = 1.0f-(verty+vertw)/(2*vertw); verty = 1.0f-(verty+vertw)/(2*vertw);
@ -2448,7 +2425,7 @@ void GFX3D_GenerateRenderLists(const ClipperMode clippingMode, const GFX3D_State
{ {
for (size_t i = 0; i < outGList.clippedPolyCount; i++) for (size_t i = 0; i < outGList.clippedPolyCount; i++)
{ {
outGList.clippedPolyList[i].poly = _clippedPolyUnsortedList[gfx3d.polyWorkingIndexList[i]].poly; outGList.clippedPolyList[i].index = _clippedPolyUnsortedList[gfx3d.polyWorkingIndexList[i]].index;
} }
} }
else else
@ -2478,9 +2455,8 @@ static void gfx3d_doFlush()
gfx3d.pendingListIndex &= 1; gfx3d.pendingListIndex &= 1;
GFX3D_GeometryList &pendingGList = gfx3d.gList[gfx3d.pendingListIndex]; GFX3D_GeometryList &pendingGList = gfx3d.gList[gfx3d.pendingListIndex];
pendingGList.polyCount = 0; pendingGList.rawPolyCount = 0;
pendingGList.polyOpaqueCount = 0; pendingGList.rawVertCount = 0;
pendingGList.vertListCount = 0;
pendingGList.clippedPolyCount = 0; pendingGList.clippedPolyCount = 0;
pendingGList.clippedPolyOpaqueCount = 0; pendingGList.clippedPolyOpaqueCount = 0;
@ -2488,14 +2464,13 @@ static void gfx3d_doFlush()
{ {
viewer3D.frameNumber = currFrameCounter; viewer3D.frameNumber = currFrameCounter;
viewer3D.state = gfx3d.appliedState; viewer3D.state = gfx3d.appliedState;
viewer3D.gList.polyCount = appliedGList.polyCount; viewer3D.gList.rawVertCount = appliedGList.rawVertCount;
viewer3D.gList.polyOpaqueCount = appliedGList.polyOpaqueCount; viewer3D.gList.rawPolyCount = appliedGList.rawPolyCount;
viewer3D.gList.clippedPolyCount = appliedGList.clippedPolyCount; viewer3D.gList.clippedPolyCount = appliedGList.clippedPolyCount;
viewer3D.gList.clippedPolyOpaqueCount = appliedGList.clippedPolyOpaqueCount; viewer3D.gList.clippedPolyOpaqueCount = appliedGList.clippedPolyOpaqueCount;
viewer3D.gList.vertListCount = appliedGList.vertListCount;
memcpy(viewer3D.gList.polyList, appliedGList.polyList, appliedGList.polyCount * sizeof(POLY)); memcpy(viewer3D.gList.rawVertList, appliedGList.rawVertList, appliedGList.rawVertCount * sizeof(VERT));
memcpy(viewer3D.gList.vertList, appliedGList.vertList, appliedGList.vertListCount * sizeof(VERT)); memcpy(viewer3D.gList.rawPolyList, appliedGList.rawPolyList, appliedGList.rawPolyCount * sizeof(POLY));
memcpy(viewer3D.gList.clippedPolyList, appliedGList.clippedPolyList, appliedGList.clippedPolyCount * sizeof(CPoly)); memcpy(viewer3D.gList.clippedPolyList, appliedGList.clippedPolyList, appliedGList.clippedPolyCount * sizeof(CPoly));
memcpy(viewer3D.indexList, gfx3d.polyWorkingIndexList, appliedGList.clippedPolyCount * sizeof(int)); memcpy(viewer3D.indexList, gfx3d.polyWorkingIndexList, appliedGList.clippedPolyCount * sizeof(int));
@ -2923,16 +2898,16 @@ void gfx3d_savestate(EMUFILE &os)
os.write_32LE(4); os.write_32LE(4);
//dump the render lists //dump the render lists
os.write_32LE((u32)gfx3d.gList[gfx3d.pendingListIndex].vertListCount); os.write_32LE((u32)gfx3d.gList[gfx3d.pendingListIndex].rawVertCount);
for (size_t i = 0; i < gfx3d.gList[gfx3d.pendingListIndex].vertListCount; i++) for (size_t i = 0; i < gfx3d.gList[gfx3d.pendingListIndex].rawVertCount; i++)
{ {
GFX3D_SaveStateVERT(gfx3d.gList[gfx3d.pendingListIndex].vertList[i], os); GFX3D_SaveStateVERT(gfx3d.gList[gfx3d.pendingListIndex].rawVertList[i], os);
} }
os.write_32LE((u32)gfx3d.gList[gfx3d.pendingListIndex].polyCount); os.write_32LE((u32)gfx3d.gList[gfx3d.pendingListIndex].rawPolyCount);
for (size_t i = 0; i < gfx3d.gList[gfx3d.pendingListIndex].polyCount; i++) for (size_t i = 0; i < gfx3d.gList[gfx3d.pendingListIndex].rawPolyCount; i++)
{ {
GFX3D_SaveStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].polyList[i], os); GFX3D_SaveStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].rawPolyList[i], os);
} }
// Write matrix stack data // Write matrix stack data
@ -3012,21 +2987,21 @@ bool gfx3d_loadstate(EMUFILE &is, int size)
u32 polyListCount32 = 0; u32 polyListCount32 = 0;
is.read_32LE(vertListCount32); is.read_32LE(vertListCount32);
gfx3d.gList[gfx3d.pendingListIndex].vertListCount = vertListCount32; gfx3d.gList[gfx3d.pendingListIndex].rawVertCount = vertListCount32;
gfx3d.gList[gfx3d.appliedListIndex].vertListCount = vertListCount32; gfx3d.gList[gfx3d.appliedListIndex].rawVertCount = vertListCount32;
for (size_t i = 0; i < gfx3d.gList[gfx3d.appliedListIndex].vertListCount; i++) for (size_t i = 0; i < gfx3d.gList[gfx3d.appliedListIndex].rawVertCount; i++)
{ {
GFX3D_LoadStateVERT(gfx3d.gList[gfx3d.pendingListIndex].vertList[i], is); GFX3D_LoadStateVERT(gfx3d.gList[gfx3d.pendingListIndex].rawVertList[i], is);
gfx3d.gList[gfx3d.appliedListIndex].vertList[i] = gfx3d.gList[gfx3d.pendingListIndex].vertList[i]; gfx3d.gList[gfx3d.appliedListIndex].rawVertList[i] = gfx3d.gList[gfx3d.pendingListIndex].rawVertList[i];
} }
is.read_32LE(polyListCount32); is.read_32LE(polyListCount32);
gfx3d.gList[gfx3d.pendingListIndex].polyCount = polyListCount32; gfx3d.gList[gfx3d.pendingListIndex].rawPolyCount = polyListCount32;
gfx3d.gList[gfx3d.appliedListIndex].polyCount = polyListCount32; gfx3d.gList[gfx3d.appliedListIndex].rawPolyCount = polyListCount32;
for (size_t i = 0; i < gfx3d.gList[gfx3d.appliedListIndex].polyCount; i++) for (size_t i = 0; i < gfx3d.gList[gfx3d.appliedListIndex].rawPolyCount; i++)
{ {
GFX3D_LoadStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].polyList[i], is); GFX3D_LoadStatePOLY(gfx3d.gList[gfx3d.pendingListIndex].rawPolyList[i], is);
gfx3d.gList[gfx3d.appliedListIndex].polyList[i] = gfx3d.gList[gfx3d.pendingListIndex].polyList[i]; gfx3d.gList[gfx3d.appliedListIndex].rawPolyList[i] = gfx3d.gList[gfx3d.pendingListIndex].rawPolyList[i];
} }
} }
@ -3463,95 +3438,57 @@ typedef ClipperPlane<ClipperMode_DetermineClipOnly, 1,-1,Stage4d> Stage3d;
typedef ClipperPlane<ClipperMode_DetermineClipOnly, 0, 1,Stage3d> Stage2d; static Stage2d clipper2d (clipper3d); // right plane typedef ClipperPlane<ClipperMode_DetermineClipOnly, 0, 1,Stage3d> Stage2d; static Stage2d clipper2d (clipper3d); // right plane
typedef ClipperPlane<ClipperMode_DetermineClipOnly, 0,-1,Stage2d> Stage1d; static Stage1d clipper1d (clipper2d); // left plane typedef ClipperPlane<ClipperMode_DetermineClipOnly, 0,-1,Stage2d> Stage1d; static Stage1d clipper1d (clipper2d); // left plane
GFX3D_Clipper::GFX3D_Clipper()
{
_clippedPolyList = NULL;
_clippedPolyCounter = 0;
}
const CPoly* GFX3D_Clipper::GetClippedPolyBufferPtr()
{
return this->_clippedPolyList;
}
void GFX3D_Clipper::SetClippedPolyBufferPtr(CPoly *bufferPtr)
{
this->_clippedPolyList = bufferPtr;
}
const CPoly& GFX3D_Clipper::GetClippedPolyByIndex(size_t index) const
{
return this->_clippedPolyList[index];
}
size_t GFX3D_Clipper::GetPolyCount() const
{
return this->_clippedPolyCounter;
}
void GFX3D_Clipper::Reset()
{
this->_clippedPolyCounter = 0;
}
template <ClipperMode CLIPPERMODE> template <ClipperMode CLIPPERMODE>
bool GFX3D_Clipper::ClipPoly(const u16 polyIndex, const POLY &poly, const VERT **verts) PolygonType GFX3D_GenerateClippedPoly(const u16 rawPolyIndex, const PolygonType rawPolyType, const VERT **rawVtx, CPoly &outCPoly)
{ {
CLIPLOG("==Begin poly==\n"); CLIPLOG("==Begin poly==\n");
PolygonType outType; PolygonType outClippedType;
const PolygonType polyType = poly.type;
numScratchClipVerts = 0; numScratchClipVerts = 0;
switch (CLIPPERMODE) switch (CLIPPERMODE)
{ {
case ClipperMode_Full: case ClipperMode_Full:
{ {
clipper1.init(this->_clippedPolyList[this->_clippedPolyCounter].clipVerts); clipper1.init(outCPoly.clipVerts);
for (size_t i = 0; i < (size_t)polyType; i++) for (size_t i = 0; i < (size_t)rawPolyType; i++)
clipper1.clipVert(verts[i]); clipper1.clipVert(rawVtx[i]);
outType = (PolygonType)clipper1.finish(); outClippedType = (PolygonType)clipper1.finish();
break; break;
} }
case ClipperMode_FullColorInterpolate: case ClipperMode_FullColorInterpolate:
{ {
clipper1i.init(this->_clippedPolyList[this->_clippedPolyCounter].clipVerts); clipper1i.init(outCPoly.clipVerts);
for (size_t i = 0; i < (size_t)polyType; i++) for (size_t i = 0; i < (size_t)rawPolyType; i++)
clipper1i.clipVert(verts[i]); clipper1i.clipVert(rawVtx[i]);
outType = (PolygonType)clipper1i.finish(); outClippedType = (PolygonType)clipper1i.finish();
break; break;
} }
case ClipperMode_DetermineClipOnly: case ClipperMode_DetermineClipOnly:
{ {
clipper1d.init(this->_clippedPolyList[this->_clippedPolyCounter].clipVerts); clipper1d.init(outCPoly.clipVerts);
for (size_t i = 0; i < (size_t)polyType; i++) for (size_t i = 0; i < (size_t)rawPolyType; i++)
clipper1d.clipVert(verts[i]); clipper1d.clipVert(rawVtx[i]);
outType = (PolygonType)clipper1d.finish(); outClippedType = (PolygonType)clipper1d.finish();
break; break;
} }
} }
assert((u32)outType < MAX_CLIPPED_VERTS); assert((u32)outClippedType < MAX_CLIPPED_VERTS);
if (outType < POLYGON_TYPE_TRIANGLE) if (outClippedType < POLYGON_TYPE_TRIANGLE)
{ {
//a totally clipped poly. discard it. //a totally clipped poly. discard it.
//or, a degenerate poly. we're not handling these right now //or, a degenerate poly. we're not handling these right now
return false; return POLYGON_TYPE_UNDEFINED;
}
else
{
CPoly &thePoly = this->_clippedPolyList[this->_clippedPolyCounter];
thePoly.index = polyIndex;
thePoly.type = outType;
thePoly.poly = (POLY *)&poly;
this->_clippedPolyCounter++;
} }
return true; outCPoly.index = rawPolyIndex;
outCPoly.type = outClippedType;
return outClippedType;
} }

View File

@ -109,8 +109,9 @@ enum PolygonMode
// POLYGON TYPES // POLYGON TYPES
enum PolygonType enum PolygonType
{ {
POLYGON_TYPE_TRIANGLE = 3, POLYGON_TYPE_UNDEFINED = 0,
POLYGON_TYPE_QUAD = 4 POLYGON_TYPE_TRIANGLE = 3,
POLYGON_TYPE_QUAD = 4
}; };
// TEXTURE PARAMETERS - FORMAT ID // TEXTURE PARAMETERS - FORMAT ID
@ -634,30 +635,10 @@ struct CPoly
{ {
u16 index; // The index number of this polygon in the full polygon list. u16 index; // The index number of this polygon in the full polygon list.
PolygonType type; //otherwise known as "count" of verts PolygonType type; //otherwise known as "count" of verts
POLY *poly;
VERT clipVerts[MAX_CLIPPED_VERTS]; VERT clipVerts[MAX_CLIPPED_VERTS];
}; };
typedef struct CPoly CPoly; typedef struct CPoly CPoly;
class GFX3D_Clipper
{
protected:
size_t _clippedPolyCounter;
CPoly *_clippedPolyList; // The output of clipping operations goes into here. Be sure you init it before clipping!
public:
GFX3D_Clipper();
const CPoly* GetClippedPolyBufferPtr();
void SetClippedPolyBufferPtr(CPoly *bufferPtr);
const CPoly& GetClippedPolyByIndex(size_t index) const;
size_t GetPolyCount() const;
void Reset();
template<ClipperMode CLIPPERMODE> bool ClipPoly(const u16 polyIndex, const POLY &poly, const VERT **verts); // the entry point for poly clipping
};
//used to communicate state to the renderer //used to communicate state to the renderer
struct GFX3D_State struct GFX3D_State
{ {
@ -682,13 +663,12 @@ typedef struct GFX3D_State GFX3D_State;
struct GFX3D_GeometryList struct GFX3D_GeometryList
{ {
PAGE_ALIGN VERT vertList[VERTLIST_SIZE]; PAGE_ALIGN VERT rawVertList[VERTLIST_SIZE];
PAGE_ALIGN POLY polyList[POLYLIST_SIZE]; PAGE_ALIGN POLY rawPolyList[POLYLIST_SIZE];
PAGE_ALIGN CPoly clippedPolyList[POLYLIST_SIZE]; PAGE_ALIGN CPoly clippedPolyList[POLYLIST_SIZE];
size_t vertListCount; size_t rawVertCount;
size_t polyCount; size_t rawPolyCount;
size_t polyOpaqueCount;
size_t clippedPolyCount; size_t clippedPolyCount;
size_t clippedPolyOpaqueCount; size_t clippedPolyOpaqueCount;
}; };
@ -750,7 +730,7 @@ struct GFX3D
u32 render3DFrameCount; // Increments when gfx3d_doFlush() is called. Resets every 60 video frames. u32 render3DFrameCount; // Increments when gfx3d_doFlush() is called. Resets every 60 video frames.
// Working lists for rendering. // Working lists for rendering.
PAGE_ALIGN int polyWorkingIndexList[INDEXLIST_SIZE]; PAGE_ALIGN u16 polyWorkingIndexList[POLYLIST_SIZE * 2];
// Everything below is for save state compatibility. // Everything below is for save state compatibility.
IOREG_VIEWPORT viewportLegacySave; // Historically, the viewport was stored as its raw register value. IOREG_VIEWPORT viewportLegacySave; // Historically, the viewport was stored as its raw register value.
@ -809,4 +789,6 @@ void gfx3d_parseCurrentDISP3DCNT();
const GFX3D_IOREG& GFX3D_GetIORegisterMap(); const GFX3D_IOREG& GFX3D_GetIORegisterMap();
void ParseReg_DISP3DCNT(); void ParseReg_DISP3DCNT();
template<ClipperMode CLIPPERMODE> PolygonType GFX3D_GenerateClippedPoly(const u16 rawPolyIndex, const PolygonType rawPolyType, const VERT **rawVtx, CPoly &outCPoly);
#endif //_GFX3D_H_ #endif //_GFX3D_H_

View File

@ -1266,8 +1266,8 @@ void RasterizerUnit<RENDERER>::SetRenderer(SoftRasterizerRenderer *theRenderer)
template<bool RENDERER> template <bool SLI, bool USELINEHACK> template<bool RENDERER> template <bool SLI, bool USELINEHACK>
FORCEINLINE void RasterizerUnit<RENDERER>::Render() FORCEINLINE void RasterizerUnit<RENDERER>::Render()
{ {
const size_t polyCount = this->_softRender->GetClippedPolyCount(); const size_t clippedPolyCount = this->_softRender->GetClippedPolyCount();
if (polyCount == 0) if (clippedPolyCount == 0)
{ {
return; return;
} }
@ -1276,8 +1276,9 @@ FORCEINLINE void RasterizerUnit<RENDERER>::Render()
const size_t dstWidth = this->_softRender->GetFramebufferWidth(); const size_t dstWidth = this->_softRender->GetFramebufferWidth();
const size_t dstHeight = this->_softRender->GetFramebufferHeight(); const size_t dstHeight = this->_softRender->GetFramebufferHeight();
const POLY *rawPolyList = this->_softRender->GetRawPolyList();
const CPoly &firstClippedPoly = this->_softRender->GetClippedPolyByIndex(0); const CPoly &firstClippedPoly = this->_softRender->GetClippedPolyByIndex(0);
const POLY &firstPoly = *firstClippedPoly.poly; const POLY &firstPoly = rawPolyList[firstClippedPoly.index];
POLYGON_ATTR polyAttr = firstPoly.attribute; POLYGON_ATTR polyAttr = firstPoly.attribute;
TEXIMAGE_PARAM lastTexParams = firstPoly.texParam; TEXIMAGE_PARAM lastTexParams = firstPoly.texParam;
u32 lastTexPalette = firstPoly.texPalette; u32 lastTexPalette = firstPoly.texPalette;
@ -1285,25 +1286,24 @@ FORCEINLINE void RasterizerUnit<RENDERER>::Render()
this->_SetupTexture(firstPoly, 0); this->_SetupTexture(firstPoly, 0);
//iterate over polys //iterate over polys
for (size_t i = 0; i < polyCount; i++) for (size_t i = 0; i < clippedPolyCount; i++)
{ {
if (!RENDERER) _debug_thisPoly = (i == this->_softRender->_debug_drawClippedUserPoly); if (!RENDERER) _debug_thisPoly = (i == this->_softRender->_debug_drawClippedUserPoly);
if (!this->_softRender->isPolyVisible[i]) continue; if (!this->_softRender->isPolyVisible[i]) continue;
this->_polynum = i;
const CPoly &clippedPoly = this->_softRender->GetClippedPolyByIndex(i); const CPoly &clippedPoly = this->_softRender->GetClippedPolyByIndex(i);
const POLY &thePoly = *clippedPoly.poly; const POLY &rawPoly = rawPolyList[clippedPoly.index];
const size_t vertCount = (size_t)clippedPoly.type; const size_t vertCount = (size_t)clippedPoly.type;
const bool useLineHack = USELINEHACK && (thePoly.vtxFormat & 4); const bool useLineHack = USELINEHACK && (rawPoly.vtxFormat & 4);
polyAttr = thePoly.attribute; polyAttr = rawPoly.attribute;
const bool isTranslucent = GFX3D_IsPolyTranslucent(thePoly); const bool isTranslucent = GFX3D_IsPolyTranslucent(rawPoly);
if (lastTexParams.value != thePoly.texParam.value || lastTexPalette != thePoly.texPalette) if (lastTexParams.value != rawPoly.texParam.value || lastTexPalette != rawPoly.texPalette)
{ {
lastTexParams = thePoly.texParam; lastTexParams = rawPoly.texParam;
lastTexPalette = thePoly.texPalette; lastTexPalette = rawPoly.texPalette;
this->_SetupTexture(thePoly, i); this->_SetupTexture(rawPoly, i);
} }
for (size_t j = 0; j < vertCount; j++) for (size_t j = 0; j < vertCount; j++)
@ -1877,16 +1877,17 @@ ClipperMode SoftRasterizerRenderer::GetPreferredPolygonClippingMode() const
void SoftRasterizerRenderer::_TransformVertices() void SoftRasterizerRenderer::_TransformVertices()
{ {
const POLY *rawPolyList = this->_rawPolyList;
const float wScalar = (float)this->_framebufferWidth / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH; const float wScalar = (float)this->_framebufferWidth / (float)GPU_FRAMEBUFFER_NATIVE_WIDTH;
const float hScalar = (float)this->_framebufferHeight / (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT; const float hScalar = (float)this->_framebufferHeight / (float)GPU_FRAMEBUFFER_NATIVE_HEIGHT;
//viewport transforms //viewport transforms
for (size_t i = 0; i < this->_clippedPolyCount; i++) for (size_t i = 0; i < this->_clippedPolyCount; i++)
{ {
CPoly &poly = this->_clippedPolyList[i]; CPoly &cPoly = this->_clippedPolyList[i];
for (size_t j = 0; j < (size_t)poly.type; j++) for (size_t j = 0; j < (size_t)cPoly.type; j++)
{ {
VERT &vert = poly.clipVerts[j]; VERT &vert = cPoly.clipVerts[j];
// TODO: Possible divide by zero with the w-coordinate. // TODO: Possible divide by zero with the w-coordinate.
// Is the vertex being read correctly? Is 0 a valid value for w? // Is the vertex being read correctly? Is 0 a valid value for w?
@ -1915,12 +1916,13 @@ void SoftRasterizerRenderer::_TransformVertices()
vert.fcolor[2] /= vertw; vert.fcolor[2] /= vertw;
//viewport transformation //viewport transformation
vert.coord[0] *= poly.poly->viewport.width; const GFX3D_Viewport theViewport = rawPolyList[cPoly.index].viewport;
vert.coord[0] += poly.poly->viewport.x; vert.coord[0] *= theViewport.width;
vert.coord[0] += theViewport.x;
vert.coord[0] *= wScalar; vert.coord[0] *= wScalar;
vert.coord[1] *= poly.poly->viewport.height; vert.coord[1] *= theViewport.height;
vert.coord[1] += poly.poly->viewport.y; vert.coord[1] += theViewport.y;
vert.coord[1] = 192 - vert.coord[1]; vert.coord[1] = 192 - vert.coord[1];
vert.coord[1] *= hScalar; vert.coord[1] *= hScalar;
@ -1941,13 +1943,15 @@ void SoftRasterizerRenderer::_GetPolygonStates()
{ false, true, false, true } { false, true, false, true }
}; };
const POLY *rawPolyList = this->_rawPolyList;
for (size_t i = 0; i < this->_clippedPolyCount; i++) for (size_t i = 0; i < this->_clippedPolyCount; i++)
{ {
const CPoly &clippedPoly = this->_clippedPolyList[i]; const CPoly &clippedPoly = this->_clippedPolyList[i];
const POLY &thePoly = *clippedPoly.poly; const POLY &rawPoly = rawPolyList[clippedPoly.index];
const PolygonType polyType = clippedPoly.type; const PolygonType polyType = clippedPoly.type;
const VERT *vert = &clippedPoly.clipVerts[0]; const VERT *vert = &clippedPoly.clipVerts[0];
const u8 cullingMode = thePoly.attribute.SurfaceCullingMode; const u8 cullingMode = rawPoly.attribute.SurfaceCullingMode;
//HACK: backface culling //HACK: backface culling
//this should be moved to gfx3d, but first we need to redo the way the lists are built //this should be moved to gfx3d, but first we need to redo the way the lists are built
@ -1979,16 +1983,18 @@ void SoftRasterizerRenderer::_GetPolygonStates()
void SoftRasterizerRenderer::GetAndLoadAllTextures() void SoftRasterizerRenderer::GetAndLoadAllTextures()
{ {
const POLY *rawPolyList = this->_rawPolyList;
for (size_t i = 0; i < this->_clippedPolyCount; i++) for (size_t i = 0; i < this->_clippedPolyCount; i++)
{ {
const CPoly &clippedPoly = this->_clippedPolyList[i]; const CPoly &clippedPoly = this->_clippedPolyList[i];
const POLY &thePoly = *clippedPoly.poly; const POLY &rawPoly = rawPolyList[clippedPoly.index];
//make sure all the textures we'll need are cached //make sure all the textures we'll need are cached
//(otherwise on a multithreaded system there will be multiple writers-- //(otherwise on a multithreaded system there will be multiple writers--
//this SHOULD be read-only, although some day the texcache may collect statistics or something //this SHOULD be read-only, although some day the texcache may collect statistics or something
//and then it won't be safe. //and then it won't be safe.
this->_textureList[i] = this->GetLoadedTextureFromPolygon(thePoly, this->_enableTextureSampling); this->_textureList[i] = this->GetLoadedTextureFromPolygon(rawPoly, this->_enableTextureSampling);
} }
} }
@ -2020,6 +2026,7 @@ Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D_State &renderState
this->_clippedPolyCount = renderGList.clippedPolyCount; this->_clippedPolyCount = renderGList.clippedPolyCount;
this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount; this->_clippedPolyOpaqueCount = renderGList.clippedPolyOpaqueCount;
memcpy(this->_clippedPolyList, renderGList.clippedPolyList, this->_clippedPolyCount * sizeof(CPoly)); memcpy(this->_clippedPolyList, renderGList.clippedPolyList, this->_clippedPolyCount * sizeof(CPoly));
this->_rawPolyList = (POLY *)renderGList.rawPolyList;
const bool doMultithreadedStateSetup = (this->_threadCount >= 2); const bool doMultithreadedStateSetup = (this->_threadCount >= 2);

View File

@ -104,7 +104,6 @@ protected:
SoftRasterizerRenderer *_softRender; SoftRasterizerRenderer *_softRender;
SoftRasterizerTexture *_currentTexture; SoftRasterizerTexture *_currentTexture;
const VERT *_verts[MAX_CLIPPED_VERTS]; const VERT *_verts[MAX_CLIPPED_VERTS];
size_t _polynum;
u8 _textureWrapMode; u8 _textureWrapMode;
Render3DError _SetupTexture(const POLY &thePoly, size_t polyRenderIndex); Render3DError _SetupTexture(const POLY &thePoly, size_t polyRenderIndex);

View File

@ -245,9 +245,14 @@ Render3D::Render3D()
_textureList[i] = NULL; _textureList[i] = NULL;
} }
memset(this->clearImageColor16Buffer, 0, sizeof(this->clearImageColor16Buffer)); _clippedPolyCount = 0;
memset(this->clearImageDepthBuffer, 0, sizeof(this->clearImageDepthBuffer)); _clippedPolyOpaqueCount = 0;
memset(this->clearImageFogBuffer, 0, sizeof(this->clearImageFogBuffer)); _clippedPolyList = NULL;
_rawPolyList = NULL;
memset(clearImageColor16Buffer, 0, sizeof(clearImageColor16Buffer));
memset(clearImageDepthBuffer, 0, sizeof(clearImageDepthBuffer));
memset(clearImageFogBuffer, 0, sizeof(clearImageFogBuffer));
Reset(); Reset();
} }
@ -410,6 +415,11 @@ size_t Render3D::GetClippedPolyCount() const
return this->_clippedPolyCount; return this->_clippedPolyCount;
} }
const POLY* Render3D::GetRawPolyList() const
{
return this->_rawPolyList;
}
Render3DError Render3D::ApplyRenderingSettings(const GFX3D_State &renderState) Render3DError Render3D::ApplyRenderingSettings(const GFX3D_State &renderState)
{ {
this->_enableEdgeMark = (CommonSettings.GFX3D_EdgeMark) ? (renderState.DISP3DCNT.EnableEdgeMarking != 0) : false; this->_enableEdgeMark = (CommonSettings.GFX3D_EdgeMark) ? (renderState.DISP3DCNT.EnableEdgeMarking != 0) : false;

View File

@ -188,6 +188,7 @@ protected:
size_t _clippedPolyCount; size_t _clippedPolyCount;
size_t _clippedPolyOpaqueCount; size_t _clippedPolyOpaqueCount;
CPoly *_clippedPolyList; CPoly *_clippedPolyList;
POLY *_rawPolyList;
CACHE_ALIGN u16 clearImageColor16Buffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN u16 clearImageColor16Buffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
CACHE_ALIGN u32 clearImageDepthBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT]; CACHE_ALIGN u32 clearImageDepthBuffer[GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT];
@ -271,6 +272,8 @@ public:
virtual ClipperMode GetPreferredPolygonClippingMode() const; virtual ClipperMode GetPreferredPolygonClippingMode() const;
const CPoly& GetClippedPolyByIndex(size_t index) const; const CPoly& GetClippedPolyByIndex(size_t index) const;
size_t GetClippedPolyCount() const; size_t GetClippedPolyCount() const;
const POLY* GetRawPolyList() const;
}; };
template <size_t SIMDBYTES> template <size_t SIMDBYTES>