tentative timings for "empty" polys scanlines, fix swapped polys breaking

This commit is contained in:
Jaklyy 2023-12-09 15:56:36 -05:00
parent 92ca04e479
commit c45d3320d0
4 changed files with 68 additions and 41 deletions

View File

@ -781,16 +781,16 @@ bool GPU3D::DoTimings(s32 cycles, bool odd)
if (odd) if (odd)
{ {
RasterTimingCounterOdd += cycles; RasterTimingCounterOdd += cycles;
if ((RasterTimingCounterOdd + RasterTimingCounterPrev) < RasterTimingCap) return 0; if ((RasterTimingCounterOdd + RasterTimingCounterPrev) < RasterTimingCap) return false;
} }
else else
{ {
RasterTimingCounterEven += cycles; RasterTimingCounterEven += cycles;
if ((RasterTimingCounterEven + RasterTimingCounterPrev) < RasterTimingCap) return 0; if ((RasterTimingCounterEven + RasterTimingCounterPrev) < RasterTimingCap) return false;
} }
DispCnt |= (1<<12); DispCnt |= (1<<12);
return 1; return true;
} }
void GPU3D::EndScanline(bool odd) void GPU3D::EndScanline(bool odd)
@ -805,7 +805,7 @@ void GPU3D::EndScanline(bool odd)
// seems to display the lowest scanline buffer count reached during the current frame. // seems to display the lowest scanline buffer count reached during the current frame.
// we also caps it to 46 here, because this reg does that too for some reason. // we also caps it to 46 here, because this reg does that too for some reason.
if (RDLines > RDLinesMin) RDLines = RDLinesMin; if (RDLines > RDLinesMin) RDLines = RDLinesMin;
if (RDLines < RDLinesMin) RDLinesMin = RDLines; else if (RDLines < RDLinesMin) RDLinesMin = RDLines;
RasterTimingCounterOdd = 0; RasterTimingCounterOdd = 0;
RasterTimingCounterEven = 0; RasterTimingCounterEven = 0;
} }

View File

