Render3D:

- In the OpenGL renderer, optimize framebuffer clearing (OpenGL v3.2 only).
- In SoftRasterizer, multithread the rendering state setup (requires at least 4 threads).
- Do more code refactoring.
This commit is contained in:
rogerman 2015-04-30 08:39:10 +00:00
parent 5c64a3858f
commit 80ac952e9e
10 changed files with 378 additions and 268 deletions

View File

@ -763,7 +763,7 @@ static void OGLRender()
if(!BEGINGL())
return;
_OGLRenderer->Render(&gfx3d.renderState, gfx3d.vertlist, gfx3d.polylist, &gfx3d.indexlist, gfx3d.frameCtr);
_OGLRenderer->Render(gfx3d);
ENDGL();
}
@ -2050,7 +2050,7 @@ Render3DError OpenGLRenderer_1_2::DeleteTexture(const TexCacheItem *item)
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState)
Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D &engine)
{
OGLRenderRef &OGLRef = *this->ref;
this->doubleBufferIndex = (this->doubleBufferIndex + 1) & 0x01;
@ -2060,12 +2060,12 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState)
if (this->isShaderSupported)
{
glUseProgram(OGLRef.programGeometryID);
glUniform1i(OGLRef.uniformStateToonShadingMode, renderState->shading);
glUniform1i(OGLRef.uniformStateEnableAlphaTest, (renderState->enableAlphaTest) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableAntialiasing, (renderState->enableAntialiasing) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (renderState->enableEdgeMarking) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateUseWDepth, (renderState->wbuffer) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]);
glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading);
glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
glUniform1i(OGLRef.uniformTexRenderObject, 0);
glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable);
@ -2074,9 +2074,9 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState)
}
else
{
if(renderState->enableAlphaTest && (renderState->alphaTestRef > 0))
if(engine.renderState.enableAlphaTest && (engine.renderState.alphaTestRef > 0))
{
glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[renderState->alphaTestRef]);
glAlphaFunc(GL_GEQUAL, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
}
else
{
@ -2087,7 +2087,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState)
glLoadIdentity();
}
if(renderState->enableAlphaBlending)
if(engine.renderState.enableAlphaBlending)
{
glEnable(GL_BLEND);
}
@ -2101,7 +2101,7 @@ Render3DError OpenGLRenderer_1_2::BeginRender(const GFX3D_State *renderState)
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State &renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
{
OGLRenderRef &OGLRef = *this->ref;
const size_t polyCount = polyList->count;
@ -2130,7 +2130,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State *renderState,
u32 lastViewport = firstPoly->viewport;
this->SetupPolygon(firstPoly);
this->SetupTexture(firstPoly, renderState->enableTexturing);
this->SetupTexture(firstPoly, renderState.enableTexturing);
this->SetupViewport(lastViewport);
GLsizei vertIndexCount = 0;
@ -2153,7 +2153,7 @@ Render3DError OpenGLRenderer_1_2::RenderGeometry(const GFX3D_State *renderState,
{
lastTexParams = poly->texParam;
lastTexPalette = poly->texPalette;
this->SetupTexture(poly, renderState->enableTexturing);
this->SetupTexture(poly, renderState.enableTexturing);
}
// Set up the viewport if it changed
@ -2279,34 +2279,34 @@ Render3DError OpenGLRenderer_1_2::ClearUsingImage(const u16 *__restrict colorBuf
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_1_2::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const
Render3DError OpenGLRenderer_1_2::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const
{
if (this->isShaderSupported && this->isFBOSupported)
{
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT); // texGColorID
glClearColor(divide5bitBy31_LUT[r], divide5bitBy31_LUT[g], divide5bitBy31_LUT[b], divide5bitBy31_LUT[a]);
glClearDepth((GLclampd)clearDepth / (GLclampd)0x00FFFFFF);
glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]);
glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT1_EXT); // texGDepthID
glClearColor((GLfloat)(clearDepth & 0x000000FF)/255.0f, (GLfloat)((clearDepth >> 8) & 0x000000FF)/255.0f, (GLfloat)((clearDepth >> 16) & 0x000000FF)/255.0f, 1.0);
glClearColor((GLfloat)(clearAttributes.depth & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 8) & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 16) & 0x000000FF)/255.0f, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT2_EXT); // texGPolyID
glClearColor((GLfloat)clearPolyID/63.0f, 0.0, 0.0, 1.0);
glClearColor((GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffer(GL_COLOR_ATTACHMENT3_EXT); // texGFogAttrID
glClearColor((enableFog) ? 1.0 : 0.0, 0.0, 0.0, 1.0);
glClearColor((clearAttributes.isFogged) ? 1.0 : 0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glDrawBuffers(4, RenderDrawList);
}
else
{
glClearColor(divide5bitBy31_LUT[r], divide5bitBy31_LUT[g], divide5bitBy31_LUT[b], divide5bitBy31_LUT[a]);
glClearDepth((GLclampd)clearDepth / (GLclampd)0x00FFFFFF);
glClearColor(divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]);
glClearDepth((GLclampd)clearAttributes.depth / (GLclampd)0x00FFFFFF);
glClearStencil(0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
}
@ -3352,7 +3352,7 @@ Render3DError OpenGLRenderer_2_0::DisableVertexAttributes()
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState)
Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D &engine)
{
OGLRenderRef &OGLRef = *this->ref;
this->doubleBufferIndex = (this->doubleBufferIndex + 1) & 0x01;
@ -3360,19 +3360,19 @@ Render3DError OpenGLRenderer_2_0::BeginRender(const GFX3D_State *renderState)
this->SelectRenderingFramebuffer();
glUseProgram(OGLRef.programGeometryID);
glUniform1i(OGLRef.uniformStateToonShadingMode, renderState->shading);
glUniform1i(OGLRef.uniformStateEnableAlphaTest, (renderState->enableAlphaTest) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableAntialiasing, (renderState->enableAntialiasing) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (renderState->enableEdgeMarking) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateUseWDepth, (renderState->wbuffer) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[renderState->alphaTestRef]);
glUniform1i(OGLRef.uniformStateToonShadingMode, engine.renderState.shading);
glUniform1i(OGLRef.uniformStateEnableAlphaTest, (engine.renderState.enableAlphaTest) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableAntialiasing, (engine.renderState.enableAntialiasing) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateEnableEdgeMarking, (engine.renderState.enableEdgeMarking) ? GL_TRUE : GL_FALSE);
glUniform1i(OGLRef.uniformStateUseWDepth, (engine.renderState.wbuffer) ? GL_TRUE : GL_FALSE);
glUniform1f(OGLRef.uniformStateAlphaTestRef, divide5bitBy31_LUT[engine.renderState.alphaTestRef]);
glUniform1i(OGLRef.uniformTexRenderObject, 0);
glUniform1i(OGLRef.uniformTexToonTable, OGLTextureUnitID_ToonTable);
glEnable(GL_DEPTH_TEST);
glEnable(GL_STENCIL_TEST);
if(renderState->enableAlphaBlending)
if(engine.renderState.enableAlphaBlending)
{
glEnable(GL_BLEND);
}

View File

@ -561,14 +561,12 @@ protected:
virtual Render3DError ReadBackPixels();
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer);
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const;
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const;
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);
@ -579,6 +577,7 @@ public:
~OpenGLRenderer_1_2();
virtual Render3DError InitExtensions();
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError Reset();
virtual Render3DError RenderFinish();
@ -631,7 +630,7 @@ protected:
virtual Render3DError EnableVertexAttributes(const VERTLIST *vertList, const GLushort *indexBuffer, const size_t vertIndexCount);
virtual Render3DError DisableVertexAttributes();
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly);

