add compute shader renderer properly to the GUI

also add option to toggle using high resolution vertex coordinates
This commit is contained in:
RSDuck
2023-05-14 22:16:11 +02:00
parent 045829b0bd
commit a631a33239
10 changed files with 120 additions and 86 deletions

View File

@ -396,7 +396,7 @@ void AssignFramebuffers()
void InitRenderer(int renderer) void InitRenderer(int renderer)
{ {
#ifdef OGLRENDERER_ENABLED #ifdef OGLRENDERER_ENABLED
if (renderer == 1) if (renderer != renderer3D_Software)
{ {
CurGLCompositor = GLCompositor::New(); CurGLCompositor = GLCompositor::New();
// Create opengl renderer // Create opengl renderer

View File

@ -160,6 +160,7 @@ struct RenderSettings
int GL_ScaleFactor; int GL_ScaleFactor;
bool GL_BetterPolygons; bool GL_BetterPolygons;
bool GL_HiresCoordinates;
}; };
@ -170,6 +171,16 @@ void Stop();
void DoSavestate(Savestate* file); void DoSavestate(Savestate* file);
enum
{
renderer3D_Software = 0,
#ifdef OGLRENDERER_ENABLED
renderer3D_OpenGL,
renderer3D_OpenGLCompute,
#endif
renderer3D_Max,
};
void InitRenderer(int renderer); void InitRenderer(int renderer);
void DeInitRenderer(); void DeInitRenderer();
void ResetRenderer(); void ResetRenderer();

View File

@ -196,6 +196,8 @@ void ComputeRenderer::SetRenderSettings(GPU::RenderSettings& settings)
TilesPerLine = ScreenWidth/TileSize; TilesPerLine = ScreenWidth/TileSize;
TileLines = ScreenHeight/TileSize; TileLines = ScreenHeight/TileSize;
HiresCoordinates = settings.GL_HiresCoordinates;
MaxWorkTiles = TilesPerLine*TileLines*8; MaxWorkTiles = TilesPerLine*TileLines*8;
for (int i = 0; i < tilememoryLayer_Num; i++) for (int i = 0; i < tilememoryLayer_Num; i++)
@ -628,8 +630,16 @@ void ComputeRenderer::RenderFrame()
s32 ytop = ScreenHeight, ybot = 0; s32 ytop = ScreenHeight, ybot = 0;
for (int i = 0; i < polygon->NumVertices; i++) for (int i = 0; i < polygon->NumVertices; i++)
{ {
scaledPositions[i][0] = (polygon->Vertices[i]->HiresPosition[0] * ScaleFactor) >> 4; if (HiresCoordinates)
scaledPositions[i][1] = (polygon->Vertices[i]->HiresPosition[1] * ScaleFactor) >> 4; {
scaledPositions[i][0] = (polygon->Vertices[i]->HiresPosition[0] * ScaleFactor) >> 4;
scaledPositions[i][1] = (polygon->Vertices[i]->HiresPosition[1] * ScaleFactor) >> 4;
}
else
{
scaledPositions[i][0] = polygon->Vertices[i]->FinalPosition[0] * ScaleFactor;
scaledPositions[i][1] = polygon->Vertices[i]->FinalPosition[1] * ScaleFactor;
}
ytop = std::min(scaledPositions[i][1], ytop); ytop = std::min(scaledPositions[i][1], ytop);
ybot = std::max(scaledPositions[i][1], ybot); ybot = std::max(scaledPositions[i][1], ybot);
} }

View File

@ -209,6 +209,7 @@ private:
int TilesPerLine, TileLines; int TilesPerLine, TileLines;
int ScaleFactor = -1; int ScaleFactor = -1;
int MaxWorkTiles; int MaxWorkTiles;
bool HiresCoordinates;
void DeleteShaders(); void DeleteShaders();

View File

@ -21,6 +21,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "Platform.h" #include "Platform.h"
#include "Config.h" #include "Config.h"
#include "GPU.h"
namespace Config namespace Config
@ -57,6 +58,7 @@ bool Threaded3D;
int GL_ScaleFactor; int GL_ScaleFactor;
bool GL_BetterPolygons; bool GL_BetterPolygons;
bool GL_HiresCoordinates;
bool LimitFPS; bool LimitFPS;
bool AudioSync; bool AudioSync;
@ -232,11 +234,12 @@ ConfigEntry ConfigFile[] =
{"ScreenVSync", 1, &ScreenVSync, false, false}, {"ScreenVSync", 1, &ScreenVSync, false, false},
{"ScreenVSyncInterval", 0, &ScreenVSyncInterval, 1, false}, {"ScreenVSyncInterval", 0, &ScreenVSyncInterval, 1, false},
{"3DRenderer", 0, &_3DRenderer, 0, false}, {"3DRenderer", 0, &_3DRenderer, GPU::renderer3D_Software, false},
{"Threaded3D", 1, &Threaded3D, true, false}, {"Threaded3D", 1, &Threaded3D, true, false},
{"GL_ScaleFactor", 0, &GL_ScaleFactor, 1, false}, {"GL_ScaleFactor", 0, &GL_ScaleFactor, 1, false},
{"GL_BetterPolygons", 1, &GL_BetterPolygons, false, false}, {"GL_BetterPolygons", 1, &GL_BetterPolygons, false, false},
{"GL_HiresCoordinates", 1, &GL_HiresCoordinates, true, false},
{"LimitFPS", 1, &LimitFPS, true, false}, {"LimitFPS", 1, &LimitFPS, true, false},
{"AudioSync", 1, &AudioSync, false}, {"AudioSync", 1, &AudioSync, false},

View File

@ -103,6 +103,7 @@ extern bool Threaded3D;
extern int GL_ScaleFactor; extern int GL_ScaleFactor;
extern bool GL_BetterPolygons; extern bool GL_BetterPolygons;
extern bool GL_HiresCoordinates;
extern bool LimitFPS; extern bool LimitFPS;
extern bool AudioSync; extern bool AudioSync;

View File

@ -23,6 +23,7 @@
#include "types.h" #include "types.h"
#include "Platform.h" #include "Platform.h"
#include "Config.h" #include "Config.h"
#include "GPU.h"
#include "VideoSettingsDialog.h" #include "VideoSettingsDialog.h"
#include "ui_VideoSettingsDialog.h" #include "ui_VideoSettingsDialog.h"
@ -30,11 +31,20 @@
inline bool UsesGL() inline bool UsesGL()
{ {
return (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); return (Config::ScreenUseGL != 0) || (Config::_3DRenderer != GPU::renderer3D_Software);
} }
VideoSettingsDialog* VideoSettingsDialog::currentDlg = nullptr; VideoSettingsDialog* VideoSettingsDialog::currentDlg = nullptr;
void VideoSettingsDialog::setEnabled()
{
bool softwareRenderer = Config::_3DRenderer == GPU::renderer3D_Software;
ui->cbGLDisplay->setEnabled(softwareRenderer);
ui->cbSoftwareThreaded->setEnabled(softwareRenderer);
ui->cbxGLResolution->setEnabled(!softwareRenderer);
ui->cbBetterPolygons->setEnabled(Config::_3DRenderer == GPU::renderer3D_OpenGL);
ui->cbxComputeHiResCoords->setEnabled(Config::_3DRenderer == GPU::renderer3D_OpenGLCompute);
}
VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::VideoSettingsDialog) VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(new Ui::VideoSettingsDialog)
{ {
@ -48,10 +58,12 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(
oldSoftThreaded = Config::Threaded3D; oldSoftThreaded = Config::Threaded3D;
oldGLScale = Config::GL_ScaleFactor; oldGLScale = Config::GL_ScaleFactor;
oldGLBetterPolygons = Config::GL_BetterPolygons; oldGLBetterPolygons = Config::GL_BetterPolygons;
oldHiresCoordinates = Config::GL_HiresCoordinates;
grp3DRenderer = new QButtonGroup(this); grp3DRenderer = new QButtonGroup(this);
grp3DRenderer->addButton(ui->rb3DSoftware, 0); grp3DRenderer->addButton(ui->rb3DSoftware, GPU::renderer3D_Software);
grp3DRenderer->addButton(ui->rb3DOpenGL, 1); grp3DRenderer->addButton(ui->rb3DOpenGL, GPU::renderer3D_OpenGL);
grp3DRenderer->addButton(ui->rb3DCompute, GPU::renderer3D_OpenGLCompute);
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int))); connect(grp3DRenderer, SIGNAL(buttonClicked(int)), this, SLOT(onChange3DRenderer(int)));
#else #else
@ -75,25 +87,13 @@ VideoSettingsDialog::VideoSettingsDialog(QWidget* parent) : QDialog(parent), ui(
ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1); ui->cbxGLResolution->setCurrentIndex(Config::GL_ScaleFactor-1);
ui->cbBetterPolygons->setChecked(Config::GL_BetterPolygons != 0); ui->cbBetterPolygons->setChecked(Config::GL_BetterPolygons != 0);
ui->cbxComputeHiResCoords->setChecked(Config::GL_HiresCoordinates != 0);
if (!Config::ScreenVSync) if (!Config::ScreenVSync)
ui->sbVSyncInterval->setEnabled(false); ui->sbVSyncInterval->setEnabled(false);
setVsyncControlEnable(UsesGL()); setVsyncControlEnable(UsesGL());
if (Config::_3DRenderer == 0) setEnabled();
{
ui->cbGLDisplay->setEnabled(true);
ui->cbSoftwareThreaded->setEnabled(true);
ui->cbxGLResolution->setEnabled(false);
ui->cbBetterPolygons->setEnabled(false);
}
else
{
ui->cbGLDisplay->setEnabled(false);
ui->cbSoftwareThreaded->setEnabled(false);
ui->cbxGLResolution->setEnabled(true);
ui->cbBetterPolygons->setEnabled(true);
}
} }
VideoSettingsDialog::~VideoSettingsDialog() VideoSettingsDialog::~VideoSettingsDialog()
@ -119,6 +119,7 @@ void VideoSettingsDialog::on_VideoSettingsDialog_rejected()
Config::Threaded3D = oldSoftThreaded; Config::Threaded3D = oldSoftThreaded;
Config::GL_ScaleFactor = oldGLScale; Config::GL_ScaleFactor = oldGLScale;
Config::GL_BetterPolygons = oldGLBetterPolygons; Config::GL_BetterPolygons = oldGLBetterPolygons;
Config::GL_HiresCoordinates = oldHiresCoordinates;
emit updateVideoSettings(old_gl != UsesGL()); emit updateVideoSettings(old_gl != UsesGL());
@ -133,31 +134,18 @@ void VideoSettingsDialog::setVsyncControlEnable(bool hasOGL)
void VideoSettingsDialog::onChange3DRenderer(int renderer) void VideoSettingsDialog::onChange3DRenderer(int renderer)
{ {
bool old_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); bool old_gl = UsesGL();
Config::_3DRenderer = renderer; Config::_3DRenderer = renderer;
if (renderer == 0) setEnabled();
{
ui->cbGLDisplay->setEnabled(true);
ui->cbSoftwareThreaded->setEnabled(true);
ui->cbxGLResolution->setEnabled(false);
ui->cbBetterPolygons->setEnabled(false);
}
else
{
ui->cbGLDisplay->setEnabled(false);
ui->cbSoftwareThreaded->setEnabled(false);
ui->cbxGLResolution->setEnabled(true);
ui->cbBetterPolygons->setEnabled(true);
}
emit updateVideoSettings(old_gl != UsesGL()); emit updateVideoSettings(old_gl != UsesGL());
} }
void VideoSettingsDialog::on_cbGLDisplay_stateChanged(int state) void VideoSettingsDialog::on_cbGLDisplay_stateChanged(int state)
{ {
bool old_gl = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); bool old_gl = UsesGL();
Config::ScreenUseGL = (state != 0); Config::ScreenUseGL = (state != 0);
@ -205,3 +193,10 @@ void VideoSettingsDialog::on_cbBetterPolygons_stateChanged(int state)
emit updateVideoSettings(false); emit updateVideoSettings(false);
} }
void VideoSettingsDialog::on_cbxComputeHiResCoords_stateChanged(int state)
{
Config::GL_HiresCoordinates = (state != 0);
emit updateVideoSettings(false);
}

