mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-24 14:49:53 -06:00
Refactor the GPU to be object-oriented (#1873)
* Refactor GPU3D to be an object - Who has two thumbs and is the sworn enemy of global state? This guy! * Refactor GPU itself to be an object - Wow, it's used in a lot of places - Also introduce a new `Melon` namespace for a few classes - I expect other classes will be moved into `Melon` over time * Change signature of Renderer3D::SetRenderSettings - Make it noexcept, and its argument const * Remove some stray whitespace
This commit is contained in:

committed by
GitHub

parent
88072a02c5
commit
4558be0d8e
@ -72,8 +72,8 @@ void SoftRenderer::SetupRenderThread()
|
||||
}
|
||||
|
||||
|
||||
SoftRenderer::SoftRenderer() noexcept
|
||||
: Renderer3D(false)
|
||||
SoftRenderer::SoftRenderer(Melon::GPU& gpu) noexcept
|
||||
: Renderer3D(false), GPU(gpu)
|
||||
{
|
||||
Sema_RenderStart = Platform::Semaphore_Create();
|
||||
Sema_RenderDone = Platform::Semaphore_Create();
|
||||
@ -105,7 +105,7 @@ void SoftRenderer::Reset()
|
||||
SetupRenderThread();
|
||||
}
|
||||
|
||||
void SoftRenderer::SetRenderSettings(GPU::RenderSettings& settings)
|
||||
void SoftRenderer::SetRenderSettings(const Melon::RenderSettings& settings) noexcept
|
||||
{
|
||||
Threaded = settings.Soft_Threaded;
|
||||
SetupRenderThread();
|
||||
@ -387,7 +387,7 @@ bool DepthTest_LessThan_FrontFacing(s32 dstz, s32 z, u32 dstattr)
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha)
|
||||
u32 SoftRenderer::AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha) noexcept
|
||||
{
|
||||
u32 dstalpha = dstcolor >> 24;
|
||||
|
||||
@ -398,7 +398,7 @@ u32 AlphaBlend(u32 srccolor, u32 dstcolor, u32 alpha)
|
||||
u32 srcG = (srccolor >> 8) & 0x3F;
|
||||
u32 srcB = (srccolor >> 16) & 0x3F;
|
||||
|
||||
if (RenderDispCnt & (1<<3))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<3))
|
||||
{
|
||||
u32 dstR = dstcolor & 0x3F;
|
||||
u32 dstG = (dstcolor >> 8) & 0x3F;
|
||||
@ -427,7 +427,7 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
||||
|
||||
if (blendmode == 2)
|
||||
{
|
||||
if (RenderDispCnt & (1<<1))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<1))
|
||||
{
|
||||
// highlight mode: color is calculated normally
|
||||
// except all vertex color components are set
|
||||
@ -441,7 +441,7 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
||||
{
|
||||
// toon mode: vertex color is replaced by toon color
|
||||
|
||||
u16 tooncolor = RenderToonTable[vr >> 1];
|
||||
u16 tooncolor = GPU.GPU3D.RenderToonTable[vr >> 1];
|
||||
|
||||
vr = (tooncolor << 1) & 0x3E; if (vr) vr++;
|
||||
vg = (tooncolor >> 4) & 0x3E; if (vg) vg++;
|
||||
@ -449,7 +449,7 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
||||
}
|
||||
}
|
||||
|
||||
if ((RenderDispCnt & (1<<0)) && (((polygon->TexParam >> 26) & 0x7) != 0))
|
||||
if ((GPU.GPU3D.RenderDispCnt & (1<<0)) && (((polygon->TexParam >> 26) & 0x7) != 0))
|
||||
{
|
||||
u8 tr, tg, tb;
|
||||
|
||||
@ -502,9 +502,9 @@ u32 SoftRenderer::RenderPixel(Polygon* polygon, u8 vr, u8 vg, u8 vb, s16 s, s16
|
||||
a = polyalpha;
|
||||
}
|
||||
|
||||
if ((blendmode == 2) && (RenderDispCnt & (1<<1)))
|
||||
if ((blendmode == 2) && (GPU.GPU3D.RenderDispCnt & (1<<1)))
|
||||
{
|
||||
u16 tooncolor = RenderToonTable[vr >> 1];
|
||||
u16 tooncolor = GPU.GPU3D.RenderToonTable[vr >> 1];
|
||||
|
||||
vr = (tooncolor << 1) & 0x3E; if (vr) vr++;
|
||||
vg = (tooncolor >> 4) & 0x3E; if (vg) vg++;
|
||||
@ -748,7 +748,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
|
||||
std::swap(zl, zr);
|
||||
|
||||
// CHECKME: edge fill rules for swapped opaque shadow mask polygons
|
||||
if ((polyalpha < 31) || (RenderDispCnt & (3<<4)))
|
||||
if ((polyalpha < 31) || (GPU.GPU3D.RenderDispCnt & (3<<4)))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
@ -776,7 +776,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
|
||||
rp->SlopeR.EdgeParams<false>(&r_edgelen, &r_edgecov);
|
||||
|
||||
// CHECKME: edge fill rules for unswapped opaque shadow mask polygons
|
||||
if ((polyalpha < 31) || (RenderDispCnt & (3<<4)))
|
||||
if ((polyalpha < 31) || (GPU.GPU3D.RenderDispCnt & (3<<4)))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
@ -797,7 +797,7 @@ void SoftRenderer::RenderShadowMaskScanline(RendererPolygon* rp, s32 y)
|
||||
// similarly, we can perform alpha test early (checkme)
|
||||
|
||||
if (wireframe) polyalpha = 31;
|
||||
if (polyalpha <= RenderAlphaRef) return;
|
||||
if (polyalpha <= GPU.GPU3D.RenderAlphaRef) return;
|
||||
|
||||
// in wireframe mode, there are special rules for equal Z (TODO)
|
||||
|
||||
@ -982,7 +982,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
||||
// * the bottom-most pixel of negative x-major slopes are filled if they are next to a flat bottom edge
|
||||
// edges are always filled if antialiasing/edgemarking are enabled or if the pixels are translucent
|
||||
// checkme: do swapped line polygons exist?
|
||||
if ((polyalpha < 31) || wireframe || (RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
if ((polyalpha < 31) || wireframe || (GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
@ -1016,7 +1016,7 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
||||
// * the bottom-most pixel of negative x-major slopes are filled if they are next to a flat bottom edge
|
||||
// * edges are filled if both sides are identical and fully overlapping
|
||||
// edges are always filled if antialiasing/edgemarking are enabled or if the pixels are translucent
|
||||
if ((polyalpha < 31) || wireframe || (RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
if ((polyalpha < 31) || wireframe || (GPU.GPU3D.RenderDispCnt & ((1<<4)|(1<<5))))
|
||||
{
|
||||
l_filledge = true;
|
||||
r_filledge = true;
|
||||
@ -1119,13 +1119,13 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
||||
u8 alpha = color >> 24;
|
||||
|
||||
// alpha test
|
||||
if (alpha <= RenderAlphaRef) continue;
|
||||
if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
|
||||
|
||||
if (alpha == 31)
|
||||
{
|
||||
u32 attr = polyattr | edge;
|
||||
|
||||
if (RenderDispCnt & (1<<4))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<4))
|
||||
{
|
||||
// anti-aliasing: all edges are rendered
|
||||
|
||||
@ -1215,13 +1215,13 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
||||
u8 alpha = color >> 24;
|
||||
|
||||
// alpha test
|
||||
if (alpha <= RenderAlphaRef) continue;
|
||||
if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
|
||||
|
||||
if (alpha == 31)
|
||||
{
|
||||
u32 attr = polyattr | edge;
|
||||
|
||||
if ((RenderDispCnt & (1<<4)) && (attr & 0xF))
|
||||
if ((GPU.GPU3D.RenderDispCnt & (1<<4)) && (attr & 0xF))
|
||||
{
|
||||
// anti-aliasing: all edges are rendered
|
||||
|
||||
@ -1307,13 +1307,13 @@ void SoftRenderer::RenderPolygonScanline(RendererPolygon* rp, s32 y)
|
||||
u8 alpha = color >> 24;
|
||||
|
||||
// alpha test
|
||||
if (alpha <= RenderAlphaRef) continue;
|
||||
if (alpha <= GPU.GPU3D.RenderAlphaRef) continue;
|
||||
|
||||
if (alpha == 31)
|
||||
{
|
||||
u32 attr = polyattr | edge;
|
||||
|
||||
if (RenderDispCnt & (1<<4))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<4))
|
||||
{
|
||||
// anti-aliasing: all edges are rendered
|
||||
|
||||
@ -1377,7 +1377,7 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr)
|
||||
u32 z = DepthBuffer[pixeladdr];
|
||||
u32 densityid, densityfrac;
|
||||
|
||||
if (z < RenderFogOffset)
|
||||
if (z < GPU.GPU3D.RenderFogOffset)
|
||||
{
|
||||
densityid = 0;
|
||||
densityfrac = 0;
|
||||
@ -1389,8 +1389,8 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr)
|
||||
// on hardware, the final value can overflow the 32-bit range with a shift big enough,
|
||||
// causing fog to 'wrap around' and accidentally apply to larger Z ranges
|
||||
|
||||
z -= RenderFogOffset;
|
||||
z = (z >> 2) << RenderFogShift;
|
||||
z -= GPU.GPU3D.RenderFogOffset;
|
||||
z = (z >> 2) << GPU.GPU3D.RenderFogShift;
|
||||
|
||||
densityid = z >> 17;
|
||||
if (densityid >= 32)
|
||||
@ -1404,8 +1404,8 @@ u32 SoftRenderer::CalculateFogDensity(u32 pixeladdr)
|
||||
|
||||
// checkme (may be too precise?)
|
||||
u32 density =
|
||||
((RenderFogDensityTable[densityid] * (0x20000-densityfrac)) +
|
||||
(RenderFogDensityTable[densityid+1] * densityfrac)) >> 17;
|
||||
((GPU.GPU3D.RenderFogDensityTable[densityid] * (0x20000-densityfrac)) +
|
||||
(GPU.GPU3D.RenderFogDensityTable[densityid+1] * densityfrac)) >> 17;
|
||||
if (density >= 127) density = 128;
|
||||
|
||||
return density;
|
||||
@ -1417,7 +1417,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
||||
// clearing all polygon fog flags if the master flag isn't set?
|
||||
// merging all final pass loops into one?
|
||||
|
||||
if (RenderDispCnt & (1<<5))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<5))
|
||||
{
|
||||
// edge marking
|
||||
// only applied to topmost pixels
|
||||
@ -1437,7 +1437,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
||||
((polyid != (AttrBuffer[pixeladdr-ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr-ScanlineWidth])) ||
|
||||
((polyid != (AttrBuffer[pixeladdr+ScanlineWidth] >> 24)) && (z < DepthBuffer[pixeladdr+ScanlineWidth])))
|
||||
{
|
||||
u16 edgecolor = RenderEdgeTable[polyid >> 3];
|
||||
u16 edgecolor = GPU.GPU3D.RenderEdgeTable[polyid >> 3];
|
||||
u32 edgeR = (edgecolor << 1) & 0x3E; if (edgeR) edgeR++;
|
||||
u32 edgeG = (edgecolor >> 4) & 0x3E; if (edgeG) edgeG++;
|
||||
u32 edgeB = (edgecolor >> 9) & 0x3E; if (edgeB) edgeB++;
|
||||
@ -1450,7 +1450,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
||||
}
|
||||
}
|
||||
|
||||
if (RenderDispCnt & (1<<7))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<7))
|
||||
{
|
||||
// fog
|
||||
|
||||
@ -1463,12 +1463,12 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
||||
|
||||
// TODO: check the 'fog alpha glitch with small Z' GBAtek talks about
|
||||
|
||||
bool fogcolor = !(RenderDispCnt & (1<<6));
|
||||
bool fogcolor = !(GPU.GPU3D.RenderDispCnt & (1<<6));
|
||||
|
||||
u32 fogR = (RenderFogColor << 1) & 0x3E; if (fogR) fogR++;
|
||||
u32 fogG = (RenderFogColor >> 4) & 0x3E; if (fogG) fogG++;
|
||||
u32 fogB = (RenderFogColor >> 9) & 0x3E; if (fogB) fogB++;
|
||||
u32 fogA = (RenderFogColor >> 16) & 0x1F;
|
||||
u32 fogR = (GPU.GPU3D.RenderFogColor << 1) & 0x3E; if (fogR) fogR++;
|
||||
u32 fogG = (GPU.GPU3D.RenderFogColor >> 4) & 0x3E; if (fogG) fogG++;
|
||||
u32 fogB = (GPU.GPU3D.RenderFogColor >> 9) & 0x3E; if (fogB) fogB++;
|
||||
u32 fogA = (GPU.GPU3D.RenderFogColor >> 16) & 0x1F;
|
||||
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
@ -1528,7 +1528,7 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
||||
}
|
||||
}
|
||||
|
||||
if (RenderDispCnt & (1<<4))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<4))
|
||||
{
|
||||
// anti-aliasing
|
||||
|
||||
@ -1583,8 +1583,8 @@ void SoftRenderer::ScanlineFinalPass(s32 y)
|
||||
|
||||
void SoftRenderer::ClearBuffers()
|
||||
{
|
||||
u32 clearz = ((RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||
u32 polyid = RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
|
||||
u32 clearz = ((GPU.GPU3D.RenderClearAttr2 & 0x7FFF) * 0x200) + 0x1FF;
|
||||
u32 polyid = GPU.GPU3D.RenderClearAttr1 & 0x3F000000; // this sets the opaque polygonID
|
||||
|
||||
// fill screen borders for edge marking
|
||||
|
||||
@ -1614,10 +1614,10 @@ void SoftRenderer::ClearBuffers()
|
||||
|
||||
// clear the screen
|
||||
|
||||
if (RenderDispCnt & (1<<14))
|
||||
if (GPU.GPU3D.RenderDispCnt & (1<<14))
|
||||
{
|
||||
u8 xoff = (RenderClearAttr2 >> 16) & 0xFF;
|
||||
u8 yoff = (RenderClearAttr2 >> 24) & 0xFF;
|
||||
u8 xoff = (GPU.GPU3D.RenderClearAttr2 >> 16) & 0xFF;
|
||||
u8 yoff = (GPU.GPU3D.RenderClearAttr2 >> 24) & 0xFF;
|
||||
|
||||
for (int y = 0; y < ScanlineWidth*192; y+=ScanlineWidth)
|
||||
{
|
||||
@ -1649,13 +1649,13 @@ void SoftRenderer::ClearBuffers()
|
||||
else
|
||||
{
|
||||
// TODO: confirm color conversion
|
||||
u32 r = (RenderClearAttr1 << 1) & 0x3E; if (r) r++;
|
||||
u32 g = (RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
|
||||
u32 b = (RenderClearAttr1 >> 9) & 0x3E; if (b) b++;
|
||||
u32 a = (RenderClearAttr1 >> 16) & 0x1F;
|
||||
u32 r = (GPU.GPU3D.RenderClearAttr1 << 1) & 0x3E; if (r) r++;
|
||||
u32 g = (GPU.GPU3D.RenderClearAttr1 >> 4) & 0x3E; if (g) g++;
|
||||
u32 b = (GPU.GPU3D.RenderClearAttr1 >> 9) & 0x3E; if (b) b++;
|
||||
u32 a = (GPU.GPU3D.RenderClearAttr1 >> 16) & 0x1F;
|
||||
u32 color = r | (g << 8) | (b << 16) | (a << 24);
|
||||
|
||||
polyid |= (RenderClearAttr1 & 0x8000);
|
||||
polyid |= (GPU.GPU3D.RenderClearAttr1 & 0x8000);
|
||||
|
||||
for (int y = 0; y < ScanlineWidth*192; y+=ScanlineWidth)
|
||||
{
|
||||
@ -1698,19 +1698,19 @@ void SoftRenderer::RenderPolygons(bool threaded, Polygon** polygons, int npolys)
|
||||
|
||||
void SoftRenderer::VCount144()
|
||||
{
|
||||
if (RenderThreadRunning.load(std::memory_order_relaxed) && !GPU3D::AbortFrame)
|
||||
if (RenderThreadRunning.load(std::memory_order_relaxed) && !GPU.GPU3D.AbortFrame)
|
||||
Platform::Semaphore_Wait(Sema_RenderDone);
|
||||
}
|
||||
|
||||
void SoftRenderer::RenderFrame()
|
||||
{
|
||||
auto textureDirty = GPU::VRAMDirty_Texture.DeriveState(GPU::VRAMMap_Texture);
|
||||
auto texPalDirty = GPU::VRAMDirty_TexPal.DeriveState(GPU::VRAMMap_TexPal);
|
||||
auto textureDirty = GPU.VRAMDirty_Texture.DeriveState(GPU.VRAMMap_Texture, GPU);
|
||||
auto texPalDirty = GPU.VRAMDirty_TexPal.DeriveState(GPU.VRAMMap_TexPal, GPU);
|
||||
|
||||
bool textureChanged = GPU::MakeVRAMFlat_TextureCoherent(textureDirty);
|
||||
bool texPalChanged = GPU::MakeVRAMFlat_TexPalCoherent(texPalDirty);
|
||||
bool textureChanged = GPU.MakeVRAMFlat_TextureCoherent(textureDirty);
|
||||
bool texPalChanged = GPU.MakeVRAMFlat_TexPalCoherent(texPalDirty);
|
||||
|
||||
FrameIdentical = !(textureChanged || texPalChanged) && RenderFrameIdentical;
|
||||
FrameIdentical = !(textureChanged || texPalChanged) && GPU.GPU3D.RenderFrameIdentical;
|
||||
|
||||
if (RenderThreadRunning.load(std::memory_order_relaxed))
|
||||
{
|
||||
@ -1719,7 +1719,7 @@ void SoftRenderer::RenderFrame()
|
||||
else if (!FrameIdentical)
|
||||
{
|
||||
ClearBuffers();
|
||||
RenderPolygons(false, &RenderPolygonRAM[0], RenderNumPolygons);
|
||||
RenderPolygons(false, &GPU.GPU3D.RenderPolygonRAM[0], GPU.GPU3D.RenderNumPolygons);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1743,7 +1743,7 @@ void SoftRenderer::RenderThreadFunc()
|
||||
else
|
||||
{
|
||||
ClearBuffers();
|
||||
RenderPolygons(true, &RenderPolygonRAM[0], RenderNumPolygons);
|
||||
RenderPolygons(true, &GPU.GPU3D.RenderPolygonRAM[0], GPU.GPU3D.RenderNumPolygons);
|
||||
}
|
||||
|
||||
Platform::Semaphore_Post(Sema_RenderDone);
|
||||
|
Reference in New Issue
Block a user