mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2024-11-14 13:27:41 -07:00
partially rendering
This commit is contained in:
parent
78da2846e6
commit
bf26b6817d
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
@ -149,22 +138,18 @@ u32 SoftRenderer::DoTimingsPixels(s32 pixels, bool odd)
|
||||
|
||||
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:
|
||||
|
||||
if (y > 2)
|
||||
rasterevents[PushScanline] = rasterevents[RenderFinal] + RastDelay;
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -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 <bool threaded> 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,
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user