View File

@ -65,10 +65,12 @@ private slots:
void on_cbxGLResolution_currentIndexChanged(int idx); void on_cbxGLResolution_currentIndexChanged(int idx);
void on_cbBetterPolygons_stateChanged(int state); void on_cbBetterPolygons_stateChanged(int state);
void on_cbxComputeHiResCoords_stateChanged(int state);
void on_cbSoftwareThreaded_stateChanged(int state); void on_cbSoftwareThreaded_stateChanged(int state);
private: private:
void setVsyncControlEnable(bool hasOGL); void setVsyncControlEnable(bool hasOGL);
void setEnabled();
Ui::VideoSettingsDialog* ui; Ui::VideoSettingsDialog* ui;
@ -81,6 +83,7 @@ private:
int oldSoftThreaded; int oldSoftThreaded;
int oldGLScale; int oldGLScale;
int oldGLBetterPolygons; int oldGLBetterPolygons;
int oldHiresCoordinates;
}; };
#endif // VIDEOSETTINGSDIALOG_H #endif // VIDEOSETTINGSDIALOG_H

View File

@ -6,7 +6,7 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>408</width> <width>427</width>
<height>262</height> <height>262</height>
</rect> </rect>
</property> </property>
@ -24,7 +24,7 @@
<enum>QLayout::SetFixedSize</enum> <enum>QLayout::SetFixedSize</enum>
</property> </property>
<property name="horizontalSpacing"> <property name="horizontalSpacing">
<number>-1</number> <number>6</number>
</property> </property>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QGroupBox" name="groupBox_3"> <widget class="QGroupBox" name="groupBox_3">
@ -39,13 +39,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QComboBox" name="cbxGLResolution">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The resolution at which the 3D graphics will be rendered. Higher resolutions improve graphics quality when the main window is enlarged, but may also cause glitches.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="2" column="0"> <item row="2" column="0">
<widget class="QCheckBox" name="cbBetterPolygons"> <widget class="QCheckBox" name="cbBetterPolygons">
<property name="whatsThis"> <property name="whatsThis">
@ -56,6 +49,20 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="0">
<widget class="QComboBox" name="cbxGLResolution">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The resolution at which the 3D graphics will be rendered. Higher resolutions improve graphics quality when the main window is enlarged, but may also cause glitches.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="cbxComputeHiResCoords">
<property name="text">
<string>Use high resolution coordinates</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>
@ -94,23 +101,7 @@
<string>Display settings</string> <string>Display settings</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="6" column="0"> <item row="7" column="1">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The interval at which to synchronize to the monitor's refresh rate. Set to 1 for a 60Hz monitor, 2 for 120Hz, ...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VSync interval:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<widget class="QSpinBox" name="sbVSyncInterval"> <widget class="QSpinBox" name="sbVSyncInterval">
<property name="whatsThis"> <property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The interval at which to synchronize to the monitor's refresh rate. Set to 1 for a 60Hz monitor, 2 for 120Hz, ...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The interval at which to synchronize to the monitor's refresh rate. Set to 1 for a 60Hz monitor, 2 for 120Hz, ...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -123,7 +114,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="4" column="0" colspan="2"> <item row="5" column="0" colspan="2">
<widget class="QCheckBox" name="cbGLDisplay"> <widget class="QCheckBox" name="cbGLDisplay">
<property name="whatsThis"> <property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use OpenGL to draw the DS screens to the main window. May result in better frame pacing. Mandatory when using the OpenGL 3D renderer.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Use OpenGL to draw the DS screens to the main window. May result in better frame pacing. Mandatory when using the OpenGL 3D renderer.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
@ -133,17 +124,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="5" column="0" colspan="2"> <item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="cbVSync">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When using OpenGL, synchronize the video output to your monitor's refresh rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VSync</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="2">
<spacer name="verticalSpacer"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
@ -159,13 +140,39 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="6" column="0" colspan="2">
<widget class="QCheckBox" name="cbVSync">
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;When using OpenGL, synchronize the video output to your monitor's refresh rate.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VSync</string>
</property>
</widget>
</item>
<item row="7" column="0">
<widget class="QLabel" name="label_2">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The interval at which to synchronize to the monitor's refresh rate. Set to 1 for a 60Hz monitor, 2 for 120Hz, ...&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>VSync interval:</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="2"> <item row="2" column="0" colspan="2">
<widget class="QRadioButton" name="rb3DOpenGL"> <widget class="QRadioButton" name="rb3DOpenGL">
<property name="whatsThis"> <property name="whatsThis">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The OpenGL renderer may be faster than software and supports graphical enhancements, but is more prone to glitches.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The OpenGL renderer may be faster than software and supports graphical enhancements, but is more prone to glitches.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>OpenGL</string> <string>OpenGL (Classic)</string>
</property> </property>
</widget> </widget>
</item> </item>
@ -186,6 +193,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="0">
<widget class="QRadioButton" name="rb3DCompute">
<property name="text">
<string>OpenGL (Compute shader)</string>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</item> </item>