View File

@ -1012,3 +1012,19 @@ Render3DError OpenGLRenderer_3_2::ClearUsingImage(const u16 *__restrict colorBuf
return OGLERROR_NOERR;
}
Render3DError OpenGLRenderer_3_2::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const
{
const GLfloat oglColor[4] = {divide5bitBy31_LUT[clearColor.r], divide5bitBy31_LUT[clearColor.g], divide5bitBy31_LUT[clearColor.b], divide5bitBy31_LUT[clearColor.a]};
const GLfloat oglDepth[4] = {(GLfloat)(clearAttributes.depth & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 8) & 0x000000FF)/255.0f, (GLfloat)((clearAttributes.depth >> 16) & 0x000000FF)/255.0f, 1.0};
const GLfloat oglPolyID[4] = {(GLfloat)clearAttributes.opaquePolyID/63.0f, 0.0, 0.0, 1.0};
const GLfloat oglFogAttr[4] = {(clearAttributes.isFogged) ? 1.0 : 0.0, 0.0, 0.0, 1.0};
glClearBufferfi(GL_DEPTH_STENCIL, 0, (GLfloat)clearAttributes.depth / (GLfloat)0x00FFFFFF, 0);
glClearBufferfv(GL_COLOR, 0, oglColor); // texGColorID
glClearBufferfv(GL_COLOR, 1, oglDepth); // texGDepthID
glClearBufferfv(GL_COLOR, 2, oglPolyID); // texGPolyID
glClearBufferfv(GL_COLOR, 3, oglFogAttr); // texGFogAttrID
return OGLERROR_NOERR;
}

View File

