melonDS/src/GPU3D.h

367 lines
9.0 KiB
C
Raw Normal View History

/*
2024-06-15 15:01:19 +00:00
Copyright 2016-2024 melonDS team
This file is part of melonDS.
melonDS is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at your option)
any later version.
melonDS is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with melonDS. If not, see http://www.gnu.org/licenses/.
*/
#ifndef GPU3D_H
#define GPU3D_H
#include <array>
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
#include <memory>
2018-10-18 00:31:01 +00:00
#include "Savestate.h"
#include "FIFO.h"
namespace melonDS
{
Clean up the 3D renderer for enhanced flexibility (#1895) * Give `GPU2D::Unit` a virtual destructor - Undefined behavior avoided! * Add an `array2d` alias * Move various parts of `GPU2D::SoftRenderer` to `constexpr` - `SoftRenderer::MosaicTable` is now initialized at compile-time - Most of the `SoftRenderer::Color*` functions are now `constexpr` - The aforementioned functions are used with a constant value in at least one place, so they'll be at least partially computed at compile-time * Generalize `GLRenderer::PrepareCaptureFrame` - Declare it in the base `Renderer3D` class, but make it empty * Remove unneeded `virtual` specifiers * Store `Framebuffer`'s memory in `unique_ptr`s - Reduce the risk of leaks this way * Clean up how `GLCompositor` is initialized - Return it as an `std::optional` instead of a `std::unique_ptr` - Make `GLCompositor` movable - Replace `GLCompositor`'s plain arrays with `std::array` to simplify moving * Pass `GPU` to `GLCompositor`'s important functions instead of passing it to the constructor * Move `GLCompositor` to be a field within `GLRenderer` - Some methods were moved up and made `virtual` * Fix some linker errors * Set the renderer in the frontend * Remove unneeded `virtual` specifiers * Remove `RenderSettings` in favor of just exposing the relevant member variables * Update the frontend to accommodate the core changes * Add `constexpr` and `const` to places in the interpolator * Qualify references to `size_t` * Construct the `optional` directly instead of using `make_optional` - It makes the Linux build choke - I think it's because `GLCompositor`'s constructor is `private`
2023-11-29 14:23:11 +00:00
class GPU;
2021-01-02 10:38:06 +00:00
struct Vertex
{
s32 Position[4];
s32 Color[3];
2017-02-27 23:50:54 +00:00
s16 TexCoords[2];
bool Clipped;
// final vertex attributes.
// allows them to be reused in polygon strips.
2017-04-21 20:40:15 +00:00
s32 FinalPosition[2];
s32 FinalColor[3];
// hi-res position (4-bit fractional part)
// TODO maybe: hi-res color? (that survives clipping)
s32 HiresPosition[2];
Protect savestates while the threaded software renderer is running (#1864) * First crack at ensuring the render thread doesn't touch GPU state while it's being serialized * Get rid of the semaphore wait * Add some extra fields into GPU3D's serialization * Oops, TempVertexBuffer is already serialized * Move vertex serialization into its own method * Lock the GPU3D state when rendering on the render thread or serializing it * Revert "Lock the GPU3D state when rendering on the render thread or serializing it" This reverts commit 2f49a551c13934b9dc815bbda67a45098f0482a7. * Add comments that describe the synchronization within GPU3D_Soft - I need to understand it before I can solve my actual problem - Now I do * Revert "Revert "Lock the GPU3D state when rendering on the render thread or serializing it"" This reverts commit 1977566a6d8671d72bd94ba4ebf832c3bf08933a. * Let's try locking the GPU3D state throughout NDS::RunFrame - Just to see what happens * Slim down the lock's scope * Narrow the lock's scope some more * Remove the lock entirely * Try protecting the GPU3D state with just a mutex - I'll clean this up once I know it works * Remove a duplicate method definition * Add a missing `noexcept` specifier * Remove an unused function * Cut some non-hardware state from `GPU3D`'s savestate * Assume that the next frame after loading a savestate won't be identical * Actually, it _is_ worth it * Don't serialize the clip matrix - It's recalculated anyway * Serialize `RenderPolygonRAM` as an array of indexes * Clean up some comments - I liked the dialogue style, but oh well * Try restarting the render thread instead of using the lock - Let's see what happens * Put the lock back * Fix some polygon and vertex indexes being saved incorrectly - Taking the difference between two pointers results in the number of elements, not the number of bytes * Remove `SoftRenderer::StateBusy` since it turns out we don't need it - The real synchronization was the friends we made along the way
2024-01-07 22:39:43 +00:00
void DoSavestate(Savestate* file) noexcept;
2021-01-02 10:38:06 +00:00
};
2021-01-02 10:38:06 +00:00
struct Polygon
{
Vertex* Vertices[10];
u32 NumVertices;
2017-04-21 20:40:15 +00:00
s32 FinalZ[10];
s32 FinalW[10];
bool WBuffer;
2017-04-21 20:40:15 +00:00
u32 Attr;
2017-02-27 23:52:17 +00:00
u32 TexParam;
u32 TexPalette;
bool Degenerate;
bool FacingView;
2017-03-15 14:53:36 +00:00
bool Translucent;
bool IsShadowMask;
bool IsShadow;
int Type; // 0=regular 1=line
u32 VTop, VBottom; // vertex indices
s32 YTop, YBottom; // Y coords
s32 XTop, XBottom; // associated X coords
2017-07-05 16:38:10 +00:00
u32 SortKey;
Protect savestates while the threaded software renderer is running (#1864) * First crack at ensuring the render thread doesn't touch GPU state while it's being serialized * Get rid of the semaphore wait * Add some extra fields into GPU3D's serialization * Oops, TempVertexBuffer is already serialized * Move vertex serialization into its own method * Lock the GPU3D state when rendering on the render thread or serializing it * Revert "Lock the GPU3D state when rendering on the render thread or serializing it" This reverts commit 2f49a551c13934b9dc815bbda67a45098f0482a7. * Add comments that describe the synchronization within GPU3D_Soft - I need to understand it before I can solve my actual problem - Now I do * Revert "Revert "Lock the GPU3D state when rendering on the render thread or serializing it"" This reverts commit 1977566a6d8671d72bd94ba4ebf832c3bf08933a. * Let's try locking the GPU3D state throughout NDS::RunFrame - Just to see what happens * Slim down the lock's scope * Narrow the lock's scope some more * Remove the lock entirely * Try protecting the GPU3D state with just a mutex - I'll clean this up once I know it works * Remove a duplicate method definition * Add a missing `noexcept` specifier * Remove an unused function * Cut some non-hardware state from `GPU3D`'s savestate * Assume that the next frame after loading a savestate won't be identical * Actually, it _is_ worth it * Don't serialize the clip matrix - It's recalculated anyway * Serialize `RenderPolygonRAM` as an array of indexes * Clean up some comments - I liked the dialogue style, but oh well * Try restarting the render thread instead of using the lock - Let's see what happens * Put the lock back * Fix some polygon and vertex indexes being saved incorrectly - Taking the difference between two pointers results in the number of elements, not the number of bytes * Remove `SoftRenderer::StateBusy` since it turns out we don't need it - The real synchronization was the friends we made along the way
2024-01-07 22:39:43 +00:00
void DoSavestate(Savestate* file) noexcept;
2021-01-02 10:38:06 +00:00
};
class Renderer3D;
class NDS;
class GPU3D
{
public:
Clean up the 3D renderer for enhanced flexibility (#1895) * Give `GPU2D::Unit` a virtual destructor - Undefined behavior avoided! * Add an `array2d` alias * Move various parts of `GPU2D::SoftRenderer` to `constexpr` - `SoftRenderer::MosaicTable` is now initialized at compile-time - Most of the `SoftRenderer::Color*` functions are now `constexpr` - The aforementioned functions are used with a constant value in at least one place, so they'll be at least partially computed at compile-time * Generalize `GLRenderer::PrepareCaptureFrame` - Declare it in the base `Renderer3D` class, but make it empty * Remove unneeded `virtual` specifiers * Store `Framebuffer`'s memory in `unique_ptr`s - Reduce the risk of leaks this way * Clean up how `GLCompositor` is initialized - Return it as an `std::optional` instead of a `std::unique_ptr` - Make `GLCompositor` movable - Replace `GLCompositor`'s plain arrays with `std::array` to simplify moving * Pass `GPU` to `GLCompositor`'s important functions instead of passing it to the constructor * Move `GLCompositor` to be a field within `GLRenderer` - Some methods were moved up and made `virtual` * Fix some linker errors * Set the renderer in the frontend * Remove unneeded `virtual` specifiers * Remove `RenderSettings` in favor of just exposing the relevant member variables * Update the frontend to accommodate the core changes * Add `constexpr` and `const` to places in the interpolator * Qualify references to `size_t` * Construct the `optional` directly instead of using `make_optional` - It makes the Linux build choke - I think it's because `GLCompositor`'s constructor is `private`
2023-11-29 14:23:11 +00:00
GPU3D(melonDS::NDS& nds, std::unique_ptr<Renderer3D>&& renderer = nullptr) noexcept;
~GPU3D() noexcept = default;
void Reset() noexcept;
void DoSavestate(Savestate* file) noexcept;
void SetEnabled(bool geometry, bool rendering) noexcept;
void ExecuteCommand() noexcept;
s32 CyclesToRunFor() const noexcept;
void Run() noexcept;
void CheckFIFOIRQ() noexcept;
void CheckFIFODMA() noexcept;
void VCount144(GPU& gpu) noexcept;
void VBlank() noexcept;
void VCount215(GPU& gpu) noexcept;
void RestartFrame(GPU& gpu) noexcept;
void Stop(const GPU& gpu) noexcept;
void SetRenderXPos(u16 xpos) noexcept;
[[nodiscard]] u16 GetRenderXPos() const noexcept { return RenderXPos; }
u32* GetLine(int line) noexcept;
void WriteToGXFIFO(u32 val) noexcept;
[[nodiscard]] bool IsRendererAccelerated() const noexcept;
Clean up the 3D renderer for enhanced flexibility (#1895) * Give `GPU2D::Unit` a virtual destructor - Undefined behavior avoided! * Add an `array2d` alias * Move various parts of `GPU2D::SoftRenderer` to `constexpr` - `SoftRenderer::MosaicTable` is now initialized at compile-time - Most of the `SoftRenderer::Color*` functions are now `constexpr` - The aforementioned functions are used with a constant value in at least one place, so they'll be at least partially computed at compile-time * Generalize `GLRenderer::PrepareCaptureFrame` - Declare it in the base `Renderer3D` class, but make it empty * Remove unneeded `virtual` specifiers * Store `Framebuffer`'s memory in `unique_ptr`s - Reduce the risk of leaks this way * Clean up how `GLCompositor` is initialized - Return it as an `std::optional` instead of a `std::unique_ptr` - Make `GLCompositor` movable - Replace `GLCompositor`'s plain arrays with `std::array` to simplify moving * Pass `GPU` to `GLCompositor`'s important functions instead of passing it to the constructor * Move `GLCompositor` to be a field within `GLRenderer` - Some methods were moved up and made `virtual` * Fix some linker errors * Set the renderer in the frontend * Remove unneeded `virtual` specifiers * Remove `RenderSettings` in favor of just exposing the relevant member variables * Update the frontend to accommodate the core changes * Add `constexpr` and `const` to places in the interpolator * Qualify references to `size_t` * Construct the `optional` directly instead of using `make_optional` - It makes the Linux build choke - I think it's because `GLCompositor`'s constructor is `private`
2023-11-29 14:23:11 +00:00
[[nodiscard]] Renderer3D& GetCurrentRenderer() noexcept { return *CurrentRenderer; }
[[nodiscard]] const Renderer3D& GetCurrentRenderer() const noexcept { return *CurrentRenderer; }
2023-12-21 20:43:57 +00:00
void SetCurrentRenderer(std::unique_ptr<Renderer3D>&& renderer) noexcept;
u8 Read8(u32 addr) noexcept;
u16 Read16(u32 addr) noexcept;
u32 Read32(u32 addr) noexcept;
void Write8(u32 addr, u8 val) noexcept;
void Write16(u32 addr, u16 val) noexcept;
void Write32(u32 addr, u32 val) noexcept;
void Blit(const GPU& gpu) noexcept;
private:
melonDS::NDS& NDS;
typedef union
{
u64 _contents;
struct
{
u32 Param;
u8 Command;
};
} CmdFIFOEntry;
void UpdateClipMatrix() noexcept;
void ResetRenderingState() noexcept;
void AddCycles(s32 num) noexcept;
void NextVertexSlot() noexcept;
void StallPolygonPipeline(s32 delay, s32 nonstalldelay) noexcept;
void SubmitPolygon() noexcept;
void SubmitVertex() noexcept;
void CalculateLighting() noexcept;
void BoxTest(const u32* params) noexcept;
void PosTest() noexcept;
void VecTest(u32 param) noexcept;
void CmdFIFOWrite(const CmdFIFOEntry& entry) noexcept;
CmdFIFOEntry CmdFIFORead() noexcept;
void FinishWork(s32 cycles) noexcept;
void VertexPipelineSubmitCmd() noexcept
{
// vertex commands 0x24, 0x25, 0x26, 0x27, 0x28
if (!(VertexSlotsFree & 0x1)) NextVertexSlot();
else AddCycles(1);
NormalPipeline = 0;
}
void VertexPipelineCmdDelayed6() noexcept
{
// 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;
}
void VertexPipelineCmdDelayed8() noexcept
{
// 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;
}
void VertexPipelineCmdDelayed4() noexcept
{
// 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;
}
std::unique_ptr<Renderer3D> CurrentRenderer = nullptr;
u16 RenderXPos = 0;
public:
FIFO<CmdFIFOEntry, 256> CmdFIFO {};
FIFO<CmdFIFOEntry, 4> CmdPIPE {};
FIFO<CmdFIFOEntry, 64> CmdStallQueue {};
u32 ZeroDotWLimit = 0;
u32 GXStat = 0;
u32 ExecParams[32] {};
u32 ExecParamCount = 0;
s32 CycleCount = 0;
s32 VertexPipeline = 0;
s32 NormalPipeline = 0;
s32 PolygonPipeline = 0;
s32 VertexSlotCounter = 0;
u32 VertexSlotsFree = 0;
u32 NumPushPopCommands = 0;
u32 NumTestCommands = 0;
u32 MatrixMode = 0;
s32 ProjMatrix[16] {};
s32 PosMatrix[16] {};
s32 VecMatrix[16] {};
s32 TexMatrix[16] {};
s32 ClipMatrix[16] {};
bool ClipMatrixDirty = false;
u32 Viewport[6] {};
s32 ProjMatrixStack[16] {};
s32 PosMatrixStack[32][16] {};
s32 VecMatrixStack[32][16] {};
s32 TexMatrixStack[16] {};
s32 ProjMatrixStackPointer = 0;
s32 PosMatrixStackPointer = 0;
s32 TexMatrixStackPointer = 0;
u32 NumCommands = 0;
u32 CurCommand = 0;
u32 ParamCount = 0;
u32 TotalParams = 0;
bool GeometryEnabled = false;
bool RenderingEnabled = false;
u32 DispCnt = 0;
u8 AlphaRefVal = 0;
u8 AlphaRef = 0;
u16 ToonTable[32] {};
u16 EdgeTable[8] {};
u32 FogColor = 0;
u32 FogOffset = 0;
u8 FogDensityTable[32] {};
u32 ClearAttr1 = 0;
u32 ClearAttr2 = 0;
u32 RenderDispCnt = 0;
u8 RenderAlphaRef = 0;
2018-10-18 00:31:01 +00:00
u16 RenderToonTable[32] {};
u16 RenderEdgeTable[8] {};
2019-05-21 20:28:46 +00:00
u32 RenderFogColor = 0;
u32 RenderFogOffset = 0;
u32 RenderFogShift = 0;
u8 RenderFogDensityTable[34] {};
2017-02-17 18:34:41 +00:00
u32 RenderClearAttr1 = 0;
u32 RenderClearAttr2 = 0;
Protect savestates while the threaded software renderer is running (#1864) * First crack at ensuring the render thread doesn't touch GPU state while it's being serialized * Get rid of the semaphore wait * Add some extra fields into GPU3D's serialization * Oops, TempVertexBuffer is already serialized * Move vertex serialization into its own method * Lock the GPU3D state when rendering on the render thread or serializing it * Revert "Lock the GPU3D state when rendering on the render thread or serializing it" This reverts commit 2f49a551c13934b9dc815bbda67a45098f0482a7. * Add comments that describe the synchronization within GPU3D_Soft - I need to understand it before I can solve my actual problem - Now I do * Revert "Revert "Lock the GPU3D state when rendering on the render thread or serializing it"" This reverts commit 1977566a6d8671d72bd94ba4ebf832c3bf08933a. * Let's try locking the GPU3D state throughout NDS::RunFrame - Just to see what happens * Slim down the lock's scope * Narrow the lock's scope some more * Remove the lock entirely * Try protecting the GPU3D state with just a mutex - I'll clean this up once I know it works * Remove a duplicate method definition * Add a missing `noexcept` specifier * Remove an unused function * Cut some non-hardware state from `GPU3D`'s savestate * Assume that the next frame after loading a savestate won't be identical * Actually, it _is_ worth it * Don't serialize the clip matrix - It's recalculated anyway * Serialize `RenderPolygonRAM` as an array of indexes * Clean up some comments - I liked the dialogue style, but oh well * Try restarting the render thread instead of using the lock - Let's see what happens * Put the lock back * Fix some polygon and vertex indexes being saved incorrectly - Taking the difference between two pointers results in the number of elements, not the number of bytes * Remove `SoftRenderer::StateBusy` since it turns out we don't need it - The real synchronization was the friends we made along the way
2024-01-07 22:39:43 +00:00
bool RenderFrameIdentical = false; // not part of the hardware state, don't serialize
bool AbortFrame = false;
u64 Timestamp = 0;
2017-04-23 13:25:15 +00:00
u32 PolygonMode = 0;
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 = false;
u8 ShininessTable[128] {};
u32 PolygonAttr = 0;
u32 CurPolygonAttr = 0;
u32 TexParam = 0;
u32 TexPalette = 0;
s32 PosTestResult[4] {};
s16 VecTestResult[3] {};
Vertex TempVertexBuffer[4] {};
u32 VertexNum = 0;
u32 VertexNumInPoly = 0;
u32 NumConsecutivePolygons = 0;
Polygon* LastStripPolygon = nullptr;
u32 NumOpaquePolygons = 0;
Vertex VertexRAM[6144 * 2] {};
Polygon PolygonRAM[2048 * 2] {};
Vertex* CurVertexRAM = nullptr;
Polygon* CurPolygonRAM = nullptr;
u32 NumVertices = 0;
u32 NumPolygons = 0;
u32 CurRAMBank = 0;
std::array<Polygon*,2048> RenderPolygonRAM {};
u32 RenderNumPolygons = 0;
u32 FlushRequest = 0;
u32 FlushAttributes = 0;
Protect savestates while the threaded software renderer is running (#1864) * First crack at ensuring the render thread doesn't touch GPU state while it's being serialized * Get rid of the semaphore wait * Add some extra fields into GPU3D's serialization * Oops, TempVertexBuffer is already serialized * Move vertex serialization into its own method * Lock the GPU3D state when rendering on the render thread or serializing it * Revert "Lock the GPU3D state when rendering on the render thread or serializing it" This reverts commit 2f49a551c13934b9dc815bbda67a45098f0482a7. * Add comments that describe the synchronization within GPU3D_Soft - I need to understand it before I can solve my actual problem - Now I do * Revert "Revert "Lock the GPU3D state when rendering on the render thread or serializing it"" This reverts commit 1977566a6d8671d72bd94ba4ebf832c3bf08933a. * Let's try locking the GPU3D state throughout NDS::RunFrame - Just to see what happens * Slim down the lock's scope * Narrow the lock's scope some more * Remove the lock entirely * Try protecting the GPU3D state with just a mutex - I'll clean this up once I know it works * Remove a duplicate method definition * Add a missing `noexcept` specifier * Remove an unused function * Cut some non-hardware state from `GPU3D`'s savestate * Assume that the next frame after loading a savestate won't be identical * Actually, it _is_ worth it * Don't serialize the clip matrix - It's recalculated anyway * Serialize `RenderPolygonRAM` as an array of indexes * Clean up some comments - I liked the dialogue style, but oh well * Try restarting the render thread instead of using the lock - Let's see what happens * Put the lock back * Fix some polygon and vertex indexes being saved incorrectly - Taking the difference between two pointers results in the number of elements, not the number of bytes * Remove `SoftRenderer::StateBusy` since it turns out we don't need it - The real synchronization was the friends we made along the way
2024-01-07 22:39:43 +00:00
u32 ScrolledLine[256]; // not part of the hardware state, don't serialize
};
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
class Renderer3D
2017-02-10 15:50:26 +00:00
{
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
public:
virtual ~Renderer3D() = default;
2017-02-10 15:50:26 +00:00
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
Renderer3D(const Renderer3D&) = delete;
Renderer3D& operator=(const Renderer3D&) = delete;
2017-02-10 15:50:26 +00:00
virtual void Reset(GPU& gpu) = 0;
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
// This "Accelerated" flag currently communicates if the framebuffer should
// be allocated differently and other little misc handlers. Ideally there
2023-11-03 23:21:46 +00:00
// are more detailed "traits" that we can ask of the Renderer3D type
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
const bool Accelerated;
2017-02-10 15:50:26 +00:00
virtual void VCount144(GPU& gpu) {};
virtual void Stop(const GPU& gpu) {}
virtual void RenderFrame(GPU& gpu) = 0;
virtual void RestartFrame(GPU& gpu) {};
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
virtual u32* GetLine(int line) = 0;
virtual void Blit(const GPU& gpu) {};
Compute shader renderer (#2041) * nothing works yet * don't double buffer 3D framebuffers for the GL Renderer looks like leftovers from when 3D+2D composition was done in the frontend * oops * it works! * implement display capture for compute renderer it's actually just all stolen from the regular OpenGL renderer * fix bad indirect call * handle cleanup properly * add hires rendering to the compute shader renderer * fix UB also misc changes to use more unsigned multiplication also fix framebuffer resize * correct edge filling behaviour when AA is disabled * fix full color textures * fix edge marking (polygon id is 6-bit not 5) also make the code a bit nicer * take all edge cases into account for XMin/XMax calculation * use hires coordinate again * stop using fixed size buffers based on scale factor in shaders this makes shader compile times tolerable on Wintel - beginning of the shader cache - increase size of tile idx in workdesc to 20 bits * apparently & is not defined on bvec4 why does this even compile on Intel and Nvidia? * put the texture cache into it's own file * add compute shader renderer properly to the GUI also add option to toggle using high resolution vertex coordinates * unbind sampler object in compute shader renderer * fix GetRangedBitMask for 64 bit aligned 64 bits pretty embarassing * convert NonStupidBitfield.h back to LF only new lines * actually adapt to latest changes * fix stupid merge * actually make compute shader renderer work with newest changes * show progress on shader compilation * remove merge leftover
2024-05-13 15:17:39 +00:00
virtual void SetupAccelFrame() {}
Clean up the 3D renderer for enhanced flexibility (#1895) * Give `GPU2D::Unit` a virtual destructor - Undefined behavior avoided! * Add an `array2d` alias * Move various parts of `GPU2D::SoftRenderer` to `constexpr` - `SoftRenderer::MosaicTable` is now initialized at compile-time - Most of the `SoftRenderer::Color*` functions are now `constexpr` - The aforementioned functions are used with a constant value in at least one place, so they'll be at least partially computed at compile-time * Generalize `GLRenderer::PrepareCaptureFrame` - Declare it in the base `Renderer3D` class, but make it empty * Remove unneeded `virtual` specifiers * Store `Framebuffer`'s memory in `unique_ptr`s - Reduce the risk of leaks this way * Clean up how `GLCompositor` is initialized - Return it as an `std::optional` instead of a `std::unique_ptr` - Make `GLCompositor` movable - Replace `GLCompositor`'s plain arrays with `std::array` to simplify moving * Pass `GPU` to `GLCompositor`'s important functions instead of passing it to the constructor * Move `GLCompositor` to be a field within `GLRenderer` - Some methods were moved up and made `virtual` * Fix some linker errors * Set the renderer in the frontend * Remove unneeded `virtual` specifiers * Remove `RenderSettings` in favor of just exposing the relevant member variables * Update the frontend to accommodate the core changes * Add `constexpr` and `const` to places in the interpolator * Qualify references to `size_t` * Construct the `optional` directly instead of using `make_optional` - It makes the Linux build choke - I think it's because `GLCompositor`'s constructor is `private`
2023-11-29 14:23:11 +00:00
virtual void PrepareCaptureFrame() {}
Compute shader renderer (#2041) * nothing works yet * don't double buffer 3D framebuffers for the GL Renderer looks like leftovers from when 3D+2D composition was done in the frontend * oops * it works! * implement display capture for compute renderer it's actually just all stolen from the regular OpenGL renderer * fix bad indirect call * handle cleanup properly * add hires rendering to the compute shader renderer * fix UB also misc changes to use more unsigned multiplication also fix framebuffer resize * correct edge filling behaviour when AA is disabled * fix full color textures * fix edge marking (polygon id is 6-bit not 5) also make the code a bit nicer * take all edge cases into account for XMin/XMax calculation * use hires coordinate again * stop using fixed size buffers based on scale factor in shaders this makes shader compile times tolerable on Wintel - beginning of the shader cache - increase size of tile idx in workdesc to 20 bits * apparently & is not defined on bvec4 why does this even compile on Intel and Nvidia? * put the texture cache into it's own file * add compute shader renderer properly to the GUI also add option to toggle using high resolution vertex coordinates * unbind sampler object in compute shader renderer * fix GetRangedBitMask for 64 bit aligned 64 bits pretty embarassing * convert NonStupidBitfield.h back to LF only new lines * actually adapt to latest changes * fix stupid merge * actually make compute shader renderer work with newest changes * show progress on shader compilation * remove merge leftover
2024-05-13 15:17:39 +00:00
virtual void BindOutputTexture(int buffer) {}
virtual bool NeedsShaderCompile() { return false; }
virtual void ShaderCompileStep(int& current, int& count) {}
protected:
Renderer3D(bool Accelerated);
Allow for a more modular renderer backends (#990) * Draft GPU3D renderer modularization * Update sources C++ standard to C++17 The top-level `CMakeLists.txt` is already using the C++17 standard. * Move GLCompositor into class type Some other misc fixes to push towards better modularity * Make renderer-implementation types move-only These types are going to be holding onto handles of GPU-side resources and shouldn't ever be copied around. * Fix OSX: Remove 'register' storage class specifier `register` has been removed in C++17... But this keyword hasn't done anything in years anyways. OSX builds consider this "warning" an error and it stops the whole build. * Add RestartFrame to Renderer3D interface * Move Accelerated property to Renderer3D interface There are points in the code base where we do: `renderer != 0` to know if we are feeding an openGL renderer. Rather than that we can instead just have this be a property of the renderer itself. With this pattern a renderer can just say how it wants its data to come in rather than have everyone know that they're talking to an OpenGL renderer. * Remove Accelerated flag from GPU * Move 2D_Soft interface in separate header Also make the current 2D engine an "owned" unique_ptr. * Update alignment attribute to standard alignas Uses standardized `alignas` rather than compiler-specific attributes. https://en.cppreference.com/w/cpp/language/alignas * Fix Clang: alignas specifier Alignment must be specified before the array to align the entire array. https://en.cppreference.com/w/cpp/language/alignas * Converted Renderer3D Accelerated to variable This flag is checked a lot during scanline rasterization. So rather than having an expensive vtable-lookup call during mainline rendering code, it is now a public constant bool type that is written to only once during Renderer3D initialization.
2021-02-09 22:38:51 +00:00
};
}
#endif