View File

@ -323,6 +323,7 @@ void EmuThread::run()
videoSettings.Soft_Threaded = Config::Threaded3D != 0; videoSettings.Soft_Threaded = Config::Threaded3D != 0;
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor; videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons; videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons;
videoSettings.GL_HiresCoordinates = Config::GL_HiresCoordinates;
if (mainWindow->hasOGL) if (mainWindow->hasOGL)
{ {
@ -444,16 +445,17 @@ void EmuThread::run()
else else
#endif #endif
{ {
videoRenderer = 0; videoRenderer = GPU::renderer3D_Software;
} }
videoRenderer = oglContext ? Config::_3DRenderer : 0; videoRenderer = oglContext ? Config::_3DRenderer : GPU::renderer3D_Software;
videoSettingsDirty = false; videoSettingsDirty = false;
videoSettings.Soft_Threaded = Config::Threaded3D != 0; videoSettings.Soft_Threaded = Config::Threaded3D != 0;
videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor; videoSettings.GL_ScaleFactor = Config::GL_ScaleFactor;
videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons; videoSettings.GL_BetterPolygons = Config::GL_BetterPolygons;
videoSettings.GL_HiresCoordinates = Config::GL_HiresCoordinates;
GPU::SetRenderSettings(videoRenderer, videoSettings); GPU::SetRenderSettings(videoRenderer, videoSettings);
} }
@ -1860,7 +1862,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
void MainWindow::createScreenPanel() void MainWindow::createScreenPanel()
{ {
hasOGL = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != 0); hasOGL = (Config::ScreenUseGL != 0) || (Config::_3DRenderer != GPU::renderer3D_Software);
if (hasOGL) if (hasOGL)
{ {
@ -3273,13 +3275,7 @@ int main(int argc, char** argv)
#define SANITIZE(var, min, max) { var = std::clamp(var, min, max); } #define SANITIZE(var, min, max) { var = std::clamp(var, min, max); }
SANITIZE(Config::ConsoleType, 0, 1); SANITIZE(Config::ConsoleType, 0, 1);
SANITIZE(Config::_3DRenderer, SANITIZE(Config::_3DRenderer, (int)GPU::renderer3D_Software, (int)GPU::renderer3D_Max);
0,
0 // Minimum, Software renderer
#ifdef OGLRENDERER_ENABLED
+ 1 // OpenGL Renderer
#endif
);
SANITIZE(Config::ScreenVSyncInterval, 1, 20); SANITIZE(Config::ScreenVSyncInterval, 1, 20);
SANITIZE(Config::GL_ScaleFactor, 1, 16); SANITIZE(Config::GL_ScaleFactor, 1, 16);
SANITIZE(Config::AudioInterp, 0, 3); SANITIZE(Config::AudioInterp, 0, 3);