From bf26b6817d444bba8752a645639aa56e4872b63c Mon Sep 17 00:00:00 2001 From: Jaklyy <102590697+Jaklyy@users.noreply.github.com> Date: Sat, 23 Dec 2023 21:26:49 -0500 Subject: [PATCH] partially rendering --- src/GPU3D.h | 5 +- src/GPU3D_Soft.cpp | 370 +++++++++++++++++---------------------------- src/GPU3D_Soft.h | 25 +-- 3 files changed, 151 insertions(+), 249 deletions(-) diff --git a/src/GPU3D.h b/src/GPU3D.h index 03dfa4f0..3c3da750 100644 --- a/src/GPU3D.h +++ b/src/GPU3D.h @@ -336,7 +336,7 @@ public: // GPU 2D Read Timings: For Emulating Buffer Read/Write Race Conditions static constexpr int DelayBetweenReads = 809 * TimingFrac; static constexpr int ScanlineReadSpeed = 256 * TimingFrac; - static constexpr int ScanlineReadInc = DelayBetweenReads + ReadScanline; + static constexpr int ScanlineReadInc = DelayBetweenReads + ScanlineReadSpeed; static constexpr int GPU2DSpeedFirstInPair = 810 * TimingFrac; // 810 | the delay between finishing reading a pair and beginning reading a new pair. @@ -344,8 +344,9 @@ public: // and beginning reading the second scanline of a scanline pair. static constexpr int GPU2DReadScanline = 256 * TimingFrac; // 256 | the time it takes to read a scanline. static constexpr int GPU2DReadSLPair = 1618 * TimingFrac; // 1618 | notably the same as the scanline increment. - static constexpr int InitGPU2DTimeout = 51874 * TimingFrac; // 51618? | when it starts reading the first scanline. + static constexpr int InitGPU2DTimeout = 51874 * TimingFrac; // 51618? | when it finishes reading the first scanline. static constexpr int GPU2D48Scanlines = GPU2DReadSLPair * 24; // time to read 48 scanlines. + static constexpr int FrameLength = ScanlineReadInc * 263; // how long the entire frame is. TODO: Verify if we actually need this? // GPU 3D Rasterization Timings: For Emulating Scanline Timeout diff --git a/src/GPU3D_Soft.cpp b/src/GPU3D_Soft.cpp index 10bbd053..458537d9 100644 --- a/src/GPU3D_Soft.cpp +++ b/src/GPU3D_Soft.cpp @@ -114,33 +114,22 @@ void SoftRenderer::SetThreaded(bool threaded, GPU& gpu) noexcept } } -bool SoftRenderer::DoTimings(s32 cycles, bool odd) +bool SoftRenderer::DoTimings(s32 cycles, s32* timingcounter) { // add timings to a counter and check if underflowed. - - s32* counter; - if (odd) counter = &RasterTimingOdd; - else counter = &RasterTimingEven; - - *counter += cycles; - if (RasterTiming + *counter > ScanlineTimeout) return false; - - return true; + *timingcounter += cycles; + if (RasterTiming + *timingcounter <= ScanlineTimeout) return false; + else return true; } -bool SoftRenderer::CheckTimings(s32 cycles, bool odd) +bool SoftRenderer::CheckTimings(s32 cycles, s32* timingcounter) { // check if there are 'cycles' amount of cycles remaining. - - s32* counter; - if (odd) counter = &RasterTimingOdd; - else counter = &RasterTimingEven; - - if (ScanlineTimeout - (RasterTiming + *counter) >= cycles) return true; + if (RasterTiming + *timingcounter <= ScanlineTimeout - cycles) return true; else return false; } -u32 SoftRenderer::DoTimingsPixels(s32 pixels, bool odd) +u32 SoftRenderer::DoTimingsPixels(s32 pixels, s32* timingcounter) { // calculate and return the difference between the old span and the new span, while adding timings to the timings counter @@ -148,23 +137,19 @@ u32 SoftRenderer::DoTimingsPixels(s32 pixels, bool odd) if (pixels <= NumFreePixels) return 0; pixels -= NumFreePixels; - - s32* counter; - if (odd) counter = &RasterTimingOdd; - else counter = &RasterTimingEven; - *counter += pixels; - pixels = -(ScanlineTimeout - (RasterTiming + *counter)); + *timingcounter += pixels; + pixels = -(ScanlineTimeout - (RasterTiming + *timingcounter)); if (pixels > 0) { - *counter -= pixels; + *timingcounter -= pixels; return pixels; } else return 0; } -bool SoftRenderer::DoTimingsSlopes(RendererPolygon* rp, s32 y, bool odd) +bool SoftRenderer::DoTimingsSlopes(RendererPolygon* rp, s32 y, s32* timingcounter) { // determine the timing impact of the first polygon's slopes. @@ -173,15 +158,11 @@ bool SoftRenderer::DoTimingsSlopes(RendererPolygon* rp, s32 y, bool odd) if (polygon->YTop == polygon->YBottom) return false; // 0 px tall line polygons do not have slopes, and thus no timing penalty if (y == polygon->YTop) return false; - s32* counter; - if (odd) counter = &RasterTimingOdd; - else counter = &RasterTimingEven; + if (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom) *timingcounter += FirstPerSlope; - if (y >= polygon->Vertices[rp->NextVL]->FinalPosition[1] && rp->CurVL != polygon->VBottom) *counter += FirstPerSlope; + if (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom) *timingcounter += FirstPerSlope; - if (y >= polygon->Vertices[rp->NextVR]->FinalPosition[1] && rp->CurVR != polygon->VBottom) *counter += FirstPerSlope; - - return DoTimings(FirstPerSlope*2, odd); // CHECKME: does this need to be done every time its incremented here? does this even need to be done *at all?* + return DoTimings(FirstPerSlope*2, timingcounter); // CHECKME: does this need to be done every time its incremented here? does this even need to be done *at all?* } void SoftRenderer::TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha) const @@ -768,7 +749,7 @@ void SoftRenderer::CheckSlope(RendererPolygon* rp, s32 y) } } -bool SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon* rp, s32 y, bool odd) +bool SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon* rp, s32 y, s32* timingcounter) { Polygon* polygon = rp->PolyData; @@ -903,7 +884,7 @@ bool SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon* // determine if the span can be rendered within the time allotted to the scanline // TODO: verify the timing characteristics of shadow masks are the same as regular polygons. - s32 diff = DoTimingsPixels(xend-x, odd); + s32 diff = DoTimingsPixels(xend-x, timingcounter); if (diff != 0) { xend -= diff; @@ -996,7 +977,7 @@ bool SoftRenderer::RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon* return abortscanline; } -bool SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s32 y, bool odd) +bool SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s32 y, s32* timingcounter) { Polygon* polygon = rp->PolyData; u32 polyattr = (polygon->Attr & 0x3F008000); @@ -1153,7 +1134,7 @@ bool SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3 if (xend > 256) xend = 256; // determine if the span can be rendered within the time allotted to the scanline - s32 diff = DoTimingsPixels(xend-x, odd); + s32 diff = DoTimingsPixels(xend-x, timingcounter); if (diff != 0) { xend -= diff; @@ -1450,7 +1431,7 @@ bool SoftRenderer::RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s3 return abortscanline; } -bool SoftRenderer::RenderScanline(const GPU& gpu, s32 y, int npolys, bool odd) +void SoftRenderer::RenderScanline(const GPU& gpu, s32 y, int npolys, s32* timingcounter) { bool abort = false; bool first = true; @@ -1461,17 +1442,17 @@ bool SoftRenderer::RenderScanline(const GPU& gpu, s32 y, int npolys, bool odd) if (y == polygon->YBottom && y != polygon->YTop) { - if (!abort) abort = (first && DoTimings(FirstNull, odd)) || DoTimings(EmptyPolyScanline, odd); + if (!abort) abort = (first && DoTimings(FirstNull, timingcounter)) || DoTimings(EmptyPolyScanline, timingcounter); first = false; } else if (y >= polygon->YTop && (y < polygon->YBottom || (y == polygon->YTop && polygon->YBottom == polygon->YTop))) { - //if (y == polygon->YTop) if(DoTimings(FirstPolyScanline, odd)) abort = true; + //if (y == polygon->YTop) if(DoTimings(FirstPolyScanline, timingcounter)) abort = true; - if (!abort) abort = (first && DoTimingsSlopes(rp, y, odd)) // incorrect. needs research; behavior is strange... - || DoTimings(PerPolyScanline, odd) - || (!CheckTimings(MinToStartPoly, odd)); + if (!abort) abort = (first && DoTimingsSlopes(rp, y, timingcounter)) // incorrect. needs research; behavior is strange... + || DoTimings(PerPolyScanline, timingcounter) + || (!CheckTimings(MinToStartPoly, timingcounter)); if (abort) { @@ -1479,15 +1460,15 @@ bool SoftRenderer::RenderScanline(const GPU& gpu, s32 y, int npolys, bool odd) Step(rp); } else if (polygon->IsShadowMask) - abort = RenderShadowMaskScanline(gpu.GPU3D, rp, y, odd); + abort = RenderShadowMaskScanline(gpu.GPU3D, rp, y, timingcounter); else - abort = RenderPolygonScanline(gpu, rp, y, odd); + abort = RenderPolygonScanline(gpu, rp, y, timingcounter); first = false; } } - return abort; + return; } u32 SoftRenderer::CalculateFogDensity(const GPU3D& gpu3d, u32 pixeladdr) const @@ -1766,8 +1747,9 @@ u16 SoftRenderer::BeginPushScanline(s32 y, s32 pixelstodraw) { // push the finished scanline to the appropriate frame buffers. // if a scanline is late enough to intersect with the 2d engine read time it will be partially drawn + /* u16 start; - if (pixelstodraw > 256) + if (pixelstodraw >= 256) { start = 0; pixelstodraw = 256; @@ -1786,21 +1768,26 @@ u16 SoftRenderer::BeginPushScanline(s32 y, s32 pixelstodraw) pixelstodraw += jitter; start -= jitter; } - bufferpos = y % 48; + u8 bufferpos = y % 48; memcpy(&RDBuffer[bufferpos*ScanlineWidth+start], &ColorBuffer[y*ScanlineWidth+start], 4 * pixelstodraw); return start; + */ + u8 bufferpos = y % 48; + memcpy(&RDBuffer[bufferpos*ScanlineWidth], &ColorBuffer[y*ScanlineWidth], 4*ScanlineWidth); + return 0; } void SoftRenderer::ReadScanline(s32 y) { + u8 bufferpos = y % 48; memcpy(&FinalBuffer[y*ScanlineWidth], &RDBuffer[bufferpos*ScanlineWidth], 4 * ScanlineWidth); } -void SoftRenderer::FinishPushScanline(s32 y s32 pixelsremain) +void SoftRenderer::FinishPushScanline(s32 y, s32 pixelsremain) { if (pixelsremain = 0) return; - bufferpos = y % 48; + u8 bufferpos = y % 48; memcpy(&RDBuffer[bufferpos*ScanlineWidth], &ColorBuffer[y*ScanlineWidth], 4 * pixelsremain); } @@ -1821,27 +1808,27 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys) s32 yold; rasterevents[RenderStart] = 0; rasterevents[RenderFinal] = INT_MAX/2; - rasterevents[RenderFinalP2] = INT_MAX; - rasterevents[ScanlineWrite] = INT_MAX; + rasterevents[PushScanline] = INT_MAX/2; + rasterevents[PushScanlineP2] = INT_MAX/2; rasterevents[ScanlineRead] = InitGPU2DTimeout; - ScanlineTimeout = INT_MAX; + ScanlineTimeout = INT_MAX/2; RasterTiming = 0; - RasterTimingEven = 0; - RasterTimingOdd = 0; - u8 scanlinesread = 0 - u8 scanlinesrendered; + s32 rastertimingeven = 0; + s32 rastertimingodd = 0; + u8 scanlinesread = 0; + u8 scanlinespushed = 0; + s8 scanlinesrendered = 0; s8 scanlineswaiting = 0; u8 nextevent; - u16 leftoversa; - u16 leftoversb; - bool finalunsched = true; + bool doa, dob, fina; + u16 leftoversa, leftoversb; - while (scanlinesread < 192) + while ((scanlinesread < 192 || scanlinespushed < 192) && (RasterTiming < FrameLength)) { nextevent = 0; - for (int i = 1; i < RasterEvents_MAX - finalunsched; i++) + for (s32 i = 1; i < RasterEvents_MAX; i++) { - if (rasterevents[nextevent] > rasterevents[i]) + if (rasterevents[i] < rasterevents[nextevent]) nextevent = i; } @@ -1849,68 +1836,107 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys) { case RenderStart: - bool abort = RenderScanline(gpu, y, j, true); - abort |= RenderScanline(gpu, y+1, j, false); + RasterTiming = rasterevents[RenderStart]; + + { + s32 rastertimingeven = 0; + s32 rastertimingodd = 0; + RenderScanline(gpu, y, j, &rastertimingeven); + RenderScanline(gpu, y+1, j, &rastertimingodd); + + s32 timespent = std::max(rastertimingeven, rastertimingodd); - timespent = std::max(RasterTimingEven, RasterTimingOdd); - RasterTiming += timespent; if ((RasterTiming + timespent) < (rasterevents[RenderFinal]+FinalPassLen)) RasterTiming += FinalPassLen; else RasterTiming += timespent; - + + s32 timeoutdist = ScanlineTimeout - RasterTiming; RasterTiming += std::clamp(timeoutdist, 0, 12); - + } rasterevents[RenderFinal] = RasterTiming; - rasterevents[RenderScanline] = RasterTiming+RastDelay; - finalunsched = false; + if (y < 190) rasterevents[RenderStart] = RasterTiming+RastDelay; + else rasterevents[RenderStart] = INT_MAX/2; break; case RenderFinal: + + rasterevents[PushScanline] = rasterevents[RenderFinal] + RastDelay; - if (y > 2) + if (y >= 2) { ScanlineFinalPass(gpu.GPU3D, y-1); - leftoversa = BeginPushScanline(y-1, (rasterevents[ScanlineRead] - ScanlineReadSpeed) - (rasterevents[RenderFinal] + FinalPassLen)); - - if (leftoversa != 0) - { - rasterevents[RenderFinalP2] = rasterevents[ScanlineRead] - ScanlineReadSpeed; - yold = y; - } - else - { - scanlineswaiting++; - scanlinesrendered++; - } - } - if (y < 192) - { - ScanlineFinalPass(gpu.GPU3D, y); - leftoversb = BeginPushScanline(y, (rasterevents[ScanlineRead] + DelayBetweenReads) - (rasterevents[RenderFinal] + FinalPassLen)); - - if (leftoversb != 0) - { - rasterevents[RenderFinalP2] = rasterevents[ScanlineRead] + DelaybetweenReads; - yold = y; - } - else - { - scanlineswaiting++; - scanlinesrendered++; - } - - finalunsched = true; + scanlinesrendered++; + doa = true; } else { - rasterevents[RenderFinal] += FinalPassLen; + doa = false; } + if (y < 192) + { + ScanlineFinalPass(gpu.GPU3D, y); + scanlinesrendered++; + rasterevents[RenderFinal] = INT_MAX/2; + } + else + rasterevents[RenderFinal] += FinalPassLen; + y += 2; break; + case PushScanline: + if (scanlineswaiting >= 48) + { + //reschedule events if buffer is full + rasterevents[PushScanline] = rasterevents[ScanlineRead]; + rasterevents[RenderStart] = ((y >= 190) ? INT_MAX/2 : rasterevents[ScanlineRead] + RastDelay); + rasterevents[RenderFinal] = ((y >= 192) ? INT_MAX/2 : rasterevents[ScanlineRead]); + break; + } + + if (doa) + { + leftoversa = BeginPushScanline(scanlinespushed, 256);//(rasterevents[ScanlineRead] - ScanlineReadSpeed) - (rasterevents[PushScanline] + FinalPassLen)); + scanlinesrendered--; + + if (leftoversa != 0) + { + rasterevents[PushScanlineP2] = rasterevents[ScanlineRead] - ScanlineReadSpeed; // todo: fix this + fina = true; + } + else + { + scanlineswaiting++; + scanlinespushed++; + } + } + else + { + leftoversb = BeginPushScanline(scanlinespushed, 256);//(rasterevents[ScanlineRead] + DelayBetweenReads) - (rasterevents[PushScanline] + FinalPassLen)); + scanlinesrendered--; + + if (leftoversb != 0) + { + rasterevents[PushScanlineP2] = rasterevents[ScanlineRead] + DelayBetweenReads; // todo: fix this + fina = false; + } + else + { + scanlineswaiting++; + scanlinespushed++; + } + } + + if (scanlinesrendered <= 0) + rasterevents[PushScanline] = INT_MAX/2; + else + doa = !doa; + + break; + case ScanlineRead: ReadScanline(scanlinesread); @@ -1923,152 +1949,26 @@ void SoftRenderer::RenderPolygons(GPU& gpu, Polygon** polygons, int npolys) scanlineswaiting--; break; - case RenderFinalP2: + case PushScanlineP2: - if (y > 2) + if (fina) { FinishPushScanline(yold-1, leftoversa); scanlineswaiting++; - scanlinesrendered++; + scanlinespushed++; } - if (y < 192) + else { FinishPushScanline(yold, leftoversb); scanlineswaiting++; - scanlinesrendered++; + scanlinespushed++; } - rasterevents[RenderFinalP2] = INT_MAX; + rasterevents[PushScanlineP2] = INT_MAX/2; break; } } } - /*ScanlineRead = InitGPU2DTimeout; - ScanlineTimeout = INT_MAX; - RasterTiming = 0; - s32 prevscanlineread; - s32 prevrastertiming; - - for (y = 0; y < 192; y += 2) - { - RasterTimingEven = 0; - RasterTimingOdd = 0; - // scanlines are rendered in pairs simultaneously - bool abort = RenderScanline(gpu, y, j, true); - abort |= RenderScanline(gpu, y+1, j, false); - - timespent = std::max(RasterTimingEven, RasterTimingOdd); - if (timespend > FreeTiming) - RasterTiming += timespent; - - // the next loop begins - if (y!=0) - { - // finish second scanline from 2 pairs back - ScanlineFinalPass(gpu.GPU3D, y-1); - PushScanline(y-1, (ScanlineRead+GPU2DReadScanline)-(RasterTiming+FinishScanline)); - ScanlineRead += ScanlineReadInc; - if constexpr (threaded) Platform::Semaphore_Post(Sema_ScanlineCount); - } - // finish previous first scanline - ScanlineFinalPass(gpu.GPU3D, y); - PushScanline(y, (ScanlineRead+GPU2DReadScanline)-(RasterTiming+FinishScanline)); - ScanlineRead += ScanlineReadInc; - if constexpr (threaded) Platform::Semaphore_Post(Sema_ScanlineCount); - y += 2; - } - RasterTiming += - // one more loop just to finish off the final scanline - ScanlineFinalPass(gpu.GPU3D, 191); - PushScanline(191, (ScanlineRead+GPU2DReadScanline)-(RasterTiming+FinishScanline)); - if constexpr (threaded) Platform::Semaphore_Post(Sema_ScanlineCount); - */ - - - /*s32 y = 0; - s8 prevbufferline = -2; - - s8 buffersize = 0; - RasterTiming = INT_MAX/2; - bool abort = false; - ClearBuffers(gpu); - s32 gpu2dtracking = InitGPU2DTimeout; - s32 prev2dtime; - bool readodd = true; - - for (u8 quarter = 0; quarter < 4; quarter++) - for (u8 bufferline = 0; bufferline < 48; bufferline += 2) - { - RasterTimingOdd = 0; - RasterTimingEven = 0; - - if (y == 2) RasterTiming = InitialTiming; - - RasterTiming += ScanlineIncrement; - gpu2dtracking += GPU2DReadSLPair; - if (abort) RasterTiming += AbortIncrement; // if previous scanline was aborted, allow an extra 12 pixels worth of timing - - if (y >= 50) - { - if (RasterTiming > Post50Max) - { - s32 temp = RasterTiming - Post50Max; - RasterTiming = Post50Max; - gpu2dtracking -= temp; - } - if (buffersize > 48) buffersize = 48; - } - - abort = RenderScanline(gpu, y, j, true); - abort |= RenderScanline(gpu, y+1, j, false); - - buffersize += 2; - //RasterTiming += ScanlineBreak; - s32 timespent = std::max(RasterTimingOdd, RasterTimingEven); - - if (RasterTiming - timespent <= UnderflowFlag) gpu.GPU3D.DispCnt |= (1<<12); // checkme: should this flag set itself every frame a "underflowed" frame is rendered, even if said frame is duplicated? - - timespent -= FreeTiming; - - if (timespent > 0) - { - RasterTiming -= timespent; - gpu2dtracking -= timespent; - } - - - //if (RasterTiming < 0) RasterTiming = 0; - buffersize = 0; - for (int i = gpu2dtracking; i > 0; i -= GPU2DReadSLPair/2) buffersize++; - - if (buffersize < gpu.GPU3D.RDLines) gpu.GPU3D.RDLines = buffersize; - - if (prevbufferline >= 0) - { - ScanlineFinalPass(gpu.GPU3D, y-2, prevbufferline, true, prev2dtime); - ScanlineFinalPass(gpu.GPU3D, y-1, prevbufferline+1, false, prev2dtime); - if (threaded) - { - Platform::Semaphore_Post(Sema_ScanlineCount); - Platform::Semaphore_Post(Sema_ScanlineCount); - } - } - - y += 2; - prevbufferline = bufferline; - prev2dtime = gpu2dtracking; - - } - - ScanlineFinalPass(gpu.GPU3D, 190, prevbufferline, true, prev2dtime); - ScanlineFinalPass(gpu.GPU3D, 191, prevbufferline+1, false, prev2dtime); - - if (threaded) - { - Platform::Semaphore_Post(Sema_ScanlineCount); - Platform::Semaphore_Post(Sema_ScanlineCount); - } -}*/ void SoftRenderer::VCount144(GPU& gpu) { diff --git a/src/GPU3D_Soft.h b/src/GPU3D_Soft.h index 69aeeb1d..33576e3b 100644 --- a/src/GPU3D_Soft.h +++ b/src/GPU3D_Soft.h @@ -453,10 +453,10 @@ private: }; RendererPolygon PolygonList[2048]; - bool DoTimings(s32 cycles, bool odd); - bool CheckTimings(s32 cycles, bool odd); - u32 DoTimingsPixels(s32 pixels, bool odd); - bool DoTimingsSlopes(RendererPolygon* rp, s32 y, bool odd); + bool DoTimings(s32 cycles, s32* timingcounter); + bool CheckTimings(s32 cycles, s32* timingcounter); + u32 DoTimingsPixels(s32 pixels, s32* timingcounter); + bool DoTimingsSlopes(RendererPolygon* rp, s32 y, s32* timingcounter); void TextureLookup(const GPU& gpu, u32 texparam, u32 texpal, s16 s, s16 t, u16* color, u8* alpha) const; u32 RenderPixel(const GPU& gpu, const Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16 t) const; void PlotTranslucentPixel(const GPU3D& gpu3d, u32 pixeladdr, u32 color, u32 z, u32 polyattr, u32 shadow); @@ -465,28 +465,29 @@ private: void SetupPolygon(RendererPolygon* rp, Polygon* polygon) const; void Step(RendererPolygon* rp); void CheckSlope(RendererPolygon* rp, s32 y); - bool RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon* rp, s32 y, bool odd); - bool RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s32 y, bool odd); - bool RenderScanline(const GPU& gpu, s32 y, int npolys, bool odd); + bool RenderShadowMaskScanline(const GPU3D& gpu3d, RendererPolygon* rp, s32 y, s32* timingcounter); + bool RenderPolygonScanline(const GPU& gpu, RendererPolygon* rp, s32 y, s32* timingcounter); + void RenderScanline(const GPU& gpu, s32 y, int npolys, s32* timingcounter); u32 CalculateFogDensity(const GPU3D& gpu3d, u32 pixeladdr) const; - void ScanlineFinalPass(const GPU3D& gpu3d, s32 y, u8 rdbufferoffset, bool odd, s32 uhohzone); + void ScanlineFinalPass(const GPU3D& gpu3d, s32 y); void ClearBuffers(const GPU& gpu); + u16 BeginPushScanline(s32 y, s32 pixelstodraw); + void ReadScanline(s32 y); + void FinishPushScanline(s32 y, s32 pixelsremain); template void RenderPolygons(GPU& gpu, Polygon** polygons, int npolys); - voi PushScanline(s32 y, s32 pixelstodraw); void RenderThreadFunc(GPU& gpu); // counters for scanline rasterization timings s32 ScanlineTimeout; s32 RasterTiming; - s32 RasterTimingOdd; - s32 RasterTimingEven; enum { RenderStart = 0, ScanlineRead, - RenderFinalP2, + PushScanline, + PushScanlineP2, RenderFinal, RasterEvents_MAX, };