From c45d3320d0a39c0445cae7d80823d50c51a36f09 Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Sat, 9 Dec 2023 15:56:36 -0500 Subject: [PATCH] tentative timings for "empty" polys scanlines, fix swapped polys breaking --- src/GPU3D.cpp | 8 ++--- src/GPU3D.h | 19 ++++++----- src/GPU3D_Soft.cpp | 78 +++++++++++++++++++++++++++++----------------- src/GPU3D_Soft.h | 4 ++- 4 files changed, 68 insertions(+), 41 deletions(-) diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp index e8ac23b4..72b2c78c 100644 --- a/src/GPU3D.cpp +++ b/src/GPU3D.cpp @@ -781,16 +781,16 @@ bool GPU3D::DoTimings(s32 cycles, bool odd) if (odd) { RasterTimingCounterOdd += cycles; - if ((RasterTimingCounterOdd + RasterTimingCounterPrev) < RasterTimingCap) return 0; + if ((RasterTimingCounterOdd + RasterTimingCounterPrev) < RasterTimingCap) return false; } else { RasterTimingCounterEven += cycles; - if ((RasterTimingCounterEven + RasterTimingCounterPrev) < RasterTimingCap) return 0; + if ((RasterTimingCounterEven + RasterTimingCounterPrev) < RasterTimingCap) return false; } DispCnt |= (1<<12); - return 1; + return true; } 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. // we also caps it to 46 here, because this reg does that too for some reason. if (RDLines > RDLinesMin) RDLines = RDLinesMin; - if (RDLines < RDLinesMin) RDLinesMin = RDLines; + else if (RDLines < RDLinesMin) RDLinesMin = RDLines; RasterTimingCounterOdd = 0; RasterTimingCounterEven = 0; } diff --git a/src/GPU3D.h b/src/GPU3D.h index cba5cf73..4450a539 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -30,14 +30,6 @@ namespace melonDS { 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 { @@ -345,6 +337,17 @@ public: 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 { public: diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 1061228e..2cd234b6 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -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) { Polygon* polygon = rp->PolyData; @@ -900,10 +925,8 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y) 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; u32 polyattr = (polygon->Attr & 0x3F008000); if (!polygon->FacingView) polyattr |= (1<<4); @@ -921,18 +944,9 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd) PrevIsShadowMask = false; - 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); - } - } + CheckSlope(rp, y); + + if (GPU.GPU3D.DoTimings(PerPolyTiming, odd)) return Step(rp, true); Vertex *vlcur, *vlnext, *vrcur, *vrnext; s32 xstart, xend; @@ -941,6 +955,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd) s32 l_edgecov, r_edgecov; Interpolator<1>* interp_start; Interpolator<1>* interp_end; + u8 pixelsrendered = 0; // for tracking timings xstart = rp->XL; xend = rp->XR; @@ -1076,11 +1091,12 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd) xcov = (l_edgecov >> 12) & 0x3FF; if (xcov == 0x3FF) xcov = 0; } + for (; x < xlimit; x++) { - if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return; - pixelsrendered++; + if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return Step(rp, true); + else pixelsrendered++; if (!l_filledge) continue; u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 dstattr = AttrBuffer[pixeladdr]; @@ -1176,8 +1192,8 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd) for (; x < xlimit; x++) { - if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return; - pixelsrendered++; + if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return Step(rp, true); + else pixelsrendered++; if (wireframe && !edge) continue; u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; u32 dstattr = AttrBuffer[pixeladdr]; @@ -1270,8 +1286,8 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd) for (; x < xlimit; x++) { - if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return; - pixelsrendered++; + if (pixelsrendered >= 4 && GPU.GPU3D.DoTimings(PerPixelTiming, odd)) return Step(rp, true); + else pixelsrendered++; if (!r_filledge) continue; u32 pixeladdr = FirstPixelOffset + (y*ScanlineWidth) + x; 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); } } - - rp->XL = rp->SlopeL.Step(); - rp->XR = rp->SlopeR.Step(); + return Step(rp, false); } void SoftRenderer::RenderScanline(s32 y, int npolys) { bool odd = !(y % 2); + bool abort = false; for (int i = 0; i < npolys; i++) { - if (GPU.GPU3D.DoTimings(0, odd)) break; - RendererPolygon* rp = &PolygonList[i]; 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) RenderShadowMaskScanline(rp, y); else - RenderPolygonScanline(rp, y, odd); + if (RenderPolygonScanline(rp, y, odd)) abort = true; } } GPU.GPU3D.EndScanline(odd); diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h index 64660ac3..11de0fef 100644 --- a/src/GPU3D_Soft.h +++ b/src/GPU3D_Soft.h @@ -460,8 +460,10 @@ private: void SetupPolygonLeftEdge(RendererPolygon* rp, s32 y); void SetupPolygonRightEdge(RendererPolygon* rp, s32 y); 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 RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd); + bool RenderPolygonScanline(RendererPolygon* rp, s32 y, bool odd); void RenderScanline(s32 y, int npolys); u32 CalculateFogDensity(u32 pixeladdr); void ScanlineFinalPass(s32 y);