aboutsummaryrefslogtreecommitdiff
path: root/src/GPU3D.cpp
diff options
context:
space:
mode:
authorJesse Talavera-Greenberg <jesse@jesse.tg>2023-11-09 15:54:51 -0500
committerGitHub <noreply@github.com>2023-11-09 21:54:51 +0100
commit4558be0d8eb79d276c89392b9410e6edb649db95 (patch)
tree3e2b37e31b38337adec64c5391e57ddf45af5d23 /src/GPU3D.cpp
parent88072a02c523e26390af6bd726608b3e567f996f (diff)
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
Diffstat (limited to 'src/GPU3D.cpp')
-rw-r--r--src/GPU3D.cpp282
1 files changed, 52 insertions, 230 deletions
diff --git a/src/GPU3D.cpp b/src/GPU3D.cpp
index 55d6de7..80c5d46 100644
--- a/src/GPU3D.cpp
+++ b/src/GPU3D.cpp
@@ -138,158 +138,9 @@ const u8 CmdNumParams[256] =
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-typedef union
-{
- u64 _contents;
- struct
- {
- u32 Param;
- u8 Command;
- };
-
-} CmdFIFOEntry;
-
-FIFO<CmdFIFOEntry, 256> CmdFIFO;
-FIFO<CmdFIFOEntry, 4> CmdPIPE;
-
-FIFO<CmdFIFOEntry, 64> CmdStallQueue;
-
-u32 NumCommands, CurCommand, ParamCount, TotalParams;
-
-bool GeometryEnabled;
-bool RenderingEnabled;
-
-u32 DispCnt;
-u8 AlphaRefVal, AlphaRef;
-
-u16 ToonTable[32];
-u16 EdgeTable[8];
-
-u32 FogColor, FogOffset;
-u8 FogDensityTable[32];
-
-u32 ClearAttr1, ClearAttr2;
-
-u32 RenderDispCnt;
-u8 RenderAlphaRef;
-
-u16 RenderToonTable[32];
-u16 RenderEdgeTable[8];
-
-u32 RenderFogColor, RenderFogOffset, RenderFogShift;
-u8 RenderFogDensityTable[34];
-
-u32 RenderClearAttr1, RenderClearAttr2;
-
-bool RenderFrameIdentical;
-
-u16 RenderXPos;
-
-u32 ZeroDotWLimit;
-
-u32 GXStat;
-
-u32 ExecParams[32];
-u32 ExecParamCount;
-
-u64 Timestamp;
-s32 CycleCount;
-s32 VertexPipeline;
-s32 NormalPipeline;
-s32 PolygonPipeline;
-s32 VertexSlotCounter;
-u32 VertexSlotsFree;
-
-u32 NumPushPopCommands;
-u32 NumTestCommands;
-
-
-u32 MatrixMode;
-
-s32 ProjMatrix[16];
-s32 PosMatrix[16];
-s32 VecMatrix[16];
-s32 TexMatrix[16];
-
-s32 ClipMatrix[16];
-bool ClipMatrixDirty;
-
-u32 Viewport[6];
-
-s32 ProjMatrixStack[16];
-s32 PosMatrixStack[32][16];
-s32 VecMatrixStack[32][16];
-s32 TexMatrixStack[16];
-s32 ProjMatrixStackPointer;
-s32 PosMatrixStackPointer;
-s32 TexMatrixStackPointer;
-
void MatrixLoadIdentity(s32* m);
-void UpdateClipMatrix();
-
-
-u32 PolygonMode;
-s16 CurVertex[3];
-u8 VertexColor[3];
-s16 TexCoords[2];
-s16 RawTexCoords[2];
-s16 Normal[3];
-
-s16 LightDirection[4][3];
-u8 LightColor[4][3];
-u8 MatDiffuse[3];
-u8 MatAmbient[3];
-u8 MatSpecular[3];
-u8 MatEmission[3];
-
-bool UseShininessTable;
-u8 ShininessTable[128];
-
-u32 PolygonAttr;
-u32 CurPolygonAttr;
-u32 TexParam;
-u32 TexPalette;
-
-s32 PosTestResult[4];
-s16 VecTestResult[3];
-
-Vertex TempVertexBuffer[4];
-u32 VertexNum;
-u32 VertexNumInPoly;
-u32 NumConsecutivePolygons;
-Polygon* LastStripPolygon;
-u32 NumOpaquePolygons;
-
-Vertex VertexRAM[6144 * 2];
-Polygon PolygonRAM[2048 * 2];
-
-Vertex* CurVertexRAM;
-Polygon* CurPolygonRAM;
-u32 NumVertices, NumPolygons;
-u32 CurRAMBank;
-
-std::array<Polygon*,2048> RenderPolygonRAM;
-u32 RenderNumPolygons;
-
-u32 FlushRequest;
-u32 FlushAttributes;
-
-std::unique_ptr<GPU3D::Renderer3D> CurrentRenderer = {};
-
-bool AbortFrame;
-
-bool Init()
-{
- return true;
-}
-
-void DeInit()
-{
- CurrentRenderer = nullptr;
-}
-
-void ResetRenderingState()
+void GPU3D::ResetRenderingState() noexcept
{
RenderNumPolygons = 0;
@@ -308,7 +159,7 @@ void ResetRenderingState()
RenderClearAttr2 = 0x00007FFF;
}
-void Reset()
+void GPU3D::Reset() noexcept
{
CmdFIFO.Clear();
CmdPIPE.Clear();
@@ -389,7 +240,7 @@ void Reset()
AbortFrame = false;
}
-void DoSavestate(Savestate* file)
+void GPU3D::DoSavestate(Savestate* file) noexcept
{
file->Section("GP3D");
@@ -634,7 +485,7 @@ void DoSavestate(Savestate* file)
-void SetEnabled(bool geometry, bool rendering)
+void GPU3D::SetEnabled(bool geometry, bool rendering) noexcept
{
GeometryEnabled = geometry;
RenderingEnabled = rendering;
@@ -767,7 +618,7 @@ void MatrixTranslate(s32* m, s32* s)
m[15] += ((s64)s[0]*m[3] + (s64)s[1]*m[7] + (s64)s[2]*m[11]) >> 12;
}
-void UpdateClipMatrix()
+void GPU3D::UpdateClipMatrix() noexcept
{
if (!ClipMatrixDirty) return;
ClipMatrixDirty = false;
@@ -778,7 +629,7 @@ void UpdateClipMatrix()
-void AddCycles(s32 num)
+void GPU3D::AddCycles(s32 num) noexcept
{
CycleCount += num;
@@ -809,7 +660,7 @@ void AddCycles(s32 num)
}
}
-void NextVertexSlot()
+void GPU3D::NextVertexSlot() noexcept
{
s32 num = (9 - VertexSlotCounter) + 1;
@@ -852,7 +703,7 @@ void NextVertexSlot()
}
}
-void StallPolygonPipeline(s32 delay, s32 nonstalldelay)
+void GPU3D::StallPolygonPipeline(s32 delay, s32 nonstalldelay) noexcept
{
if (PolygonPipeline > 0)
{
@@ -907,7 +758,7 @@ void ClipSegment(Vertex* outbuf, Vertex* vin, Vertex* vout)
}
template<int comp, bool attribs>
-int ClipAgainstPlane(Vertex* vertices, int nverts, int clipstart)
+int ClipAgainstPlane(const GPU3D& gpu, Vertex* vertices, int nverts, int clipstart)
{
Vertex temp[10];
int prev, next;
@@ -927,7 +778,7 @@ int ClipAgainstPlane(Vertex* vertices, int nverts, int clipstart)
Vertex vtx = vertices[i];
if (vtx.Position[comp] > vtx.Position[3])
{
- if ((comp == 2) && (!(CurPolygonAttr & (1<<12)))) return 0;
+ if ((comp == 2) && (!(gpu.CurPolygonAttr & (1<<12)))) return 0;
Vertex* vprev = &vertices[prev];
if (vprev->Position[comp] <= vprev->Position[3])
@@ -988,7 +839,7 @@ int ClipAgainstPlane(Vertex* vertices, int nverts, int clipstart)
}
template<bool attribs>
-int ClipPolygon(Vertex* vertices, int nverts, int clipstart)
+int ClipPolygon(GPU3D& gpu, Vertex* vertices, int nverts, int clipstart)
{
// clip.
// for each vertex:
@@ -1001,13 +852,13 @@ int ClipPolygon(Vertex* vertices, int nverts, int clipstart)
// clipping seems to process the Y plane before the X plane.
// Z clipping
- nverts = ClipAgainstPlane<2, attribs>(vertices, nverts, clipstart);
+ nverts = ClipAgainstPlane<2, attribs>(gpu, vertices, nverts, clipstart);
// Y clipping
- nverts = ClipAgainstPlane<1, attribs>(vertices, nverts, clipstart);
+ nverts = ClipAgainstPlane<1, attribs>(gpu, vertices, nverts, clipstart);
// X clipping
- nverts = ClipAgainstPlane<0, attribs>(vertices, nverts, clipstart);
+ nverts = ClipAgainstPlane<0, attribs>(gpu, vertices, nverts, clipstart);
return nverts;
}
@@ -1020,7 +871,7 @@ bool ClipCoordsEqual(Vertex* a, Vertex* b)
a->Position[3] == b->Position[3];
}
-void SubmitPolygon()
+void GPU3D::SubmitPolygon() noexcept
{
Vertex clippedvertices[10];
Vertex* reusedvertices[2];
@@ -1153,7 +1004,7 @@ void SubmitPolygon()
// clipping
- nverts = ClipPolygon<true>(clippedvertices, nverts, clipstart);
+ nverts = ClipPolygon<true>(*this, clippedvertices, nverts, clipstart);
if (nverts == 0)
{
LastStripPolygon = NULL;
@@ -1425,7 +1276,7 @@ void SubmitPolygon()
LastStripPolygon = NULL;
}
-void SubmitVertex()
+void GPU3D::SubmitVertex() noexcept
{
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
Vertex* vertextrans = &TempVertexBuffer[VertexNumInPoly];
@@ -1523,7 +1374,7 @@ void SubmitVertex()
AddCycles(3);
}
-void CalculateLighting()
+void GPU3D::CalculateLighting() noexcept
{
if ((TexParam >> 30) == 2)
{
@@ -1598,7 +1449,7 @@ void CalculateLighting()
}
-void BoxTest(u32* params)
+void GPU3D::BoxTest(u32* params) noexcept
{
Vertex cube[8];
Vertex face[10];
@@ -1642,7 +1493,7 @@ void BoxTest(u32* params)
// front face (-Z)
face[0] = cube[0]; face[1] = cube[1]; face[2] = cube[2]; face[3] = cube[3];
- res = ClipPolygon<false>(face, 4, 0);
+ res = ClipPolygon<false>(*this, face, 4, 0);
if (res > 0)
{
GXStat |= (1<<1);
@@ -1651,7 +1502,7 @@ void BoxTest(u32* params)
// back face (+Z)
face[0] = cube[4]; face[1] = cube[5]; face[2] = cube[6]; face[3] = cube[7];
- res = ClipPolygon<false>(face, 4, 0);
+ res = ClipPolygon<false>(*this, face, 4, 0);
if (res > 0)
{
GXStat |= (1<<1);
@@ -1660,7 +1511,7 @@ void BoxTest(u32* params)
// left face (-X)
face[0] = cube[0]; face[1] = cube[3]; face[2] = cube[4]; face[3] = cube[5];
- res = ClipPolygon<false>(face, 4, 0);
+ res = ClipPolygon<false>(*this, face, 4, 0);
if (res > 0)
{
GXStat |= (1<<1);
@@ -1669,7 +1520,7 @@ void BoxTest(u32* params)
// right face (+X)
face[0] = cube[1]; face[1] = cube[2]; face[2] = cube[7]; face[3] = cube[6];
- res = ClipPolygon<false>(face, 4, 0);
+ res = ClipPolygon<false>(*this, face, 4, 0);
if (res > 0)
{
GXStat |= (1<<1);
@@ -1678,7 +1529,7 @@ void BoxTest(u32* params)
// bottom face (-Y)
face[0] = cube[0]; face[1] = cube[1]; face[2] = cube[6]; face[3] = cube[5];
- res = ClipPolygon<false>(face, 4, 0);
+ res = ClipPolygon<false>(*this, face, 4, 0);
if (res > 0)
{
GXStat |= (1<<1);
@@ -1687,7 +1538,7 @@ void BoxTest(u32* params)
// top face (+Y)
face[0] = cube[2]; face[1] = cube[3]; face[2] = cube[4]; face[3] = cube[7];
- res = ClipPolygon<false>(face, 4, 0);
+ res = ClipPolygon<false>(*this, face, 4, 0);
if (res > 0)
{
GXStat |= (1<<1);
@@ -1695,7 +1546,7 @@ void BoxTest(u32* params)
}
}
-void PosTest()
+void GPU3D::PosTest() noexcept
{
s64 vertex[4] = {(s64)CurVertex[0], (s64)CurVertex[1], (s64)CurVertex[2], 0x1000};
@@ -1708,7 +1559,7 @@ void PosTest()
AddCycles(5);
}
-void VecTest(u32 param)
+void GPU3D::VecTest(u32 param) noexcept
{
// TODO: maybe it overwrites the normal registers, too
@@ -1731,7 +1582,7 @@ void VecTest(u32 param)
-void CmdFIFOWrite(CmdFIFOEntry& entry)
+void GPU3D::CmdFIFOWrite(CmdFIFOEntry& entry) noexcept
{
if (CmdFIFO.IsEmpty() && !CmdPIPE.IsFull())
{
@@ -1767,7 +1618,7 @@ void CmdFIFOWrite(CmdFIFOEntry& entry)
}
}
-CmdFIFOEntry CmdFIFORead()
+GPU3D::CmdFIFOEntry GPU3D::CmdFIFORead() noexcept
{
CmdFIFOEntry ret = CmdPIPE.Read();
@@ -1800,39 +1651,7 @@ CmdFIFOEntry CmdFIFORead()
return ret;
}
-inline void VertexPipelineSubmitCmd()
-{
- // vertex commands 0x24, 0x25, 0x26, 0x27, 0x28
- if (!(VertexSlotsFree & 0x1)) NextVertexSlot();
- else AddCycles(1);
- NormalPipeline = 0;
-}
-
-inline void VertexPipelineCmdDelayed6()
-{
- // commands 0x20, 0x30, 0x31, 0x72 that can run 6 cycles after a vertex
- if (VertexPipeline > 2) AddCycles((VertexPipeline - 2) + 1);
- else AddCycles(NormalPipeline + 1);
- NormalPipeline = 0;
-}
-
-inline void VertexPipelineCmdDelayed8()
-{
- // commands 0x29, 0x2A, 0x2B, 0x33, 0x34, 0x41, 0x60, 0x71 that can run 8 cycles after a vertex
- if (VertexPipeline > 0) AddCycles(VertexPipeline + 1);
- else AddCycles(NormalPipeline + 1);
- NormalPipeline = 0;
-}
-
-inline void VertexPipelineCmdDelayed4()
-{
- // all other commands can run 4 cycles after a vertex
- // no need to do much here since that is the minimum
- AddCycles(NormalPipeline + 1);
- NormalPipeline = 0;
-}
-
-void ExecuteCommand()
+void GPU3D::ExecuteCommand() noexcept
{
CmdFIFOEntry entry = CmdFIFORead();
@@ -2430,13 +2249,13 @@ void ExecuteCommand()
}
}
-s32 CyclesToRunFor()
+s32 GPU3D::CyclesToRunFor() const noexcept
{
if (CycleCount < 0) return 0;
return CycleCount;
}
-void FinishWork(s32 cycles)
+void GPU3D::FinishWork(s32 cycles) noexcept
{
AddCycles(cycles);
if (NormalPipeline)
@@ -2450,7 +2269,7 @@ void FinishWork(s32 cycles)
GXStat &= ~(1<<27);
}
-void Run()
+void GPU3D::Run() noexcept
{
if (!GeometryEnabled || FlushRequest ||
(CmdPIPE.IsEmpty() && !(GXStat & (1<<27))))
@@ -2485,7 +2304,7 @@ void Run()
}
-void CheckFIFOIRQ()
+void GPU3D::CheckFIFOIRQ() noexcept
{
bool irq = false;
switch (GXStat >> 30)
@@ -2498,18 +2317,18 @@ void CheckFIFOIRQ()
else NDS::ClearIRQ(0, NDS::IRQ_GXFIFO);
}
-void CheckFIFODMA()
+void GPU3D::CheckFIFODMA() noexcept
{
if (CmdFIFO.Level() < 128)
NDS::CheckDMAs(0, 0x07);
}
-void VCount144()
+void GPU3D::VCount144() noexcept
{
CurrentRenderer->VCount144();
}
-void RestartFrame()
+void GPU3D::RestartFrame() noexcept
{
CurrentRenderer->RestartFrame();
}
@@ -2527,7 +2346,7 @@ bool YSort(Polygon* a, Polygon* b)
return a->SortKey < b->SortKey;
}
-void VBlank()
+void GPU3D::VBlank() noexcept
{
if (GeometryEnabled)
{
@@ -2604,21 +2423,20 @@ void VBlank()
}
}
-void VCount215()
+void GPU3D::VCount215() noexcept
{
CurrentRenderer->RenderFrame();
}
-void SetRenderXPos(u16 xpos)
+void GPU3D::SetRenderXPos(u16 xpos) noexcept
{
if (!RenderingEnabled) return;
RenderXPos = xpos & 0x01FF;
}
-u32 ScrolledLine[256];
-u32* GetLine(int line)
+u32* GPU3D::GetLine(int line) noexcept
{
if (!AbortFrame)
{
@@ -2653,8 +2471,12 @@ u32* GetLine(int line)
return ScrolledLine;
}
+bool GPU3D::IsRendererAccelerated() const noexcept
+{
+ return CurrentRenderer && CurrentRenderer->Accelerated;
+}
-void WriteToGXFIFO(u32 val)
+void GPU3D::WriteToGXFIFO(u32 val) noexcept
{
if (NumCommands == 0)
{
@@ -2693,7 +2515,7 @@ void WriteToGXFIFO(u32 val)
}
-u8 Read8(u32 addr)
+u8 GPU3D::Read8(u32 addr) noexcept
{
switch (addr)
{
@@ -2732,7 +2554,7 @@ u8 Read8(u32 addr)
return 0;
}
-u16 Read16(u32 addr)
+u16 GPU3D::Read16(u32 addr) noexcept
{
switch (addr)
{
@@ -2776,7 +2598,7 @@ u16 Read16(u32 addr)
return 0;
}
-u32 Read32(u32 addr)
+u32 GPU3D::Read32(u32 addr) noexcept
{
switch (addr)
{
@@ -2829,7 +2651,7 @@ u32 Read32(u32 addr)
return 0;
}
-void Write8(u32 addr, u8 val)
+void GPU3D::Write8(u32 addr, u8 val) noexcept
{
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
@@ -2879,7 +2701,7 @@ void Write8(u32 addr, u8 val)
Log(LogLevel::Debug, "unknown GPU3D write8 %08X %02X\n", addr, val);
}
-void Write16(u32 addr, u16 val)
+void GPU3D::Write16(u32 addr, u16 val) noexcept
{
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;
@@ -2966,7 +2788,7 @@ void Write16(u32 addr, u16 val)
Log(LogLevel::Debug, "unknown GPU3D write16 %08X %04X\n", addr, val);
}
-void Write32(u32 addr, u32 val)
+void GPU3D::Write32(u32 addr, u32 val) noexcept
{
if (!RenderingEnabled && addr >= 0x04000320 && addr < 0x04000400) return;
if (!GeometryEnabled && addr >= 0x04000400 && addr < 0x04000700) return;