Render3D:
- In SoftRasterizer, do multithreading optimization for the fog and edge mark pass. This involved a change to the edge marking algorithm, so this will need additional testing. - Fix bug where a SoftRasterizer renderer object wouldn’t get destroyed properly. (Regression from r5187.) - Fix bug where the user wasn’t able to switch between different threaded versions of SoftRasterizer. (Regression from r5187.) - Fix a potential bug that might occur if an OpenGL renderer object failed to create. (Regression from r5188.)
This commit is contained in:
parent
c36b8cbebb
commit
dcbe28c94e
|
@ -610,6 +610,8 @@ static Render3D* OpenGLRendererCreate()
|
||||||
if(!strcmp(oglVendorString,"Intel") && strstr(oglRendererString,"965"))
|
if(!strcmp(oglVendorString,"Intel") && strstr(oglRendererString,"965"))
|
||||||
{
|
{
|
||||||
INFO("OpenGL: Incompatible graphic card detected. Disabling OpenGL support.\n");
|
INFO("OpenGL: Incompatible graphic card detected. Disabling OpenGL support.\n");
|
||||||
|
|
||||||
|
ENDGL();
|
||||||
return newRenderer;
|
return newRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,6 +624,7 @@ static Render3D* OpenGLRendererCreate()
|
||||||
OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION,
|
OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MAJOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_MINOR, OGLRENDER_MINIMUM_DRIVER_VERSION_REQUIRED_REVISION,
|
||||||
oglVersionString, oglVendorString, oglRendererString);
|
oglVersionString, oglVendorString, oglRendererString);
|
||||||
|
|
||||||
|
ENDGL();
|
||||||
return newRenderer;
|
return newRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -637,7 +640,10 @@ static Render3D* OpenGLRendererCreate()
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(require_profile)
|
if(require_profile)
|
||||||
|
{
|
||||||
|
ENDGL();
|
||||||
return newRenderer;
|
return newRenderer;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -683,6 +689,8 @@ static Render3D* OpenGLRendererCreate()
|
||||||
{
|
{
|
||||||
INFO("OpenGL: Renderer did not initialize. Disabling 3D renderer.\n[ Driver Info -\n Version: %s\n Vendor: %s\n Renderer: %s ]\n",
|
INFO("OpenGL: Renderer did not initialize. Disabling 3D renderer.\n[ Driver Info -\n Version: %s\n Vendor: %s\n Renderer: %s ]\n",
|
||||||
oglVersionString, oglVendorString, oglRendererString);
|
oglVersionString, oglVendorString, oglRendererString);
|
||||||
|
|
||||||
|
ENDGL();
|
||||||
return newRenderer;
|
return newRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,6 +707,7 @@ static Render3D* OpenGLRendererCreate()
|
||||||
delete newRenderer;
|
delete newRenderer;
|
||||||
newRenderer = NULL;
|
newRenderer = NULL;
|
||||||
|
|
||||||
|
ENDGL();
|
||||||
return newRenderer;
|
return newRenderer;
|
||||||
}
|
}
|
||||||
else if (IsVersionSupported(3, 0, 0) && error == OGLERROR_FBO_CREATE_ERROR && OGLLoadEntryPoints_3_2_Func != NULL)
|
else if (IsVersionSupported(3, 0, 0) && error == OGLERROR_FBO_CREATE_ERROR && OGLLoadEntryPoints_3_2_Func != NULL)
|
||||||
|
@ -707,6 +716,7 @@ static Render3D* OpenGLRendererCreate()
|
||||||
delete newRenderer;
|
delete newRenderer;
|
||||||
newRenderer = NULL;
|
newRenderer = NULL;
|
||||||
|
|
||||||
|
ENDGL();
|
||||||
return newRenderer;
|
return newRenderer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1111,6 +1111,14 @@ static void* SoftRasterizer_RunClearFramebuffer(void *arg)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void* SoftRasterizer_RunRenderEdgeMarkAndFog(void *arg)
|
||||||
|
{
|
||||||
|
SoftRasterizerPostProcessParams *params = (SoftRasterizerPostProcessParams *)arg;
|
||||||
|
params->renderer->RenderEdgeMarkingAndFog(*params);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void _HACK_Viewer_ExecUnit()
|
void _HACK_Viewer_ExecUnit()
|
||||||
{
|
{
|
||||||
_HACK_viewer_rasterizerUnit.mainLoop<false>();
|
_HACK_viewer_rasterizerUnit.mainLoop<false>();
|
||||||
|
@ -1121,10 +1129,19 @@ static Render3D* SoftRasterizerRendererCreate()
|
||||||
return new SoftRasterizerRenderer;
|
return new SoftRasterizerRenderer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void SoftRasterizerRendererDestroy()
|
||||||
|
{
|
||||||
|
if (CurrentRenderer != BaseRenderer)
|
||||||
|
{
|
||||||
|
delete (SoftRasterizerRenderer *)CurrentRenderer;
|
||||||
|
CurrentRenderer = BaseRenderer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
GPU3DInterface gpu3DRasterize = {
|
GPU3DInterface gpu3DRasterize = {
|
||||||
"SoftRasterizer",
|
"SoftRasterizer",
|
||||||
SoftRasterizerRendererCreate,
|
SoftRasterizerRendererCreate,
|
||||||
Render3DBaseDestroy
|
SoftRasterizerRendererDestroy
|
||||||
};
|
};
|
||||||
|
|
||||||
SoftRasterizerRenderer::SoftRasterizerRenderer()
|
SoftRasterizerRenderer::SoftRasterizerRenderer()
|
||||||
|
@ -1159,15 +1176,35 @@ SoftRasterizerRenderer::SoftRasterizerRenderer()
|
||||||
rasterizerUnit[0]._debug_thisPoly = false;
|
rasterizerUnit[0]._debug_thisPoly = false;
|
||||||
rasterizerUnit[0].SLI_MASK = 0;
|
rasterizerUnit[0].SLI_MASK = 0;
|
||||||
rasterizerUnit[0].SLI_VALUE = 0;
|
rasterizerUnit[0].SLI_VALUE = 0;
|
||||||
|
|
||||||
|
postprocessParam = new SoftRasterizerPostProcessParams[rasterizerCores];
|
||||||
|
postprocessParam[0].renderer = this;
|
||||||
|
postprocessParam[0].startLine = 0;
|
||||||
|
postprocessParam[0].endLine = _framebufferHeight;
|
||||||
|
postprocessParam[0].enableEdgeMarking = true;
|
||||||
|
postprocessParam[0].enableFog = true;
|
||||||
|
postprocessParam[0].fogColor = 0x80FFFFFF;
|
||||||
|
postprocessParam[0].fogAlphaOnly = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
const size_t linesPerThread = _framebufferHeight / rasterizerCores;
|
||||||
|
postprocessParam = new SoftRasterizerPostProcessParams[rasterizerCores];
|
||||||
|
|
||||||
for (size_t i = 0; i < rasterizerCores; i++)
|
for (size_t i = 0; i < rasterizerCores; i++)
|
||||||
{
|
{
|
||||||
rasterizerUnit[i]._debug_thisPoly = false;
|
rasterizerUnit[i]._debug_thisPoly = false;
|
||||||
rasterizerUnit[i].SLI_MASK = (rasterizerCores - 1);
|
rasterizerUnit[i].SLI_MASK = (rasterizerCores - 1);
|
||||||
rasterizerUnit[i].SLI_VALUE = i;
|
rasterizerUnit[i].SLI_VALUE = i;
|
||||||
rasterizerUnitTask[i].start(false);
|
rasterizerUnitTask[i].start(false);
|
||||||
|
|
||||||
|
postprocessParam[i].renderer = this;
|
||||||
|
postprocessParam[i].startLine = i * linesPerThread;
|
||||||
|
postprocessParam[i].endLine = (i < rasterizerCores - 1) ? (i + 1) * linesPerThread : _framebufferHeight;
|
||||||
|
postprocessParam[i].enableEdgeMarking = true;
|
||||||
|
postprocessParam[i].enableFog = true;
|
||||||
|
postprocessParam[i].fogColor = 0x80FFFFFF;
|
||||||
|
postprocessParam[i].fogAlphaOnly = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,6 +1229,8 @@ SoftRasterizerRenderer::~SoftRasterizerRenderer()
|
||||||
}
|
}
|
||||||
|
|
||||||
rasterizerUnitTasksInited = false;
|
rasterizerUnitTasksInited = false;
|
||||||
|
delete[] postprocessParam;
|
||||||
|
postprocessParam = NULL;
|
||||||
|
|
||||||
free(screenAttributes);
|
free(screenAttributes);
|
||||||
free(screenColor);
|
free(screenColor);
|
||||||
|
@ -1499,8 +1538,14 @@ Render3DError SoftRasterizerRenderer::RenderGeometry(const GFX3D_State &renderSt
|
||||||
return RENDER3DERROR_NOERR;
|
return RENDER3DERROR_NOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is currently unused right now, in favor of the new multithreaded
|
||||||
|
// SoftRasterizerRenderer::RenderEdgeMarkingAndFog() method. But let's keep this
|
||||||
|
// one around for reference just in case something goes horribly wrong with the
|
||||||
|
// new multithreaded method.
|
||||||
Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias)
|
Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, const bool useAntialias)
|
||||||
{
|
{
|
||||||
|
// TODO: Old edge marking algorithm which tests only polyID, but checks the 8 surrounding pixels. Can this be removed?
|
||||||
|
|
||||||
// this looks ok although it's still pretty much a hack,
|
// this looks ok although it's still pretty much a hack,
|
||||||
// it needs to be redone with low-level accuracy at some point,
|
// it needs to be redone with low-level accuracy at some point,
|
||||||
// but that should probably wait until the shape renderer is more accurate.
|
// but that should probably wait until the shape renderer is more accurate.
|
||||||
|
@ -1513,20 +1558,21 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, c
|
||||||
{
|
{
|
||||||
for (size_t x = 0; x < this->_framebufferWidth; x++, i++)
|
for (size_t x = 0; x < this->_framebufferWidth; x++, i++)
|
||||||
{
|
{
|
||||||
FragmentAttributes destFragment = screenAttributes[i];
|
const FragmentAttributes dstAttributes = this->screenAttributes[i];
|
||||||
u8 self = destFragment.opaquePolyID;
|
const u8 polyID = dstAttributes.opaquePolyID;
|
||||||
if(edgeMarkDisabled[self>>3]) continue;
|
|
||||||
if(destFragment.isTranslucentPoly) continue;
|
if(this->edgeMarkDisabled[polyID>>3]) continue;
|
||||||
|
if(dstAttributes.isTranslucentPoly) continue;
|
||||||
|
|
||||||
// > is used instead of != to prevent double edges
|
// > is used instead of != to prevent double edges
|
||||||
// between overlapping polys of different IDs.
|
// between overlapping polys of different IDs.
|
||||||
// also note that the edge generally goes on the outside, not the inside, (maybe needs to change later)
|
// 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.
|
// and that polys with the same edge color can make edges against each other.
|
||||||
|
|
||||||
FragmentColor edgeColor = this->edgeMarkTable[self>>3];
|
FragmentColor edgeColor = this->edgeMarkTable[polyID>>3];
|
||||||
|
|
||||||
#define PIXOFFSET(dx,dy) ((dx)+(GFX3D_FRAMEBUFFER_WIDTH*(dy)))
|
#define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(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)
|
#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID > this->screenAttributes[i+PIXOFFSET(dx,dy)].opaquePolyID)
|
||||||
#define DRAWEDGE(dx,dy) alphaBlend(screenColor[i+PIXOFFSET(dx,dy)], edgeColor)
|
#define DRAWEDGE(dx,dy) alphaBlend(screenColor[i+PIXOFFSET(dx,dy)], edgeColor)
|
||||||
|
|
||||||
bool upleft = ISEDGE(-1,-1);
|
bool upleft = ISEDGE(-1,-1);
|
||||||
|
@ -1558,7 +1604,6 @@ Render3DError SoftRasterizerRenderer::RenderEdgeMarking(const u16 *colorTable, c
|
||||||
#undef PIXOFFSET
|
#undef PIXOFFSET
|
||||||
#undef ISEDGE
|
#undef ISEDGE
|
||||||
#undef DRAWEDGE
|
#undef DRAWEDGE
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1653,6 +1698,10 @@ Render3DError SoftRasterizerRenderer::UpdateFogTable(const u8 *fogDensityTable)
|
||||||
return RENDER3DERROR_NOERR;
|
return RENDER3DERROR_NOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This method is currently unused right now, in favor of the new multithreaded
|
||||||
|
// SoftRasterizerRenderer::RenderEdgeMarkingAndFog() method. But let's keep this
|
||||||
|
// one around for reference just in case something goes horribly wrong with the
|
||||||
|
// new multithreaded method.
|
||||||
Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u32 color, const u32 offset, const u8 shift, const bool alphaOnly)
|
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 r = GFX3D_5TO6((color)&0x1F);
|
||||||
|
@ -1694,6 +1743,99 @@ Render3DError SoftRasterizerRenderer::RenderFog(const u8 *densityTable, const u3
|
||||||
return RENDER3DERROR_NOERR;
|
return RENDER3DERROR_NOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Render3DError SoftRasterizerRenderer::RenderEdgeMarkingAndFog(const SoftRasterizerPostProcessParams ¶m)
|
||||||
|
{
|
||||||
|
for (size_t i = param.startLine * this->_framebufferWidth, y = param.startLine; y < param.endLine; y++)
|
||||||
|
{
|
||||||
|
for (size_t x = 0; x < this->_framebufferWidth; x++, i++)
|
||||||
|
{
|
||||||
|
FragmentColor &dstColor = screenColor[i];
|
||||||
|
const FragmentAttributes dstAttributes = this->screenAttributes[i];
|
||||||
|
const u32 depth = dstAttributes.depth;
|
||||||
|
const u8 polyID = dstAttributes.opaquePolyID;
|
||||||
|
|
||||||
|
// TODO: New edge marking algorithm which tests both polyID and depth, but only checks 4 surrounding pixels. Can we keep this one?
|
||||||
|
if (param.enableEdgeMarking)
|
||||||
|
{
|
||||||
|
// this looks ok although it's still pretty much a hack,
|
||||||
|
// it needs to be redone with low-level accuracy at some point,
|
||||||
|
// but that should probably wait until the shape renderer is more accurate.
|
||||||
|
// a good test case for edge marking is Sonic Rush:
|
||||||
|
// - 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.
|
||||||
|
|
||||||
|
FragmentColor edgeColor = this->edgeMarkTable[polyID>>3];
|
||||||
|
bool right = false;
|
||||||
|
bool down = false;
|
||||||
|
bool left = false;
|
||||||
|
bool up = false;
|
||||||
|
|
||||||
|
#define PIXOFFSET(dx,dy) ((dx)+(this->_framebufferWidth*(dy)))
|
||||||
|
#define ISEDGE(dx,dy) ((x+(dx) < this->_framebufferWidth) && (y+(dy) < this->_framebufferHeight) && polyID != this->screenAttributes[i+PIXOFFSET(dx,dy)].opaquePolyID && depth >= this->screenAttributes[i+PIXOFFSET(dx,dy)].depth)
|
||||||
|
|
||||||
|
up = ISEDGE( 0,-1);
|
||||||
|
left = ISEDGE(-1, 0);
|
||||||
|
right = ISEDGE( 1, 0);
|
||||||
|
down = ISEDGE( 0, 1);
|
||||||
|
|
||||||
|
if(this->edgeMarkDisabled[polyID>>3]) goto END_EDGE_MARK;
|
||||||
|
if(dstAttributes.isTranslucentPoly) goto END_EDGE_MARK;
|
||||||
|
|
||||||
|
if (right)
|
||||||
|
{
|
||||||
|
edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET( 1, 0)].opaquePolyID >> 3];
|
||||||
|
alphaBlend(dstColor, edgeColor);
|
||||||
|
}
|
||||||
|
else if (down)
|
||||||
|
{
|
||||||
|
edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET( 0, 1)].opaquePolyID >> 3];
|
||||||
|
alphaBlend(dstColor, edgeColor);
|
||||||
|
}
|
||||||
|
else if (left)
|
||||||
|
{
|
||||||
|
edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET(-1, 0)].opaquePolyID >> 3];
|
||||||
|
alphaBlend(dstColor, edgeColor);
|
||||||
|
}
|
||||||
|
else if (up)
|
||||||
|
{
|
||||||
|
edgeColor = this->edgeMarkTable[this->screenAttributes[i+PIXOFFSET( 0,-1)].opaquePolyID >> 3];
|
||||||
|
alphaBlend(dstColor, edgeColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef PIXOFFSET
|
||||||
|
#undef ISEDGE
|
||||||
|
#undef DRAWEDGE
|
||||||
|
|
||||||
|
END_EDGE_MARK: ;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (param.enableFog)
|
||||||
|
{
|
||||||
|
const u32 r = GFX3D_5TO6((param.fogColor)&0x1F);
|
||||||
|
const u32 g = GFX3D_5TO6((param.fogColor>>5)&0x1F);
|
||||||
|
const u32 b = GFX3D_5TO6((param.fogColor>>10)&0x1F);
|
||||||
|
const u32 a = (param.fogColor>>16)&0x1F;
|
||||||
|
|
||||||
|
const size_t fogIndex = depth >> 9;
|
||||||
|
assert(fogIndex < 32768);
|
||||||
|
const u8 fog = (dstAttributes.isFogged) ? this->fogTable[fogIndex] : 0;
|
||||||
|
|
||||||
|
if (!param.fogAlphaOnly)
|
||||||
|
{
|
||||||
|
dstColor.r = ((128-fog)*dstColor.r + r*fog)>>7;
|
||||||
|
dstColor.g = ((128-fog)*dstColor.g + g*fog)>>7;
|
||||||
|
dstColor.b = ((128-fog)*dstColor.b + b*fog)>>7;
|
||||||
|
}
|
||||||
|
|
||||||
|
dstColor.a = ((128-fog)*dstColor.a + a*fog)>>7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return RENDER3DERROR_NOERR;
|
||||||
|
}
|
||||||
|
|
||||||
Render3DError SoftRasterizerRenderer::UpdateToonTable(const u16 *toonTableBuffer)
|
Render3DError SoftRasterizerRenderer::UpdateToonTable(const u16 *toonTableBuffer)
|
||||||
{
|
{
|
||||||
//convert the toon colors
|
//convert the toon colors
|
||||||
|
@ -1802,14 +1944,17 @@ Render3DError SoftRasterizerRenderer::EndRender(const u64 frameCount)
|
||||||
// If we're not multithreaded, then just do the post-processing steps now.
|
// If we're not multithreaded, then just do the post-processing steps now.
|
||||||
if (!this->_renderGeometryNeedsFinish)
|
if (!this->_renderGeometryNeedsFinish)
|
||||||
{
|
{
|
||||||
if (this->currentRenderState->enableEdgeMarking)
|
if (this->currentRenderState->enableEdgeMarking || this->currentRenderState->enableFog)
|
||||||
{
|
{
|
||||||
this->RenderEdgeMarking(this->currentRenderState->edgeMarkColorTable, this->currentRenderState->enableAntialiasing);
|
this->postprocessParam[0].renderer = this;
|
||||||
}
|
this->postprocessParam[0].startLine = 0;
|
||||||
|
this->postprocessParam[0].endLine = this->_framebufferHeight;
|
||||||
if (this->currentRenderState->enableFog)
|
this->postprocessParam[0].enableEdgeMarking = this->currentRenderState->enableEdgeMarking;
|
||||||
{
|
this->postprocessParam[0].enableFog = this->currentRenderState->enableFog;
|
||||||
this->RenderFog(this->currentRenderState->fogDensityTable, this->currentRenderState->fogColor, this->currentRenderState->fogOffset, this->currentRenderState->fogShift, this->currentRenderState->enableFogAlphaOnly);
|
this->postprocessParam[0].fogColor = this->currentRenderState->fogColor;
|
||||||
|
this->postprocessParam[0].fogAlphaOnly = this->currentRenderState->enableFogAlphaOnly;
|
||||||
|
|
||||||
|
this->RenderEdgeMarkingAndFog(this->postprocessParam[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor));
|
memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor));
|
||||||
|
@ -1825,21 +1970,31 @@ Render3DError SoftRasterizerRenderer::RenderFinish()
|
||||||
return RENDER3DERROR_NOERR;
|
return RENDER3DERROR_NOERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Allow for the geometry rendering to finish.
|
||||||
this->_renderGeometryNeedsFinish = false;
|
this->_renderGeometryNeedsFinish = false;
|
||||||
|
|
||||||
for (size_t i = 0; i < rasterizerCores; i++)
|
for (size_t i = 0; i < rasterizerCores; i++)
|
||||||
{
|
{
|
||||||
rasterizerUnitTask[i].finish();
|
rasterizerUnitTask[i].finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->currentRenderState->enableEdgeMarking)
|
// Do multithreaded post-processing.
|
||||||
|
if (this->currentRenderState->enableEdgeMarking || this->currentRenderState->enableFog)
|
||||||
{
|
{
|
||||||
this->RenderEdgeMarking(this->currentRenderState->edgeMarkColorTable, this->currentRenderState->enableAntialiasing);
|
for (size_t i = 0; i < rasterizerCores; i++)
|
||||||
}
|
{
|
||||||
|
this->postprocessParam[i].enableEdgeMarking = this->currentRenderState->enableEdgeMarking;
|
||||||
if (this->currentRenderState->enableFog)
|
this->postprocessParam[i].enableFog = this->currentRenderState->enableFog;
|
||||||
{
|
this->postprocessParam[i].fogColor = this->currentRenderState->fogColor;
|
||||||
this->RenderFog(this->currentRenderState->fogDensityTable, this->currentRenderState->fogColor, this->currentRenderState->fogOffset, this->currentRenderState->fogShift, this->currentRenderState->enableFogAlphaOnly);
|
this->postprocessParam[i].fogAlphaOnly = this->currentRenderState->enableFogAlphaOnly;
|
||||||
|
|
||||||
|
rasterizerUnitTask[i].execute(&SoftRasterizer_RunRenderEdgeMarkAndFog, &this->postprocessParam[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow for post-processing to finish.
|
||||||
|
for (size_t i = 0; i < rasterizerCores; i++)
|
||||||
|
{
|
||||||
|
rasterizerUnitTask[i].finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor));
|
memcpy(gfx3d_convertedScreen, this->screenColor, this->_framebufferWidth * this->_framebufferHeight * sizeof(FragmentColor));
|
||||||
|
|
|
@ -24,6 +24,18 @@
|
||||||
extern GPU3DInterface gpu3DRasterize;
|
extern GPU3DInterface gpu3DRasterize;
|
||||||
|
|
||||||
class TexCacheItem;
|
class TexCacheItem;
|
||||||
|
class SoftRasterizerRenderer;
|
||||||
|
|
||||||
|
struct SoftRasterizerPostProcessParams
|
||||||
|
{
|
||||||
|
SoftRasterizerRenderer *renderer;
|
||||||
|
size_t startLine;
|
||||||
|
size_t endLine;
|
||||||
|
bool enableEdgeMarking;
|
||||||
|
bool enableFog;
|
||||||
|
u32 fogColor;
|
||||||
|
bool fogAlphaOnly;
|
||||||
|
};
|
||||||
|
|
||||||
class SoftRasterizerRenderer : public Render3D
|
class SoftRasterizerRenderer : public Render3D
|
||||||
{
|
{
|
||||||
|
@ -64,6 +76,7 @@ public:
|
||||||
size_t _framebufferWidth;
|
size_t _framebufferWidth;
|
||||||
size_t _framebufferHeight;
|
size_t _framebufferHeight;
|
||||||
GFX3D_State *currentRenderState;
|
GFX3D_State *currentRenderState;
|
||||||
|
SoftRasterizerPostProcessParams *postprocessParam;
|
||||||
|
|
||||||
SoftRasterizerRenderer();
|
SoftRasterizerRenderer();
|
||||||
virtual ~SoftRasterizerRenderer();
|
virtual ~SoftRasterizerRenderer();
|
||||||
|
@ -74,6 +87,7 @@ public:
|
||||||
void setupTextures();
|
void setupTextures();
|
||||||
Render3DError UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable);
|
Render3DError UpdateEdgeMarkColorTable(const u16 *edgeMarkColorTable);
|
||||||
Render3DError UpdateFogTable(const u8 *fogDensityTable);
|
Render3DError UpdateFogTable(const u8 *fogDensityTable);
|
||||||
|
Render3DError RenderEdgeMarkingAndFog(const SoftRasterizerPostProcessParams ¶m);
|
||||||
|
|
||||||
// Base rendering methods
|
// Base rendering methods
|
||||||
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
|
virtual Render3DError UpdateToonTable(const u16 *toonTableBuffer);
|
||||||
|
|
|
@ -70,12 +70,6 @@ bool NDS_3D_ChangeCore(int newCore)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newRenderInterface == gpu3D)
|
|
||||||
{
|
|
||||||
result = true;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some resources are shared between renderers, such as the texture cache,
|
// Some resources are shared between renderers, such as the texture cache,
|
||||||
// so we need to shut down the current renderer now to ensure that any
|
// so we need to shut down the current renderer now to ensure that any
|
||||||
// shared resources aren't in use.
|
// shared resources aren't in use.
|
||||||
|
|
|
@ -139,7 +139,7 @@ public:
|
||||||
// and only release the block when 3D rendering is finished. (Before reading the 3D layer, be
|
// and only release the block when 3D rendering is finished. (Before reading the 3D layer, be
|
||||||
// sure to always call this function.)
|
// sure to always call this function.)
|
||||||
|
|
||||||
virtual Render3DError VramReconfigureSignal(); // Called when the emulator reconfigures its VRAM. Ypu may need to invalidate your texture cache.
|
virtual Render3DError VramReconfigureSignal(); // Called when the emulator reconfigures its VRAM. You may need to invalidate your texture cache.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue