From bffaec9c5e6b68187a86288cf3db6e88e4bea2ce Mon Sep 17 00:00:00 2001
From: OatmealDome <julian@oatmealdome.me>
Date: Fri, 24 Jan 2025 18:31:42 -0500
Subject: [PATCH] VertexLoaderBase: Allow the vertex loader type to be set via
 config

---
 Source/Core/Core/Config/GraphicsSettings.cpp |  3 ++
 Source/Core/Core/Config/GraphicsSettings.h   |  5 +++
 Source/Core/VideoCommon/VertexLoaderBase.cpp | 37 ++++++++++++--------
 Source/Core/VideoCommon/VideoConfig.cpp      |  2 ++
 Source/Core/VideoCommon/VideoConfig.h        | 10 ++++++
 5 files changed, 43 insertions(+), 14 deletions(-)

diff --git a/Source/Core/Core/Config/GraphicsSettings.cpp b/Source/Core/Core/Config/GraphicsSettings.cpp
index 1d6d4def08..f201ac7f95 100644
--- a/Source/Core/Core/Config/GraphicsSettings.cpp
+++ b/Source/Core/Core/Config/GraphicsSettings.cpp
@@ -126,6 +126,9 @@ const Info<bool> GFX_MODS_ENABLE{{System::GFX, "Settings", "EnableMods"}, false}
 
 const Info<std::string> GFX_DRIVER_LIB_NAME{{System::GFX, "Settings", "DriverLibName"}, ""};
 
+const Info<VertexLoaderType> GFX_VERTEX_LOADER_TYPE{{System::GFX, "Settings", "VertexLoaderType"},
+                                                    VertexLoaderType::Native};
+
 // Graphics.Enhancements
 
 const Info<TextureFilteringMode> GFX_ENHANCE_FORCE_TEXTURE_FILTERING{
diff --git a/Source/Core/Core/Config/GraphicsSettings.h b/Source/Core/Core/Config/GraphicsSettings.h
index 49c7b10412..bf4ef4f008 100644
--- a/Source/Core/Core/Config/GraphicsSettings.h
+++ b/Source/Core/Core/Config/GraphicsSettings.h
@@ -16,6 +16,7 @@ enum class OutputResamplingMode : int;
 enum class ColorCorrectionRegion : int;
 enum class TriState : int;
 enum class FrameDumpResolutionType : int;
+enum class VertexLoaderType : int;
 
 namespace Config
 {
@@ -184,4 +185,8 @@ extern const Info<bool> GFX_PERF_QUERIES_ENABLE;
 
 extern const Info<std::string> GFX_DRIVER_LIB_NAME;
 
+// Vertex loader
+
+extern const Info<VertexLoaderType> GFX_VERTEX_LOADER_TYPE;
+
 }  // namespace Config
diff --git a/Source/Core/VideoCommon/VertexLoaderBase.cpp b/Source/Core/VideoCommon/VertexLoaderBase.cpp
index a3597b53e5..36b6a2a67f 100644
--- a/Source/Core/VideoCommon/VertexLoaderBase.cpp
+++ b/Source/Core/VideoCommon/VertexLoaderBase.cpp
@@ -25,6 +25,7 @@
 #include "VideoCommon/VertexLoader_Normal.h"
 #include "VideoCommon/VertexLoader_Position.h"
 #include "VideoCommon/VertexLoader_TextCoord.h"
+#include "VideoCommon/VideoConfig.h"
 
 #ifdef _M_X86_64
 #include "VideoCommon/VertexLoaderX64.h"
@@ -238,29 +239,37 @@ u32 VertexLoaderBase::GetVertexComponents(const TVtxDesc& vtx_desc, const VAT& v
 std::unique_ptr<VertexLoaderBase> VertexLoaderBase::CreateVertexLoader(const TVtxDesc& vtx_desc,
                                                                        const VAT& vtx_attr)
 {
-  std::unique_ptr<VertexLoaderBase> loader = nullptr;
+  const VertexLoaderType loader_type = g_ActiveConfig.vertex_loader_type;
 
-  // #define COMPARE_VERTEXLOADERS
+  if (loader_type == VertexLoaderType::Software)
+  {
+    return std::make_unique<VertexLoader>(vtx_desc, vtx_attr);
+  }
+
+  std::unique_ptr<VertexLoaderBase> native_loader = nullptr;
 
 #if defined(_M_X86_64)
-  loader = std::make_unique<VertexLoaderX64>(vtx_desc, vtx_attr);
+  native_loader = std::make_unique<VertexLoaderX64>(vtx_desc, vtx_attr);
 #elif defined(_M_ARM_64)
-  loader = std::make_unique<VertexLoaderARM64>(vtx_desc, vtx_attr);
+  native_loader = std::make_unique<VertexLoaderARM64>(vtx_desc, vtx_attr);
 #endif
 
   // Use the software loader as a fallback
   // (not currently applicable, as both VertexLoaderX64 and VertexLoaderARM64
   // are always usable, but if a loader that only works on some CPUs is created
   // then this fallback would be used)
-  if (!loader)
-    loader = std::make_unique<VertexLoader>(vtx_desc, vtx_attr);
+  if (!native_loader)
+  {
+    return std::make_unique<VertexLoader>(vtx_desc, vtx_attr);
+  }
 
-#if defined(COMPARE_VERTEXLOADERS)
-  return std::make_unique<VertexLoaderTester>(
-      std::make_unique<VertexLoader>(vtx_desc, vtx_attr),  // the software one
-      std::move(loader),                                   // the new one to compare
-      vtx_desc, vtx_attr);
-#else
-  return loader;
-#endif
+  if (loader_type == VertexLoaderType::Compare)
+  {
+    return std::make_unique<VertexLoaderTester>(
+        std::make_unique<VertexLoader>(vtx_desc, vtx_attr),  // the software one
+        std::move(native_loader),                            // the new one to compare
+        vtx_desc, vtx_attr);
+  }
+
+  return native_loader;
 }
diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp
index cc62d33959..81e4c9cb05 100644
--- a/Source/Core/VideoCommon/VideoConfig.cpp
+++ b/Source/Core/VideoCommon/VideoConfig.cpp
@@ -206,6 +206,8 @@ void VideoConfig::Refresh()
   bGraphicMods = Config::Get(Config::GFX_MODS_ENABLE);
 
   customDriverLibraryName = Config::Get(Config::GFX_DRIVER_LIB_NAME);
+
+  vertex_loader_type = Config::Get(Config::GFX_VERTEX_LOADER_TYPE);
 }
 
 void VideoConfig::VerifyValidity()
diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h
index d2f0d50cbd..5076561fd0 100644
--- a/Source/Core/VideoCommon/VideoConfig.h
+++ b/Source/Core/VideoCommon/VideoConfig.h
@@ -90,6 +90,13 @@ enum class FrameDumpResolutionType : int
   XFBRawResolution,
 };
 
+enum class VertexLoaderType : int
+{
+  Native,
+  Software,
+  Compare
+};
+
 // Bitmask containing information about which configuration has changed for the backend.
 enum ConfigChangeBits : u32
 {
@@ -279,6 +286,9 @@ struct VideoConfig final
   // Loading custom drivers on Android
   std::string customDriverLibraryName;
 
+  // Vertex loader
+  VertexLoaderType vertex_loader_type;
+
   // Static config per API
   // TODO: Move this out of VideoConfig
   struct