@ -30,14 +30,6 @@ namespace melonDS
{ {
class GPU; class GPU;
// numbers based on 339 poly 64-172 horiz. line poly
static constexpr int RasterTimingCap = 51116;
static constexpr int PerPolyTiming = 12; // should be correct for *most* line polygons
static constexpr int PerPixelTiming = 1; // does not apply to the first 4 pixels in a polygon (per scanline?)
static constexpr int PerScanlineTiming = 1064;// approximate currently, used to calc RDLines
static constexpr int PerScanlineRecup = 2112; // seems to check out?
//static constexpr int EmptyPolyScanline;
//static constexpr int FirstPixelTiming;
struct Vertex struct Vertex
{ {
@ -345,6 +337,17 @@ public:
u32 ScrolledLine[256]; u32 ScrolledLine[256];
}; };
// numbers based on 339 poly 64-172 horiz. line poly
static constexpr int Frac = 481; // add a fractional component if pixels is not enough precision
static constexpr int RasterTimingCap = 51116*Frac;
static constexpr int PerScanlineTiming = 1064*Frac; // approximate currently, used to calc RDLines. TEMPORARY UNTIL ACCURATE "FRAMEBUFFER" CAN BE IMPLEMENTED
static constexpr int PerScanlineRecup = 2112*Frac; // seems to check out?
static constexpr int PerPolyTiming = 12*Frac; // should be correct for *most* line polygons and polygons with vertical slopes
static constexpr int PerPixelTiming = 1*Frac; // does not apply to the first 4 pixels in a polygon (per scanline?)
static constexpr int EmptyPolyScanline = 4*Frac - 14; // seems to be slightly under 4?
//static constexpr int FirstPixelTiming;
class Renderer3D class Renderer3D
{ {
public: public:

View File

@ -672,6 +672,31 @@ void SoftRenderer::SetupPolygon(SoftRenderer::RendererPolygon* rp, Polygon* poly
} }
} }
bool SoftRenderer::Step(RendererPolygon* rp, bool abortscanline)
{
rp->XL = rp->SlopeL.Step();
rp->XR = rp->SlopeR.Step();
return abortscanline;
}
void SoftRenderer::CheckSlope(RendererPolygon* rp, s32 y)
{
Polygon* polygon = rp->PolyData;
if (polygon->YTop != polygon->YBottom)
{
if (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom)
{
SetupPolygonLeftEdge(rp, y);
}
if (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom)
{
SetupPolygonRightEdge(rp, y);
}
}
}
void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y) void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
{ {
Polygon* polygon = rp->PolyData; Polygon* polygon = rp->PolyData;
@ -900,10 +925,8 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
rp->XR = rp->SlopeR.Step(); rp->XR = rp->SlopeR.Step();
} }
void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd) bool SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd)
{ {
if (GPU.GPU3D.DoTimings(PerPolyTiming, odd)) return;
int pixelsrendered = 0;
Polygon* polygon = rp->PolyData; Polygon* polygon = rp->PolyData;
u32 polyattr = (polygon->Attr & 0x3F008000); u32 polyattr = (polygon->Attr & 0x3F008000);
if (!polygon->FacingView) polyattr |= (1<<4); if (!polygon->FacingView) polyattr |= (1<<4);
@ -921,18 +944,9 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd)
PrevIsShadowMask = false; PrevIsShadowMask = false;
if (polygon->YTop != polygon->YBottom) CheckSlope(rp, y);
{
if (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom)
{
SetupPolygonLeftEdge(rp, y);
}
if (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom) if (GPU.GPU3D.DoTimings(PerPolyTiming, odd)) return Step(rp, true);
{
SetupPolygonRightEdge(rp, y);
}
}
Vertex *vlcur, *vlnext, *vrcur, *vrnext; Vertex *vlcur, *vlnext, *vrcur, *vrnext;
s32 xstart, xend; s32 xstart, xend;
@ -941,6 +955,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd)
s32 l_edgecov, r_edgecov; s32 l_edgecov, r_edgecov;
Interpolator<1>* interp_start; Interpolator<1>* interp_start;
Interpolator<1>* interp_end; Interpolator<1>* interp_end;
u8 pixelsrendered = 0; // for tracking timings
xstart = rp->XL; xstart = rp->XL;
xend = rp->XR; xend = rp->XR;
@ -1077,10 +1092,11 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd)
if (xcov == 0x3FF) xcov = 0; if (xcov == 0x3FF) xcov = 0;
} }
for (; x < xlimit; x++) for (; x < xlimit; x++)
{ {
if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return; if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return Step(rp, true);
pixelsrendered++; else pixelsrendered++;
if (!l_filledge) continue; if (!l_filledge) continue;
u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x;
u32 dstattr = AttrBuffer[pixeladdr]; u32 dstattr = AttrBuffer[pixeladdr];
@ -1176,8 +1192,8 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd)
for (; x < xlimit; x++) for (; x < xlimit; x++)
{ {
if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return; if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return Step(rp, true);
pixelsrendered++; else pixelsrendered++;
if (wireframe && !edge) continue; if (wireframe && !edge) continue;
u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x;
u32 dstattr = AttrBuffer[pixeladdr]; u32 dstattr = AttrBuffer[pixeladdr];
@ -1270,8 +1286,8 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd)
for (; x < xlimit; x++) for (; x < xlimit; x++)
{ {
if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return; if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return Step(rp, true);
pixelsrendered++; else pixelsrendered++;
if (!r_filledge) continue; if (!r_filledge) continue;
u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x;
u32 dstattr = AttrBuffer[pixeladdr]; u32 dstattr = AttrBuffer[pixeladdr];
@ -1358,27 +1374,33 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd)
PlotTranslucentPixel(pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow); PlotTranslucentPixel(pixeladdr+BufferSize, color, z, polyattr, polygon->IsShadow);
} }
} }
return Step(rp, false);
rp->XL = rp->SlopeL.Step();
rp->XR = rp->SlopeR.Step();
} }
void SoftRenderer::RenderScanline(s32 y, int npolys) void SoftRenderer::RenderScanline(s32 y, int npolys)
{ {
bool odd = !(y % 2); bool odd = !(y % 2);
bool abort = false;
for (int i = 0; i < npolys; i++) for (int i = 0; i < npolys; i++)
{ {
if (GPU.GPU3D.DoTimings(0, odd)) break;
RendererPolygon* rp = &PolygonList[i]; RendererPolygon* rp = &PolygonList[i];
Polygon* polygon = rp->PolyData; Polygon* polygon = rp->PolyData;
if (y >= polygon->YTop && (y < polygon->YBottom || (y == polygon->YTop && polygon->YBottom == polygon->YTop))) if (abort)
{
CheckSlope(rp, y);
Step(rp, NULL);
}
else if (y == polygon->YBottom && y != polygon->YTop)
{
if (GPU.GPU3D.DoTimings(EmptyPolyScanline, odd)) abort = true;
}
else if (y >= polygon->YTop && (y < polygon->YBottom || (y == polygon->YTop && polygon->YBottom == polygon->YTop)))
{ {
if (polygon->IsShadowMask) if (polygon->IsShadowMask)
RenderShadowMaskScanline(rp, y); RenderShadowMaskScanline(rp, y);
else else
RenderPolygonScanline(rp, y, odd); if (RenderPolygonScanline(rp, y, odd)) abort = true;
} }
} }
GPU.GPU3D.EndScanline(odd); GPU.GPU3D.EndScanline(odd);

View File

@ -460,8 +460,10 @@ private:
void SetupPolygonLeftEdge(RendererPolygon* rp, s32 y); void SetupPolygonLeftEdge(RendererPolygon* rp, s32 y);
void SetupPolygonRightEdge(RendererPolygon* rp, s32 y); void SetupPolygonRightEdge(RendererPolygon* rp, s32 y);
void SetupPolygon(RendererPolygon* rp, Polygon* polygon); void SetupPolygon(RendererPolygon* rp, Polygon* polygon);
bool Step(RendererPolygon* rp, bool abortscanline);
void CheckSlope(RendererPolygon* rp, s32 y);
void RenderShadowMaskScanline(RendererPolygon* rp, s32 y); void RenderShadowMaskScanline(RendererPolygon* rp, s32 y);
void RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd); bool RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd);
void RenderScanline(s32 y, int npolys); void RenderScanline(s32 y, int npolys);
u32 CalculateFogDensity(u32 pixeladdr); u32 CalculateFogDensity(u32 pixeladdr);
void ScanlineFinalPass(s32 y); void ScanlineFinalPass(s32 y);