@ -1,7 +1,7 @@
/*
Copyright (C) 2006 yopyop
Copyright (C) 2006-2007 shash
Copyright (C) 2008-2013 DeSmuME team
Copyright (C) 2008-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -82,6 +82,7 @@ protected:
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly);
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer);
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const;
public:
~OpenGLRenderer_3_2();

View File

@ -537,6 +537,9 @@ void gfx3d_init()
vertlist = &vertlists[0];
}
gfx3d.state.fogDensityTable = MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360;
gfx3d.state.edgeMarkColorTable = (u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330);
makeTables();
gfx3d_reset();
}

View File

@ -658,6 +658,8 @@ struct GFX3D_State
bool invalidateToon;
u16 u16ToonTable[32];
u8 shininessTable[128];
u8 *fogDensityTable; // Alias to MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360
u16 *edgeMarkColorTable; // Alias to MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330
};
struct Viewer3d_State

View File

@ -69,8 +69,6 @@ template<typename T> T _max(T a, T b, T c) { return max(max(a,b),c); }
template<typename T> T _min(T a, T b, T c, T d) { return min(_min(a,b,d),c); }
template<typename T> T _max(T a, T b, T c, T d) { return max(_max(a,b,d),c); }
static const int kUnsetTranslucentPolyID = 255;
static u8 modulate_table[64][64];
static u8 decal_table[32][64][64];
static u8 index_lookup_table[65];
@ -540,7 +538,7 @@ public:
case 2: //toon/highlight shading
{
texColor = sample(texCoordU, texCoordV);
FragmentColor toonColor = this->_softRender->_toonColor32LUT[src.r >> 1];
FragmentColor toonColor = this->_softRender->toonColor32LUT[src.r >> 1];
if(gfx3d.renderState.shading == GFX3D_State::HIGHLIGHT)
{
@ -571,10 +569,8 @@ public:
}
}
FORCEINLINE void pixel(PolygonAttributes &polyAttr, FragmentAttributes *fragmentAttributes, FragmentColor *fragmentColor, int adr, float r, float g, float b, float invu, float invv, float w, float z)
FORCEINLINE void pixel(const PolygonAttributes &polyAttr, FragmentAttributes &dstAttributes, FragmentColor &dstColor, float r, float g, float b, float invu, float invv, float w, float z)
{
FragmentAttributes &destFragment = fragmentAttributes[adr];
FragmentColor &destFragmentColor = fragmentColor[adr];
FragmentColor srcColor;
FragmentColor shaderOutput;
@ -596,15 +592,15 @@ public:
{
if (CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack > 0)
{
if( depth<destFragment.depth - CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack
|| depth>destFragment.depth + CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack)
if( depth < dstAttributes.depth - CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack
|| depth > dstAttributes.depth + CommonSettings.GFX3D_Zelda_Shadow_Depth_Hack)
{
goto depth_fail;
}
}
else
{
if (depth != destFragment.depth)
if (depth != dstAttributes.depth)
{
goto depth_fail;
}
@ -612,7 +608,7 @@ public:
}
else
{
if (depth >= destFragment.depth)
if (depth >= dstAttributes.depth)
{
goto depth_fail;
}
@ -627,7 +623,7 @@ public:
}
else
{
if (destFragment.stencil == 0)
if (dstAttributes.stencil == 0)
{
goto rejected_fragment;
}
@ -635,7 +631,7 @@ public:
//shadow polys have a special check here to keep from self-shadowing when user
//has tried to prevent it from happening
//if this isnt here, then the vehicle select in mariokart will look terrible
if (destFragment.opaquePolyID == polyAttr.polygonID)
if (dstAttributes.opaquePolyID == polyAttr.polygonID)
{
goto rejected_fragment;
}
@ -672,31 +668,31 @@ public:
bool isOpaquePixel = shaderOutput.a == 31;
if (isOpaquePixel)
{
destFragment.opaquePolyID = polyAttr.polygonID;
destFragment.isTranslucentPoly = polyAttr.isTranslucent;
destFragment.isFogged = polyAttr.enableRenderFog;
destFragmentColor = shaderOutput;
dstAttributes.opaquePolyID = polyAttr.polygonID;
dstAttributes.isTranslucentPoly = polyAttr.isTranslucent;
dstAttributes.isFogged = polyAttr.enableRenderFog;
dstColor = shaderOutput;
}
else
{
//dont overwrite pixels on translucent polys with the same polyids
if (destFragment.translucentPolyID == polyAttr.polygonID)
if (dstAttributes.translucentPolyID == polyAttr.polygonID)
goto rejected_fragment;
//originally we were using a test case of shadows-behind-trees in sm64ds
//but, it looks bad in that game. this is actually correct
//if this isnt correct, then complex shape cart shadows in mario kart don't work right
destFragment.translucentPolyID = polyAttr.polygonID;
dstAttributes.translucentPolyID = polyAttr.polygonID;
//alpha blending and write color
alphaBlend(destFragmentColor, shaderOutput);
alphaBlend(dstColor, shaderOutput);
destFragment.isFogged = (destFragment.isFogged && polyAttr.enableRenderFog);
dstAttributes.isFogged = (dstAttributes.isFogged && polyAttr.enableRenderFog);
}
//depth writing
if (isOpaquePixel || polyAttr.enableAlphaDepthWrite)
destFragment.depth = depth;
dstAttributes.depth = depth;
}
@ -709,17 +705,17 @@ public:
goto done;
depth_fail:
if (polyAttr.polygonMode == 3 && polyAttr.polygonID == 0)
destFragment.stencil++;
dstAttributes.stencil++;
rejected_fragment:
done:
;
if (polyAttr.polygonMode == 3 && polyAttr.polygonID != 0 && destFragment.stencil)
destFragment.stencil--;
if (polyAttr.polygonMode == 3 && polyAttr.polygonID != 0 && dstAttributes.stencil)
dstAttributes.stencil--;
}
//draws a single scanline
FORCEINLINE void drawscanline(PolygonAttributes &polyAttr, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack)
FORCEINLINE void drawscanline(const PolygonAttributes &polyAttr, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *pLeft, edge_fx_fl *pRight, bool lineHack)
{
int XStart = pLeft->X;
int width = pRight->X - XStart;
@ -802,7 +798,7 @@ public:
while(width-- > 0)
{
pixel(polyAttr, this->_softRender->screenAttributes, this->_softRender->screenColor, adr,color[0],color[1],color[2],u,v,1.0f/invw,z);
pixel(polyAttr, this->_softRender->screenAttributes[adr], this->_softRender->screenColor[adr], color[0], color[1], color[2], u, v, 1.0f/invw, z);
adr++;
x++;
@ -818,7 +814,7 @@ public:
//runs several scanlines, until an edge is finished
template<bool SLI>
void runscanlines(PolygonAttributes &polyAttr, FragmentColor *color, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack)
void runscanlines(const PolygonAttributes &polyAttr, FragmentColor *color, const size_t framebufferWidth, const size_t framebufferHeight, edge_fx_fl *left, edge_fx_fl *right, bool horizontal, bool lineHack)
{
//oh lord, hack city for edge drawing
@ -957,7 +953,7 @@ public:
//I didnt reference anything for this algorithm but it seems like I've seen it somewhere before.
//Maybe it is like crow's algorithm
template<bool SLI>
void shape_engine(PolygonAttributes &polyAttr, FragmentColor *color, const size_t framebufferWidth, const size_t framebufferHeight, int type, const bool backwards, bool lineHack)
void shape_engine(const PolygonAttributes &polyAttr, FragmentColor *color, const size_t framebufferWidth, const size_t framebufferHeight, int type, const bool backwards, bool lineHack)
{
bool failure = false;
@ -1081,6 +1077,42 @@ static void* execRasterizerUnit(void *arg)
return 0;
}
static void* SoftRasterizer_RunCalculateVertices(void *arg)
{
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
softRender->performViewportTransforms<false>();
softRender->performBackfaceTests();
softRender->performCoordAdjustment();
return NULL;
}
static void* SoftRasterizer_RunSetupTextures(void *arg)
{
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
softRender->setupTextures();
return NULL;
}
static void* SoftRasterizer_RunUpdateTables(void *arg)
{
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
softRender->UpdateToonTable(softRender->currentRenderState->u16ToonTable);
softRender->UpdateFogTable(softRender->currentRenderState->fogDensityTable);
softRender->UpdateEdgeMarkColorTable(softRender->currentRenderState->edgeMarkColorTable);
return NULL;
}
static void* SoftRasterizer_RunClearFramebuffer(void *arg)
{
SoftRasterizerRenderer *softRender = (SoftRasterizerRenderer *)arg;
softRender->ClearFramebuffer(*softRender->currentRenderState);
return NULL;
}
void _HACK_Viewer_ExecUnit()
{
_HACK_viewer_rasterizerUnit.mainLoop<false>();
@ -1115,7 +1147,7 @@ static void SoftRastClose()
static void SoftRastRender()
{
_SoftRastRenderer->Render(&gfx3d.renderState, gfx3d.vertlist, gfx3d.polylist, &gfx3d.indexlist, gfx3d.frameCtr);
_SoftRastRenderer->Render(gfx3d);
}
static void SoftRastVramReconfigureSignal()
@ -1143,6 +1175,7 @@ SoftRasterizerRenderer::SoftRasterizerRenderer()
_debug_drawClippedUserPoly = -1;
clippedPolys = clipper.clippedPolys = new GFX3D_Clipper::TClippedPoly[POLYLIST_SIZE*2];
_stateSetupNeedsFinish = false;
_renderGeometryNeedsFinish = false;
_framebufferWidth = GFX3D_FRAMEBUFFER_WIDTH;
_framebufferHeight = GFX3D_FRAMEBUFFER_HEIGHT;
@ -1268,7 +1301,7 @@ size_t SoftRasterizerRenderer::performClipping(bool hirez, const VERTLIST *vertL
return clipper.clippedPolyCounter;
}
template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms(const size_t polyCount)
template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms()
{
const float xfactor = (float)this->_framebufferWidth/(float)GFX3D_FRAMEBUFFER_WIDTH;
const float yfactor = (float)this->_framebufferHeight/(float)GFX3D_FRAMEBUFFER_HEIGHT;
@ -1276,7 +1309,7 @@ template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms(con
const float ymax = GFX3D_FRAMEBUFFER_HEIGHT*yfactor-(CUSTOM?0.001f:0);
//viewport transforms
for (size_t i = 0; i < polyCount; i++)
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
GFX3D_Clipper::TClippedPoly &poly = clippedPolys[i];
for (size_t j = 0; j < poly.type; j++)
@ -1317,12 +1350,12 @@ template<bool CUSTOM> void SoftRasterizerRenderer::performViewportTransforms(con
}
}
//these templates needed to be instantiated manually
template void SoftRasterizerRenderer::performViewportTransforms<true>(const size_t polyCount);
template void SoftRasterizerRenderer::performViewportTransforms<false>(const size_t polyCount);
template void SoftRasterizerRenderer::performViewportTransforms<true>();
template void SoftRasterizerRenderer::performViewportTransforms<false>();
void SoftRasterizerRenderer::performCoordAdjustment(const size_t polyCount)
void SoftRasterizerRenderer::performCoordAdjustment()
{
for (size_t i = 0; i < polyCount; i++)
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i];
int type = clippedPoly.type;
@ -1337,13 +1370,14 @@ void SoftRasterizerRenderer::performCoordAdjustment(const size_t polyCount)
}
}
void SoftRasterizerRenderer::setupTextures(const size_t polyCount)
void SoftRasterizerRenderer::setupTextures()
{
TexCacheItem *lastTexKey = NULL;
u32 lastTextureFormat = 0, lastTexturePalette = 0;
bool needInitTexture = true;
for (size_t i = 0; i < polyCount; i++)
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i];
POLY *thePoly = clippedPoly.poly;
@ -1388,9 +1422,9 @@ bool PolygonIsVisible(const PolygonAttributes &polyAttr, const bool backfacing)
return false;
}
void SoftRasterizerRenderer::performBackfaceTests(const size_t polyCount)
void SoftRasterizerRenderer::performBackfaceTests()
{
for (size_t i = 0; i < polyCount; i++)
for (size_t i = 0; i < this->_clippedPolyCount; i++)
{
GFX3D_Clipper::TClippedPoly &clippedPoly = clippedPolys[i];
POLY *thePoly = clippedPoly.poly;
@ -1423,40 +1457,82 @@ void SoftRasterizerRenderer::performBackfaceTests(const size_t polyCount)
}
}
Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D_State *renderState)
Render3DError SoftRasterizerRenderer::BeginRender(const GFX3D &engine)
{
// Force threads to finish before rendering with new data
if (rasterizerCores > 1)
{
// Force all threads to finish before rendering with new data
for (size_t i = 0; i < rasterizerCores; i++)
{
rasterizerUnitTask[i].finish();
}
}
// Keep the current render states for later use
this->currentRenderState = (GFX3D_State *)&engine.renderState;
this->_clippedPolyCount = this->performClipping(CommonSettings.GFX3D_HighResolutionInterpolateColor, engine.vertlist, engine.polylist, &engine.indexlist);
if (rasterizerCores >= 4)
{
rasterizerUnitTask[0].execute(&SoftRasterizer_RunCalculateVertices, this);
rasterizerUnitTask[1].execute(&SoftRasterizer_RunSetupTextures, this);
rasterizerUnitTask[2].execute(&SoftRasterizer_RunUpdateTables, this);
rasterizerUnitTask[3].execute(&SoftRasterizer_RunClearFramebuffer, this);
this->_stateSetupNeedsFinish = true;
}
else
{
this->performViewportTransforms<false>();
this->performBackfaceTests();
this->performCoordAdjustment();
this->setupTextures();
this->UpdateToonTable(engine.renderState.u16ToonTable);
if (this->currentRenderState->enableEdgeMarking)
{
this->UpdateEdgeMarkColorTable(this->currentRenderState->edgeMarkColorTable);
}
if (this->currentRenderState->enableFog)
{
this->UpdateFogTable(this->currentRenderState->fogDensityTable);
}
this->ClearFramebuffer(engine.renderState);
this->_stateSetupNeedsFinish = false;
}
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
{
const size_t polyCount = this->performClipping(CommonSettings.GFX3D_HighResolutionInterpolateColor, vertList, polyList, indexList);
this->_clippedPolyCount = polyCount;
this->performViewportTransforms<false>(polyCount);
this->performBackfaceTests(polyCount);
this->performCoordAdjustment(polyCount);
this->setupTextures(polyCount);
// If multithreaded, allow for states to finish setting up
if (this->_stateSetupNeedsFinish)
{
rasterizerUnitTask[0].finish();
rasterizerUnitTask[1].finish();
rasterizerUnitTask[2].finish();
rasterizerUnitTask[3].finish();
this->_stateSetupNeedsFinish = false;
}
// Render the geometry
if (rasterizerCores > 1)
{
for (size_t i = 0; i < rasterizerCores; i++)
{
rasterizerUnitTask[i].execute(&execRasterizerUnit, (void *)i);
}
this->_renderGeometryNeedsFinish = true;
}
else
{
rasterizerUnit[0].mainLoop<false>();
this->_renderGeometryNeedsFinish = false;
}
// printf("rendered %d of %d polys after backface culling\n",gfx3d.polylist->count-culled,gfx3d.polylist->count);
@ -1474,24 +1550,6 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, c
// - the edges are completely sharp/opaque on the very brief title screen intro,
// - the level-start intro gets a pseudo-antialiasing effect around the silhouette,
// - the character edges in-level are clearly transparent, and also show well through shield powerups.
//TODO - need to test and find out whether these get grabbed at flush time, or at render time
//we can do this by rendering a 3d frame and then freezing the system, but only changing the edge mark colors
FragmentColor edgeMarkColors[8];
int edgeMarkDisabled[8];
for (size_t i = 0; i < 8; i++)
{
u16 col = colorTable[i];
edgeMarkColors[i].color = RGB15TO5555(col, (useAntialias) ? 0x0F : 0x1F);
edgeMarkColors[i].r = GFX3D_5TO6(edgeMarkColors[i].r);
edgeMarkColors[i].g = GFX3D_5TO6(edgeMarkColors[i].g);
edgeMarkColors[i].b = GFX3D_5TO6(edgeMarkColors[i].b);
//zero 20-jun-2013 - this doesnt make any sense. at least, it should be related to the 0x8000 bit. if this is undocumented behaviour, lets write about which scenario proves it here, or which scenario is requiring this code.
//// this seems to be the only thing that selectively disables edge marking
//edgeMarkDisabled[i] = (col == 0x7FFF);
edgeMarkDisabled[i] = 0;
}
for (size_t i = 0, y = 0; y < this->_framebufferHeight; y++)
{
@ -1507,7 +1565,7 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, c
// also note that the edge generally goes on the outside, not the inside, (maybe needs to change later)
// and that polys with the same edge color can make edges against each other.
FragmentColor edgeColor = edgeMarkColors[self>>3];
FragmentColor edgeColor = this->edgeMarkTable[self>>3];
#define PIXOFFSET(dx,dy) ((dx)+(GFX3D_FRAMEBUFFER_WIDTH*(dy)))
#define ISEDGE(dx,dy) ((x+(dx)!=GFX3D_FRAMEBUFFER_WIDTH) && (x+(dx)!=-1) && (y+(dy)!=GFX3D_FRAMEBUFFER_HEIGHT) && (y+(dy)!=-1) && self > screenAttributes[i+PIXOFFSET(dx,dy)].opaquePolyID)
@ -1549,7 +1607,28 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, c
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly)
Render3DError SoftRasterizerRenderer::UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable)
{
//TODO: need to test and find out whether these get grabbed at flush time, or at render time
//we can do this by rendering a 3d frame and then freezing the system, but only changing the edge mark colors
for (size_t i = 0; i < 8; i++)
{
u16 col = edgeMarkColorTable[i];
this->edgeMarkTable[i].color = RGB15TO5555(col, (this->currentRenderState->enableAntialiasing) ? 0x0F : 0x1F);
this->edgeMarkTable[i].r = GFX3D_5TO6(this->edgeMarkTable[i].r);
this->edgeMarkTable[i].g = GFX3D_5TO6(this->edgeMarkTable[i].g);
this->edgeMarkTable[i].b = GFX3D_5TO6(this->edgeMarkTable[i].b);
//zero 20-jun-2013 - this doesnt make any sense. at least, it should be related to the 0x8000 bit. if this is undocumented behaviour, lets write about which scenario proves it here, or which scenario is requiring this code.
//// this seems to be the only thing that selectively disables edge marking
//edgeMarkDisabled[i] = (col == 0x7FFF);
this->edgeMarkDisabled[i] = false;
}
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable)
{
#if 0
//TODO - this might be a little slow;
@ -1587,46 +1666,71 @@ Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u3
// this should behave exactly the same as the previous loop,
// except much faster. (because it's not a 2d loop and isn't so branchy either)
// maybe it's fast enough to not need to be cached, now.
const int increment = ((1 << 10) >> shift);
const int incrementDivShift = 10 - shift;
u32 fogOffset = min<u32>(max<u32>(offset, 0), 32768);
const int increment = ((1 << 10) >> this->currentRenderState->fogShift);
const int incrementDivShift = 10 - this->currentRenderState->fogShift;
u32 fogOffset = min<u32>(max<u32>(this->currentRenderState->fogOffset, 0), 32768);
u32 iMin = min<u32>(32768, (( 1 + 1) << incrementDivShift) + fogOffset + 1 - increment);
u32 iMax = min<u32>(32768, ((32 + 1) << incrementDivShift) + fogOffset + 1 - increment);
assert(iMin <= iMax);
memset(fogTable, densityTable[0], iMin);
for(u32 i = iMin; i < iMax; i++) {
// If the fog factor is 127, then treat it as 128.
u8 fogFactor = (fogDensityTable[0] == 127) ? 128 : fogDensityTable[0];
memset(this->fogTable, fogFactor, iMin);
for(u32 i = iMin; i < iMax; i++)
{
int num = (i - fogOffset + (increment-1));
int j = (num >> incrementDivShift) - 1;
u32 value = (num & ~(increment-1)) + fogOffset;
u32 diff = value - i;
assert(j >= 1 && j < 32);
fogTable[i] = ((diff*(densityTable[j-1]) + (increment-diff)*(densityTable[j])) >> incrementDivShift);
fogFactor = ((diff*(fogDensityTable[j-1]) + (increment-diff)*(fogDensityTable[j])) >> incrementDivShift);
this->fogTable[i] = (fogFactor == 127) ? 128 : fogFactor;
}
memset(fogTable+iMax, densityTable[31], 32768-iMax);
fogFactor = (fogDensityTable[31] == 127) ? 128 : fogDensityTable[31];
memset(this->fogTable+iMax, fogFactor, 32768-iMax);
#endif
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly)
{
u32 r = GFX3D_5TO6((color)&0x1F);
u32 g = GFX3D_5TO6((color>>5)&0x1F);
u32 b = GFX3D_5TO6((color>>10)&0x1F);
u32 a = (color>>16)&0x1F;
const size_t framebufferFragmentCount = this->_framebufferWidth * this->_framebufferHeight;
for (size_t i = 0; i < (this->_framebufferWidth * this->_framebufferHeight); i++)
if (!alphaOnly)
{
FragmentAttributes &destFragment = screenAttributes[i];
if (!destFragment.isFogged) continue;
FragmentColor &destFragmentColor = screenColor[i];
u32 fogIndex = destFragment.depth>>9;
assert(fogIndex < 32768);
u8 fog = fogTable[fogIndex];
if (fog == 127) fog = 128;
if (!alphaOnly)
for (size_t i = 0; i < framebufferFragmentCount; i++)
{
const FragmentAttributes &destFragment = screenAttributes[i];
const size_t fogIndex = destFragment.depth >> 9;
assert(fogIndex < 32768);
const u8 fog = (destFragment.isFogged) ? this->fogTable[fogIndex] : 0;
FragmentColor &destFragmentColor = screenColor[i];
destFragmentColor.r = ((128-fog)*destFragmentColor.r + r*fog)>>7;
destFragmentColor.g = ((128-fog)*destFragmentColor.g + g*fog)>>7;
destFragmentColor.b = ((128-fog)*destFragmentColor.b + b*fog)>>7;
destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7;
}
}
else
{
for (size_t i = 0; i < framebufferFragmentCount; i++)
{
const FragmentAttributes &destFragment = screenAttributes[i];
const size_t fogIndex = destFragment.depth >> 9;
assert(fogIndex < 32768);
const u8 fog = (destFragment.isFogged) ? this->fogTable[fogIndex] : 0;
FragmentColor &destFragmentColor = screenColor[i];
destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7;
}
destFragmentColor.a = ((128-fog)*destFragmentColor.a + a*fog)>>7;
}
return RENDER3DERROR_NOERR;
@ -1639,13 +1743,13 @@ Render3DError SoftRasterizerRenderer::UpdateToonTable(const u16 *toonTableBuffer
{
#ifdef WORDS_BIGENDIAN
u32 u32temp = RGB15TO32_NOALPHA(toonTableBuffer[i]);
this->_toonColor32LUT[i].r = (u32temp >> 2) & 0x3F;
this->_toonColor32LUT[i].g = (u32temp >> 10) & 0x3F;
this->_toonColor32LUT[i].b = (u32temp >> 18) & 0x3F;
this->toonColor32LUT[i].r = (u32temp >> 2) & 0x3F;
this->toonColor32LUT[i].g = (u32temp >> 10) & 0x3F;
this->toonColor32LUT[i].b = (u32temp >> 18) & 0x3F;
#else
this->_toonColor32LUT[i].color = (RGB15TO32_NOALPHA(toonTableBuffer[i])>>2)&0x3F3F3F3F;
this->toonColor32LUT[i].color = (RGB15TO32_NOALPHA(toonTableBuffer[i])>>2)&0x3F3F3F3F;
#endif
//printf("%d %d %d %d\n", this->_toonColor32LUT[i].r, this->_toonColor32LUT[i].g, this->_toonColor32LUT[i].b, this->_toonColor32LUT[i].a);
//printf("%d %d %d %d\n", this->toonColor32LUT[i].r, this->toonColor32LUT[i].g, this->toonColor32LUT[i].b, this->toonColor32LUT[i].a);
}
return RENDER3DERROR_NOERR;
@ -1662,41 +1766,30 @@ Render3DError SoftRasterizerRenderer::ClearUsingImage(const u16 *__restrict colo
size_t iw = x + ((this->_framebufferHeight - 1 - y) * this->_framebufferWidth);
((u32 *)this->screenColor)[iw] = RGB15TO6665(colorBuffer[ir] & 0x7FFF, (colorBuffer[ir] >> 15) * 31);
screenAttributes[iw].isFogged = fogBuffer[ir];
screenAttributes[iw].depth = depthBuffer[ir];
screenAttributes[iw].opaquePolyID = polyIDBuffer[ir];
screenAttributes[iw].translucentPolyID = kUnsetTranslucentPolyID;
screenAttributes[iw].isTranslucentPoly = false;
screenAttributes[iw].stencil = 0;
this->screenAttributes[iw].isFogged = fogBuffer[ir];
this->screenAttributes[iw].depth = depthBuffer[ir];
this->screenAttributes[iw].opaquePolyID = polyIDBuffer[ir];
this->screenAttributes[iw].translucentPolyID = kUnsetTranslucentPolyID;
this->screenAttributes[iw].isTranslucentPoly = false;
this->screenAttributes[iw].stencil = 0;
}
}
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const
Render3DError SoftRasterizerRenderer::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const
{
FragmentColor clearFragmentColor;
clearFragmentColor.r = GFX3D_5TO6(r);
clearFragmentColor.g = GFX3D_5TO6(g);
clearFragmentColor.b = GFX3D_5TO6(b);
clearFragmentColor.a = a;
FragmentAttributes clearFragment;
clearFragment.opaquePolyID = clearPolyID;
//special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display
//I am not sure whether it is right, though. previously this was cleared to 0, as a guess,
//but in spiderman2 some fires with polyid 0 try to render on top of the background
clearFragment.translucentPolyID = kUnsetTranslucentPolyID;
clearFragment.depth = clearDepth;
clearFragment.stencil = 0;
clearFragment.isTranslucentPoly = false;
clearFragment.isFogged = enableFog;
FragmentColor convertedClearColor;
convertedClearColor.r = GFX3D_5TO6(clearColor.r);
convertedClearColor.g = GFX3D_5TO6(clearColor.g);
convertedClearColor.b = GFX3D_5TO6(clearColor.b);
convertedClearColor.a = clearColor.a;
for (size_t i = 0; i < (this->_framebufferWidth * this->_framebufferHeight); i++)
{
screenAttributes[i] = clearFragment;
screenColor[i] = clearFragmentColor;
this->screenAttributes[i] = clearAttributes;
this->screenColor[i] = convertedClearColor;
}
return RENDER3DERROR_NOERR;
@ -1717,57 +1810,48 @@ Render3DError SoftRasterizerRenderer::Reset()
rasterizerUnit[0].SetRenderer(this);
}
this->_stateSetupNeedsFinish = false;
this->_renderGeometryNeedsFinish = false;
Default3D_Reset();
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount)
Render3DError SoftRasterizerRenderer::Render(const GFX3D &engine)
{
Render3DError error = RENDER3DERROR_NOERR;
error = this->BeginRender(renderState);
error = this->BeginRender(engine);
if (error != RENDER3DERROR_NOERR)
{
return error;
}
this->UpdateToonTable(renderState->u16ToonTable);
this->ClearFramebuffer(renderState);
this->RenderGeometry(renderState, vertList, polyList, indexList);
this->EndRender(frameCount);
this->RenderGeometry(engine.renderState, engine.vertlist, engine.polylist, &engine.indexlist);
this->EndRender(engine.frameCtr);
if (rasterizerCores > 1)
return error;
}
Render3DError SoftRasterizerRenderer::EndRender(const u64 frameCount)
{
// If we're not multithreaded, then just do the post-processing steps now.
if (!this->_renderGeometryNeedsFinish)
{
this->_enableAntialias = renderState->enableAntialiasing;
this->_enableEdgeMark = renderState->enableEdgeMarking;
this->_enableFog = renderState->enableFog;
this->_enableFogAlphaOnly = renderState->enableFogAlphaOnly;
this->_fogColor = renderState->fogColor;
this->_fogOffset = renderState->fogOffset;
this->_fogShift = renderState->fogShift;
this->_renderGeometryNeedsFinish = true;
}
else
{
this->_renderGeometryNeedsFinish = false;
if (renderState->enableEdgeMarking)
if (this->currentRenderState->enableEdgeMarking)
{
this->RenderEdgeMarking((const u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330), renderState->enableAntialiasing);
this->RenderEdgeMarking(this->currentRenderState->edgeMarkColorTable, this->currentRenderState->enableAntialiasing);
}
if (renderState->enableFog)
if (this->currentRenderState->enableFog)
{
this->RenderFog(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360, renderState->fogColor, renderState->fogOffset, renderState->fogShift, renderState->enableFogAlphaOnly);
this->RenderFog(this->currentRenderState->fogDensityTable, this->currentRenderState->fogColor, this->currentRenderState->fogOffset, this->currentRenderState->fogShift, this->currentRenderState->enableFogAlphaOnly);
}
memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor));
}
return error;
return RENDER3DERROR_NOERR;
}
Render3DError SoftRasterizerRenderer::RenderFinish()
@ -1784,14 +1868,14 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
rasterizerUnitTask[i].finish();
}
if (this->_enableEdgeMark)
if (this->currentRenderState->enableEdgeMarking)
{
this->RenderEdgeMarking((const u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330), this->_enableAntialias);
this->RenderEdgeMarking(this->currentRenderState->edgeMarkColorTable, this->currentRenderState->enableAntialiasing);
}
if (this->_enableFog)
if (this->currentRenderState->enableFog)
{
this->RenderFog(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360, this->_fogColor, this->_fogOffset, this->_fogShift, this->_enableFogAlphaOnly);
this->RenderFog(this->currentRenderState->fogDensityTable, this->currentRenderState->fogColor, this->currentRenderState->fogOffset, this->currentRenderState->fogShift, this->currentRenderState->enableFogAlphaOnly);
}
memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor));

View File

@ -1,5 +1,5 @@
/*
Copyright (C) 2009-2010 DeSmuME team
Copyright (C) 2009-2015 DeSmuME team
This file is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -23,32 +23,6 @@
extern GPU3DInterface gpu3DRasterize;
union FragmentColor
{
u32 color;
struct
{
u8 r,g,b,a;
};
};
inline FragmentColor MakeFragmentColor(u8 r, u8 g,u8 b,u8 a)
{
FragmentColor ret;
ret.r = r; ret.g = g; ret.b = b; ret.a = a;
return ret;
}
struct FragmentAttributes
{
u32 depth;
u8 opaquePolyID;
u8 translucentPolyID;
u8 stencil;
bool isFogged;
bool isTranslucentPoly;
};
class TexCacheItem;
class SoftRasterizerRenderer : public Render3D
@ -56,39 +30,31 @@ class SoftRasterizerRenderer : public Render3D
protected:
GFX3D_Clipper clipper;
u8 fogTable[32768];
bool _enableAntialias;
bool _enableEdgeMark;
bool _enableFog;
bool _enableFogAlphaOnly;
u32 _fogColor;
u32 _fogOffset;
u32 _fogShift;
FragmentColor edgeMarkTable[8];
bool edgeMarkDisabled[8];
bool _stateSetupNeedsFinish;
bool _renderGeometryNeedsFinish;
// SoftRasterizer-specific methods
virtual Render3DError InitTables();
size_t performClipping(bool hirez, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
template<bool CUSTOM> void performViewportTransforms(const size_t polyCount);
void performCoordAdjustment(const size_t polyCount);
void performBackfaceTests(const size_t polyCount);
void setupTextures(const size_t polyCount);
// Base rendering methods
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly);
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer);
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const;
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const;
public:
int _debug_drawClippedUserPoly;
size_t _clippedPolyCount;
FragmentColor _toonColor32LUT[32];
FragmentColor toonColor32LUT[32];
GFX3D_Clipper::TClippedPoly *clippedPolys;
FragmentAttributes *screenAttributes;
FragmentColor *screenColor;
@ -97,12 +63,22 @@ public:
bool polyBackfacing[POLYLIST_SIZE];
size_t _framebufferWidth;
size_t _framebufferHeight;
GFX3D_State *currentRenderState;
SoftRasterizerRenderer();
virtual ~SoftRasterizerRenderer();
template<bool CUSTOM> void performViewportTransforms();
void performBackfaceTests();
void performCoordAdjustment();
void setupTextures();
Render3DError UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable);
Render3DError UpdateFogTable(const u8 *fogDensityTable);
// Base rendering methods
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError Reset();
virtual Render3DError Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount);
virtual Render3DError Render(const GFX3D &engine);
virtual Render3DError RenderFinish();
};

View File

@ -116,12 +116,12 @@ Render3D::Render3D()
Reset();
}
Render3DError Render3D::BeginRender(const GFX3D_State *renderState)
Render3DError Render3D::BeginRender(const GFX3D &engine)
{
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
Render3DError Render3D::RenderGeometry(const GFX3D_State &renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList)
{
return RENDER3DERROR_NOERR;
}
@ -146,27 +146,28 @@ Render3DError Render3D::UpdateToonTable(const u16 *toonTableBuffer)
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState)
Render3DError Render3D::ClearFramebuffer(const GFX3D_State &renderState)
{
Render3DError error = RENDER3DERROR_NOERR;
struct GFX3D_ClearColor
{
u8 r;
u8 g;
u8 b;
u8 a;
} clearColor;
FragmentColor clearColor;
clearColor.r = renderState.clearColor & 0x1F;
clearColor.g = (renderState.clearColor >> 5) & 0x1F;
clearColor.b = (renderState.clearColor >> 10) & 0x1F;
clearColor.a = (renderState.clearColor >> 16) & 0x1F;
clearColor.r = renderState->clearColor & 0x1F;
clearColor.g = (renderState->clearColor >> 5) & 0x1F;
clearColor.b = (renderState->clearColor >> 10) & 0x1F;
clearColor.a = (renderState->clearColor >> 16) & 0x1F;
FragmentAttributes clearFragment;
clearFragment.opaquePolyID = (renderState.clearColor >> 24) & 0x3F;
//special value for uninitialized translucent polyid. without this, fires in spiderman2 dont display
//I am not sure whether it is right, though. previously this was cleared to 0, as a guess,
//but in spiderman2 some fires with polyid 0 try to render on top of the background
clearFragment.translucentPolyID = kUnsetTranslucentPolyID;
clearFragment.depth = renderState.clearDepth;
clearFragment.stencil = 0;
clearFragment.isTranslucentPoly = false;
clearFragment.isFogged = BIT15(renderState.clearColor);
const u8 polyID = (renderState->clearColor >> 24) & 0x3F;
const bool enableFog = BIT15(renderState->clearColor);
if (renderState->enableClearImage)
if (renderState.enableClearImage)
{
//the lion, the witch, and the wardrobe (thats book 1, suck it you new-school numberers)
//uses the scroll registers in the main game engine
@ -197,7 +198,7 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState)
this->clearImageDepthBuffer[dd] = dsDepthToD24S8_LUT[clearDepthBuffer[adr] & 0x7FFF];
this->clearImageFogBuffer[dd] = BIT15(clearDepthBuffer[adr]);
this->clearImagePolyIDBuffer[dd] = polyID;
this->clearImagePolyIDBuffer[dd] = clearFragment.opaquePolyID;
dd++;
}
@ -208,12 +209,12 @@ Render3DError Render3D::ClearFramebuffer(const GFX3D_State *renderState)
error = this->ClearUsingImage(this->clearImageColor16Buffer, this->clearImageDepthBuffer, this->clearImageFogBuffer, this->clearImagePolyIDBuffer);
if (error != RENDER3DERROR_NOERR)
{
error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, polyID, enableFog);
error = this->ClearUsingValues(clearColor, clearFragment);
}
}
else
{
error = this->ClearUsingValues(clearColor.r, clearColor.g, clearColor.b, clearColor.a, renderState->clearDepth, polyID, enableFog);
error = this->ClearUsingValues(clearColor, clearFragment);
}
return error;
@ -224,7 +225,7 @@ Render3DError Render3D::ClearUsingImage(const u16 *__restrict colorBuffer, const
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const
Render3DError Render3D::ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const
{
return RENDER3DERROR_NOERR;
}
@ -254,32 +255,32 @@ Render3DError Render3D::Reset()
return RENDER3DERROR_NOERR;
}
Render3DError Render3D::Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount)
Render3DError Render3D::Render(const GFX3D &engine)
{
Render3DError error = RENDER3DERROR_NOERR;
error = this->BeginRender(renderState);
error = this->BeginRender(engine);
if (error != RENDER3DERROR_NOERR)
{
return error;
}
this->UpdateToonTable(renderState->u16ToonTable);
this->ClearFramebuffer(renderState);
this->UpdateToonTable(engine.renderState.u16ToonTable);
this->ClearFramebuffer(engine.renderState);
this->RenderGeometry(renderState, vertList, polyList, indexList);
this->RenderGeometry(engine.renderState, engine.vertlist, engine.polylist, &engine.indexlist);
if (renderState->enableEdgeMarking)
if (engine.renderState.enableEdgeMarking)
{
this->RenderEdgeMarking((const u16 *)(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0330), renderState->enableAntialiasing);
this->RenderEdgeMarking(engine.renderState.edgeMarkColorTable, engine.renderState.enableAntialiasing);
}
if (renderState->enableFog)
if (engine.renderState.enableFog)
{
this->RenderFog(MMU.MMU_MEM[ARMCPU_ARM9][0x40]+0x0360, renderState->fogColor, renderState->fogOffset, renderState->fogShift, renderState->enableFogAlphaOnly);
this->RenderFog(engine.renderState.fogDensityTable, engine.renderState.fogColor, engine.renderState.fogOffset, engine.renderState.fogShift, engine.renderState.enableFogAlphaOnly);
}
this->EndRender(frameCount);
this->EndRender(engine.frameCtr);
return error;
}

View File

@ -25,6 +25,8 @@
//not using this right now
#define CALL_CONVENTION
#define kUnsetTranslucentPolyID 255
typedef struct Render3DInterface
{
// The name of the plugin, this name will appear in the plugins list
@ -81,6 +83,32 @@ enum Render3DErrorCode
typedef int Render3DError;
union FragmentColor
{
u32 color;
struct
{
u8 r,g,b,a;
};
};
struct FragmentAttributes
{
u32 depth;
u8 opaquePolyID;
u8 translucentPolyID;
u8 stencil;
bool isFogged;
bool isTranslucentPoly;
};
inline FragmentColor MakeFragmentColor(u8 r, u8 g,u8 b,u8 a)
{
FragmentColor ret;
ret.r = r; ret.g = g; ret.b = b; ret.a = a;
return ret;
}
class Render3D
{
protected:
@ -89,17 +117,14 @@ protected:
CACHE_ALIGN bool clearImageFogBuffer[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT];
CACHE_ALIGN u8 clearImagePolyIDBuffer[GFX3D_FRAMEBUFFER_WIDTH * GFX3D_FRAMEBUFFER_HEIGHT];
virtual Render3DError BeginRender(const GFX3D_State *renderState);
virtual Render3DError RenderGeometry(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError BeginRender(const GFX3D &engine);
virtual Render3DError RenderGeometry(const GFX3D_State &renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList);
virtual Render3DError RenderEdgeMarking(const u16 *colorTable, const bool useAntialias);
virtual Render3DError RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly);
virtual Render3DError EndRender(const u64 frameCount);
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearFramebuffer(const GFX3D_State *renderState);
virtual Render3DError ClearUsingImage(const u16 *__restrict colorBuffer, const u32 *__restrict depthBuffer, const bool *__restrict fogBuffer, const u8 *__restrict polyIDBuffer);
virtual Render3DError ClearUsingValues(const u8 r, const u8 g, const u8 b, const u8 a, const u32 clearDepth, const u8 clearPolyID, const bool enableFog) const;
virtual Render3DError ClearUsingValues(const FragmentColor &clearColor, const FragmentAttributes &clearAttributes) const;
virtual Render3DError SetupPolygon(const POLY *thePoly);
virtual Render3DError SetupTexture(const POLY *thePoly, bool enableTexturing);
@ -108,8 +133,11 @@ protected:
public:
Render3D();
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
virtual Render3DError ClearFramebuffer(const GFX3D_State &renderState);
virtual Render3DError Reset();
virtual Render3DError Render(const GFX3D_State *renderState, const VERTLIST *vertList, const POLYLIST *polyList, const INDEXLIST *indexList, const u64 frameCount);
virtual Render3DError Render(const GFX3D &engine);
virtual Render3DError RenderFinish();
virtual Render3DError VramReconfigureSignal();
};