Browse Source

Refactor the config vars

Panagiotis Christopoulos Charitos 2 years ago
parent
commit
2f0300dbbe
66 changed files with 722 additions and 830 deletions
  1. 48 31
      AnKi/Core/App.cpp
  2. 6 1
      AnKi/Core/App.h
  3. 69 200
      AnKi/Core/ConfigSet.cpp
  4. 164 119
      AnKi/Core/ConfigSet.h
  5. 0 24
      AnKi/Core/ConfigVars.defs.h
  6. 4 1
      AnKi/Core/GpuMemory/GpuSceneBuffer.cpp
  7. 4 1
      AnKi/Core/GpuMemory/RebarTransientMemoryPool.cpp
  8. 4 1
      AnKi/Core/GpuMemory/UnifiedGeometryBuffer.cpp
  9. 0 23
      AnKi/Gr/ConfigVars.defs.h
  10. 2 0
      AnKi/Gr/GrManager.h
  11. 0 1
      AnKi/Gr/Vulkan/Common.h
  12. 38 92
      AnKi/Gr/Vulkan/GrManagerImpl.cpp
  13. 2 3
      AnKi/Gr/Vulkan/GrManagerImpl.h
  14. 1 1
      AnKi/Gr/Vulkan/Pipeline.cpp
  15. 4 1
      AnKi/Gr/Vulkan/PipelineCache.cpp
  16. 1 1
      AnKi/Gr/Vulkan/ShaderProgramImpl.cpp
  17. 12 10
      AnKi/Renderer/Bloom.cpp
  18. 3 0
      AnKi/Renderer/Bloom.h
  19. 1 0
      AnKi/Renderer/Common.h
  20. 0 84
      AnKi/Renderer/ConfigVars.defs.h
  21. 6 3
      AnKi/Renderer/Dbg.cpp
  22. 3 0
      AnKi/Renderer/Dbg.h
  23. 2 2
      AnKi/Renderer/DepthDownscale.cpp
  24. 3 3
      AnKi/Renderer/DownscaleBlur.cpp
  25. 8 5
      AnKi/Renderer/FinalComposite.cpp
  26. 11 9
      AnKi/Renderer/GBuffer.cpp
  27. 27 15
      AnKi/Renderer/IndirectDiffuse.cpp
  28. 7 2
      AnKi/Renderer/IndirectDiffuseProbes.cpp
  29. 20 13
      AnKi/Renderer/IndirectSpecular.cpp
  30. 6 2
      AnKi/Renderer/LensFlare.cpp
  31. 3 3
      AnKi/Renderer/LightShading.cpp
  32. 2 2
      AnKi/Renderer/MainRenderer.cpp
  33. 6 6
      AnKi/Renderer/MotionVectors.cpp
  34. 10 4
      AnKi/Renderer/ProbeReflections.cpp
  35. 22 7
      AnKi/Renderer/Renderer.cpp
  36. 6 0
      AnKi/Renderer/Renderer.h
  37. 8 3
      AnKi/Renderer/RtShadows.cpp
  38. 14 9
      AnKi/Renderer/Scale.cpp
  39. 15 9
      AnKi/Renderer/ShadowMapping.cpp
  40. 1 0
      AnKi/Renderer/ShadowMapping.h
  41. 8 7
      AnKi/Renderer/ShadowmapsResolve.cpp
  42. 6 8
      AnKi/Renderer/TemporalAA.cpp
  43. 3 3
      AnKi/Renderer/VolumetricFog.cpp
  44. 10 3
      AnKi/Renderer/VolumetricLightingAccumulation.cpp
  45. 5 0
      AnKi/Renderer/VolumetricLightingAccumulation.h
  46. 7 4
      AnKi/Renderer/VrsSriGeneration.cpp
  47. 0 15
      AnKi/Resource/ConfigVars.defs.h
  48. 3 1
      AnKi/Resource/ImageResource.cpp
  49. 9 3
      AnKi/Resource/ResourceFilesystem.cpp
  50. 4 0
      AnKi/Resource/ResourceFilesystem.h
  51. 4 1
      AnKi/Resource/ResourceManager.cpp
  52. 28 13
      AnKi/Scene/Components/CameraComponent.cpp
  53. 3 0
      AnKi/Scene/Components/CameraComponent.h
  54. 2 2
      AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp
  55. 6 3
      AnKi/Scene/Components/ReflectionProbeComponent.cpp
  56. 2 0
      AnKi/Scene/Components/ReflectionProbeComponent.h
  57. 0 40
      AnKi/Scene/ConfigVars.defs.h
  58. 25 7
      AnKi/Scene/ContiguousArrayAllocator.cpp
  59. 8 1
      AnKi/Scene/SceneGraph.cpp
  60. 3 0
      AnKi/Scene/SceneGraph.h
  61. 18 0
      AnKi/Util/Singleton.h
  62. 7 8
      Samples/Common/SampleApp.cpp
  63. 4 4
      Samples/PhysicsPlayground/Main.cpp
  64. 1 1
      Samples/SkeletalAnimation/Main.cpp
  65. 10 10
      Sandbox/Main.cpp
  66. 3 5
      Tools/Image/ImageViewerMain.cpp

+ 48 - 31
AnKi/Core/App.cpp

@@ -53,10 +53,31 @@ static StatCounter g_cpuAllocationCount(StatCategory::kCpuMem, "Allocations/fram
 										StatFlag::kBytes | StatFlag::kZeroEveryFrame | StatFlag::kThreadSafe);
 static StatCounter g_cpuFreesCount(StatCategory::kCpuMem, "Frees/frame", StatFlag::kBytes | StatFlag::kZeroEveryFrame | StatFlag::kThreadSafe);
 
+static NumericCVar<U32> g_widthCVar(CVarSubsystem::kCore, "Width", 1920, 16, 16 * 1024, "Width");
+static NumericCVar<U32> g_heightCVar(CVarSubsystem::kCore, "Height", 1080, 16, 16 * 1024, "Height");
+NumericCVar<U32> g_windowFullscreenCVar(CVarSubsystem::kCore, "WindowFullscreen", 1, 0, 2,
+										"0: windowed, 1: borderless fullscreen, 2: exclusive fullscreen");
+NumericCVar<U32> g_targetFpsCVar(CVarSubsystem::kCore, "TargetFps", 60u, 1u, kMaxU32, "Target FPS");
+static NumericCVar<U32> g_jobThreadCountCVar(CVarSubsystem::kCore, "JobThreadCount", max(2u, getCpuCoresCount() / 2u), 2u, 1024u,
+											 "Number of job thread");
+NumericCVar<U32> g_displayStatsCVar(CVarSubsystem::kCore, "DisplayStats", 0, 0, 2, "Display stats, 0: None, 1: Simple, 2: Detailed");
+BoolCVar g_clearCachesCVar(CVarSubsystem::kCore, "ClearCaches", false, "Clear all caches");
+BoolCVar g_verboseLogCVar(CVarSubsystem::kCore, "VerboseLog", false, "Verbose logging");
+BoolCVar g_benchmarkModeCVar(CVarSubsystem::kCore, "BenchmarkMode", false, "Run in a benchmark mode. Fixed timestep, unlimited target FPS");
+NumericCVar<U32> g_benchmarkModeFrameCountCVar(CVarSubsystem::kCore, "BenchmarkModeFrameCount", 60 * 60 * 2, 1, kMaxU32,
+											   "How many frames the benchmark will run before it quits");
+
+NumericCVar<F32> g_lod0MaxDistanceCVar(CVarSubsystem::kCore, "Lod0MaxDistance", 20.0f, 1.0f, kMaxF32,
+									   "Distance that will be used to calculate the LOD 0");
+NumericCVar<F32> g_lod1MaxDistanceCVar(CVarSubsystem::kCore, "Lod1MaxDistance", 40.0f, 2.0f, kMaxF32,
+									   "Distance that will be used to calculate the LOD 1");
+
 #if ANKI_PLATFORM_MOBILE
 static StatCounter g_maliGpuActive(StatCategory::kGpuMisc, "Mali active cycles");
 static StatCounter g_maliGpuReadBandwidth(StatCategory::kGpuMisc, "Mali read bandwidth");
 static StatCounter g_maliGpuWriteBandwidth(StatCategory::kGpuMisc, "Mali write bandwidth");
+
+static BoolCVar g_maliHwCountersCVar(CVarSubsystem::kCore, "MaliHwCounters", false, "Enable Mali counters");
 #endif
 
 void* App::statsAllocCallback(void* userData, void* ptr, PtrSize size, [[maybe_unused]] PtrSize alignment)
@@ -120,9 +141,6 @@ App::App(AllocAlignedCallback allocCb, void* allocCbUserData)
 {
 	m_originalAllocCallback = allocCb;
 	m_originalAllocUserData = allocCbUserData;
-
-	// Config set is a bit special so init it ASAP
-	ConfigSet::allocateSingleton(allocCb, allocCbUserData);
 }
 
 App::~App()
@@ -159,7 +177,6 @@ void App::cleanup()
 #endif
 
 	GlobalFrameIndex::freeSingleton();
-	ConfigSet::freeSingleton();
 
 	m_settingsDir.destroy();
 	m_cacheDir.destroy();
@@ -182,7 +199,7 @@ Error App::init()
 
 Error App::initInternal()
 {
-	Logger::getSingleton().enableVerbosity(ConfigSet::getSingleton().getCoreVerboseLog());
+	Logger::getSingleton().enableVerbosity(g_verboseLogCVar.get());
 
 	setSignalHandlers();
 
@@ -234,12 +251,12 @@ Error App::initInternal()
 	}
 #endif
 
-	ANKI_CORE_LOGI("Number of job threads: %u", ConfigSet::getSingleton().getCoreJobThreadCount());
+	ANKI_CORE_LOGI("Number of job threads: %u", g_jobThreadCountCVar.get());
 
-	if(ConfigSet::getSingleton().getCoreBenchmarkMode() && ConfigSet::getSingleton().getGrVsync())
+	if(g_benchmarkModeCVar.get() && g_vsyncCVar.get())
 	{
 		ANKI_CORE_LOGW("Vsync is enabled and benchmark mode as well. Will turn vsync off");
-		ConfigSet::getSingleton().setGrVsync(false);
+		g_vsyncCVar.set(false);
 	}
 
 	GlobalFrameIndex::allocateSingleton();
@@ -255,13 +272,13 @@ Error App::initInternal()
 	// Window
 	//
 	NativeWindowInitInfo nwinit;
-	nwinit.m_width = ConfigSet::getSingleton().getWidth();
-	nwinit.m_height = ConfigSet::getSingleton().getHeight();
+	nwinit.m_width = g_widthCVar.get();
+	nwinit.m_height = g_heightCVar.get();
 	nwinit.m_depthBits = 0;
 	nwinit.m_stencilBits = 0;
-	nwinit.m_fullscreenDesktopRez = ConfigSet::getSingleton().getWindowFullscreen() > 0;
-	nwinit.m_exclusiveFullscreen = ConfigSet::getSingleton().getWindowFullscreen() == 2;
-	nwinit.m_targetFps = ConfigSet::getSingleton().getCoreTargetFps();
+	nwinit.m_fullscreenDesktopRez = g_windowFullscreenCVar.get() > 0;
+	nwinit.m_exclusiveFullscreen = g_windowFullscreenCVar.get() == 2;
+	nwinit.m_targetFps = g_targetFpsCVar.get();
 	NativeWindow::allocateSingleton();
 	ANKI_CHECK(NativeWindow::getSingleton().init(nwinit));
 
@@ -275,7 +292,7 @@ Error App::initInternal()
 	// ThreadPool
 	//
 	const Bool pinThreads = !ANKI_OS_ANDROID;
-	CoreThreadHive::allocateSingleton(ConfigSet::getSingleton().getCoreJobThreadCount(), pinThreads);
+	CoreThreadHive::allocateSingleton(g_jobThreadCountCVar.get(), pinThreads);
 
 	//
 	// Graphics API
@@ -289,11 +306,12 @@ Error App::initInternal()
 	//
 	// Mali HW counters
 	//
-	if(ANKI_STATS_ENABLED && GrManager::getSingleton().getDeviceCapabilities().m_gpuVendor == GpuVendor::kArm
-	   && ConfigSet::getSingleton().getCoreMaliHwCounters())
+#if ANKI_PLATFORM_MOBILE
+	if(ANKI_STATS_ENABLED && GrManager::getSingleton().getDeviceCapabilities().m_gpuVendor == GpuVendor::kArm && g_maliHwCountersCVar.get())
 	{
 		MaliHwCounters::allocateSingleton();
 	}
+#endif
 
 	//
 	// GPU mem
@@ -321,8 +339,8 @@ Error App::initInternal()
 	String shadersPath;
 	getParentFilepath(executableFname, shadersPath);
 	shadersPath += ":";
-	shadersPath += ConfigSet::getSingleton().getRsrcDataPaths();
-	ConfigSet::getSingleton().setRsrcDataPaths(shadersPath);
+	shadersPath += g_dataPathsCVar.get();
+	g_dataPathsCVar.set(shadersPath);
 #endif
 
 	ANKI_CHECK(ResourceManager::allocateSingleton().init(allocCb, allocCbUserData));
@@ -393,7 +411,7 @@ Error App::initDirs()
 	m_cacheDir.sprintf("%s/cache", &m_settingsDir[0]);
 
 	const Bool cacheDirExists = directoryExists(m_cacheDir.toCString());
-	if(ConfigSet::getSingleton().getCoreClearCaches() && cacheDirExists)
+	if(g_clearCachesCVar.get() && cacheDirExists)
 	{
 		ANKI_CORE_LOGI("Will delete the cache dir and start fresh: %s", m_cacheDir.cstr());
 		ANKI_CHECK(removeDirectory(m_cacheDir.toCString()));
@@ -417,7 +435,7 @@ Error App::mainLoop()
 	Second crntTime = prevUpdateTime;
 
 	// Benchmark mode stuff:
-	const Bool benchmarkMode = ConfigSet::getSingleton().getCoreBenchmarkMode();
+	const Bool benchmarkMode = g_benchmarkModeCVar.get();
 	Second aggregatedCpuTime = 0.0;
 	Second aggregatedGpuTime = 0.0;
 	constexpr U32 kBenchmarkFramesToGatherBeforeFlush = 60;
@@ -465,14 +483,14 @@ Error App::mainLoop()
 			// If we get stats exclude the time of GR because it forces some GPU-CPU serialization. We don't want to
 			// count that
 			Second grTime = 0.0;
-			if(benchmarkMode || ConfigSet::getSingleton().getCoreDisplayStats() > 0) [[unlikely]]
+			if(benchmarkMode || g_displayStatsCVar.get() > 0) [[unlikely]]
 			{
 				grTime = HighRezTimer::getCurrentTime();
 			}
 
 			GrManager::getSingleton().swapBuffers();
 
-			if(benchmarkMode || ConfigSet::getSingleton().getCoreDisplayStats() > 0) [[unlikely]]
+			if(benchmarkMode || g_displayStatsCVar.get() > 0) [[unlikely]]
 			{
 				grTime = HighRezTimer::getCurrentTime() - grTime;
 			}
@@ -497,7 +515,7 @@ Error App::mainLoop()
 			g_cpuTotalTime.set((frameTime - grTime) * 1000.0);
 			if(!benchmarkMode) [[likely]]
 			{
-				const Second timerTick = 1.0_sec / Second(ConfigSet::getSingleton().getCoreTargetFps());
+				const Second timerTick = 1.0_sec / Second(g_targetFpsCVar.get());
 				if(frameTime < timerTick)
 				{
 					ANKI_TRACE_SCOPED_EVENT(TimerTickSleep);
@@ -523,7 +541,7 @@ Error App::mainLoop()
 			}
 
 			// Stats
-			if(ConfigSet::getSingleton().getCoreDisplayStats() > 0)
+			if(g_displayStatsCVar.get() > 0)
 			{
 #if ANKI_PLATFORM_MOBILE
 				if(MaliHwCounters::isAllocated())
@@ -537,8 +555,7 @@ Error App::mainLoop()
 #endif
 
 				StatsUi& statsUi = *static_cast<StatsUi*>(m_statsUi.get());
-				const StatsUiDetail detail =
-					(ConfigSet::getSingleton().getCoreDisplayStats() == 1) ? StatsUiDetail::kFpsOnly : StatsUiDetail::kDetailed;
+				const StatsUiDetail detail = (g_displayStatsCVar.get() == 1) ? StatsUiDetail::kFpsOnly : StatsUiDetail::kDetailed;
 				statsUi.setStatsDetail(detail);
 
 				StatsSet::getSingleton().endFrame();
@@ -548,7 +565,7 @@ Error App::mainLoop()
 
 			if(benchmarkMode) [[unlikely]]
 			{
-				if(GlobalFrameIndex::getSingleton().m_value >= ConfigSet::getSingleton().getCoreBenchmarkModeFrameCount())
+				if(GlobalFrameIndex::getSingleton().m_value >= g_benchmarkModeFrameCountCVar.get())
 				{
 					quit = true;
 				}
@@ -572,9 +589,9 @@ Error App::mainLoop()
 void App::injectUiElements(CoreDynamicArray<UiQueueElement>& newUiElementArr, RenderQueue& rqueue)
 {
 	const U32 originalCount = rqueue.m_uis.getSize();
-	if(ConfigSet::getSingleton().getCoreDisplayStats() > 0 || m_consoleEnabled)
+	if(g_displayStatsCVar.get() > 0 || m_consoleEnabled)
 	{
-		const U32 extraElements = (ConfigSet::getSingleton().getCoreDisplayStats() > 0) + (m_consoleEnabled != 0);
+		const U32 extraElements = (g_displayStatsCVar.get() > 0) + (m_consoleEnabled != 0);
 		newUiElementArr.resize(originalCount + extraElements);
 
 		if(originalCount > 0)
@@ -586,7 +603,7 @@ void App::injectUiElements(CoreDynamicArray<UiQueueElement>& newUiElementArr, Re
 	}
 
 	U32 count = originalCount;
-	if(ConfigSet::getSingleton().getCoreDisplayStats() > 0)
+	if(g_displayStatsCVar.get() > 0)
 	{
 		newUiElementArr[count].m_userData = m_statsUi.get();
 		newUiElementArr[count].m_drawCallback = [](CanvasPtr& canvas, void* userData) -> void {
@@ -607,7 +624,7 @@ void App::injectUiElements(CoreDynamicArray<UiQueueElement>& newUiElementArr, Re
 
 void App::initMemoryCallbacks(AllocAlignedCallback& allocCb, void*& allocCbUserData)
 {
-	if(ANKI_STATS_ENABLED && ConfigSet::getSingleton().getCoreDisplayStats() > 1)
+	if(ANKI_STATS_ENABLED && g_displayStatsCVar.get() > 1)
 	{
 		allocCb = statsAllocCallback;
 		allocCbUserData = this;

+ 6 - 1
AnKi/Core/App.h

@@ -5,7 +5,7 @@
 
 #pragma once
 
-#include <AnKi/Core/Common.h>
+#include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Util/String.h>
 #include <AnKi/Util/Ptr.h>
 #include <AnKi/Ui/UiImmediateModeBuilder.h>
@@ -15,6 +15,11 @@ namespace anki {
 // Forward
 class UiQueueElement;
 class RenderQueue;
+extern NumericCVar<U32> g_windowFullscreenCVar;
+extern NumericCVar<U32> g_targetFpsCVar;
+extern NumericCVar<F32> g_lod0MaxDistanceCVar;
+extern NumericCVar<F32> g_lod1MaxDistanceCVar;
+extern NumericCVar<U32> g_displayStatsCVar;
 
 /// The core class of the engine.
 class App

+ 69 - 200
AnKi/Core/ConfigSet.cpp

@@ -14,238 +14,107 @@
 
 namespace anki {
 
-ConfigSet::~ConfigSet()
-{
-#define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
-	if(m_##name.m_value) \
-	{ \
-		m_pool.free(m_##name.m_value); \
-	}
-#include <AnKi/Core/AllConfigVars.defs.h>
-
-#if ANKI_EXTRA_CHECKS
-	for(const Var& var : m_vars)
-	{
-		if(var.m_timesAccessed.load() == 0)
-		{
-			ANKI_CORE_LOGW("Config var doesn't appear to have been accessed. Maybe unused: %s", var.m_name.cstr());
-		}
-	}
-#endif
-}
+static constexpr Array<CString, U32(CVarSubsystem::kCount)> g_cvarSubsystemNames = {"Core", "R", "Gr", "Rsrc", "Scene"};
 
-void ConfigSet::init(AllocAlignedCallback allocCb, void* allocCbUserData)
+void CVar::getFullNameInternal(Array<Char, 256>& arr) const
 {
-	ANKI_ASSERT(!isInitialized());
-	m_pool.init(allocCb, allocCbUserData);
-
-#define ANKI_CONFIG_VAR_NUMERIC(name, defaultValue, minValue, maxValue, description) \
-	ANKI_ASSERT((minValue) <= (maxValue) && (defaultValue) >= (minValue) && (defaultValue) <= (maxValue)); \
-	m_##name.m_name = #name; \
-	m_##name.m_description = description; \
-	m_##name.m_value = defaultValue; \
-	m_##name.m_min = minValue; \
-	m_##name.m_max = maxValue; \
-	m_vars.pushBack(&m_##name);
-
-#define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_NUMERIC(name, defaultValue, minValue, maxValue, description)
-
-#define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_NUMERIC(name, defaultValue, minValue, maxValue, description)
-
-#define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_NUMERIC(name, defaultValue, minValue, maxValue, description)
-
-#define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_NUMERIC(name, defaultValue, minValue, maxValue, description)
-
-#define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) \
-	m_##name.m_name = #name; \
-	m_##name.m_description = description; \
-	m_##name.m_value = defaultValue; \
-	m_vars.pushBack(&m_##name);
-
-#define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
-	m_##name.m_name = #name; \
-	m_##name.m_description = description; \
-	setStringVar(defaultValue, m_##name); \
-	m_vars.pushBack(&m_##name);
-
-#include <AnKi/Core/AllConfigVars.defs.h>
+	snprintf(arr.getBegin(), arr.getSize(), "%s.%s", g_cvarSubsystemNames[m_subsystem].cstr(), m_name.cstr());
 }
 
-ConfigSet::Var* ConfigSet::tryFind(CString optionName)
+CoreString CVar::getFullName() const
 {
-	for(auto it = m_vars.getBegin(); it != m_vars.getEnd(); ++it)
-	{
-		if((*it).m_name == optionName)
-		{
-			return &(*it);
-		}
-	}
-
-	return nullptr;
-}
-
-const ConfigSet::Var* ConfigSet::tryFind(CString optionName) const
-{
-	for(auto it = m_vars.getBegin(); it != m_vars.getEnd(); ++it)
-	{
-		if((*it).m_name == optionName)
-		{
-			return &(*it);
-		}
-	}
-
-	return nullptr;
-}
-
-Error ConfigSet::loadFromFile(CString filename)
-{
-	ANKI_ASSERT(isInitialized());
-
-	ANKI_CORE_LOGI("Loading config file %s", filename.cstr());
-	CoreXmlDocument xml;
-	ANKI_CHECK(xml.loadFile(filename));
-
-	XmlElement rootel;
-	ANKI_CHECK(xml.getChildElement("config", rootel));
-
-	XmlElement el;
-
-#define ANKI_NUMERIC(name) \
-	ANKI_CHECK(rootel.getChildElementOptional(m_##name.m_name, el)); \
-	if(el) \
-	{ \
-		ANKI_CHECK(el.getNumber(m_##name.m_value)); \
-	}
-
-#define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(name)
-#define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(name)
-#define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(name)
-#define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(name)
-
-#define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) \
-	ANKI_CHECK(rootel.getChildElementOptional(m_##name.m_name, el)); \
-	if(el) \
-	{ \
-		CString txt; \
-		ANKI_CHECK(el.getText(txt)); \
-		if(txt == "true") \
-		{ \
-			m_##name.m_value = true; \
-		} \
-		else if(txt == "false") \
-		{ \
-			m_##name.m_value = false; \
-		} \
-		else \
-		{ \
-			ANKI_CORE_LOGE("Wrong value for %s", m_##name.m_name.cstr()); \
-			return Error::kUserData; \
-		} \
-	}
-
-#define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
-	ANKI_CHECK(rootel.getChildElementOptional(m_##name.m_name, el)); \
-	if(el) \
-	{ \
-		CString txt; \
-		ANKI_CHECK(el.getText(txt)); \
-		setStringVar(txt, m_##name); \
-	}
-
-#include <AnKi/Core/AllConfigVars.defs.h>
-#undef ANKI_NUMERIC
-
-	return Error::kNone;
+	CoreString out;
+	out.sprintf("%s.%s", g_cvarSubsystemNames[m_subsystem].cstr(), m_name.cstr());
+	return out;
 }
 
-Error ConfigSet::saveToFile(CString filename) const
+void CVarSet::registerCVar(CVar* cvar)
 {
-	ANKI_ASSERT(isInitialized());
-	ANKI_CORE_LOGI("Saving config file %s", &filename[0]);
-
-	File file;
-	ANKI_CHECK(file.open(filename, FileOpenFlag::kWrite));
-
-	ANKI_CHECK(file.writeTextf("%s\n<config>\n", CoreXmlDocument::kXmlHeader.cstr()));
-
-#define ANKI_NUMERIC_UINT(name) \
-	ANKI_CHECK(file.writeTextf("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
-	ANKI_CHECK(file.writeTextf("\t<%s>%" PRIu64 "</%s>\n", m_##name.m_name.cstr(), U64(m_##name.m_value), m_##name.m_name.cstr()));
-
-#define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
-#define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
-#define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
-#define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
-#define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) \
-	ANKI_CHECK(file.writeTextf("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
-	ANKI_CHECK(file.writeTextf("\t<%s>%s</%s>\n", m_##name.m_name.cstr(), (m_##name.m_value) ? "true" : "false", m_##name.m_name.cstr()));
-#define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
-	ANKI_CHECK(file.writeTextf("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
-	ANKI_CHECK(file.writeTextf("\t<%s>%s</%s>\n", m_##name.m_name.cstr(), m_##name.m_value, m_##name.m_name.cstr()));
-#include <AnKi/Core/AllConfigVars.defs.h>
-#undef ANKI_NUMERIC_UINT
-
-	ANKI_CHECK(file.writeText("</config>\n"));
-	return Error::kNone;
+	m_cvars.pushBack(cvar);
 }
 
-Error ConfigSet::setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[])
+Error CVarSet::setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[])
 {
-	ANKI_ASSERT(isInitialized());
-
 	for(U i = 0; i < cmdLineArgsCount; ++i)
 	{
 		ANKI_ASSERT(cmdLineArgs[i]);
 		const CString varName = cmdLineArgs[i];
 
-		// Set the value
+		// Get the value string
 		++i;
 		if(i >= cmdLineArgsCount)
 		{
 			ANKI_CORE_LOGE("Expecting a command line argument after %s", varName.cstr());
 			return Error::kUserData;
 		}
-
 		ANKI_ASSERT(cmdLineArgs[i]);
 		const CString value = cmdLineArgs[i];
 
-		if(false)
+		// Find the CVar
+		CVar* foundCVar = nullptr;
+		Array<Char, 256> fullnameArr;
+		for(CVar& it : m_cvars)
 		{
+			it.getFullNameInternal(fullnameArr);
+			CString fullname = &fullnameArr[0];
+
+			if(fullname == varName || it.m_name == varName)
+			{
+				if(foundCVar)
+				{
+					ANKI_CORE_LOGW("Command line arg %s has ambiguous name", varName.cstr());
+				}
+				else
+				{
+					foundCVar = &it;
+				}
+			}
 		}
 
-#define ANKI_NUMERIC(type, name) \
-	else if(varName == m_##name.m_name) \
+		if(foundCVar)
+		{
+#define ANKI_CVAR_NUMERIC_SET(type) \
+	case CVar::Type::kNumeric##type: \
 	{ \
 		type v; \
-		ANKI_CHECK(value.toNumber(v)); \
-		set##name(v); \
-	}
-
-#define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(U8, name)
-#define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(U32, name)
-#define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(PtrSize, name)
-#define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC(F32, name)
-
-#define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) \
-	else if(varName == m_##name.m_name) \
-	{ \
-		U32 v; \
-		ANKI_CHECK(value.toNumber(v)); \
-		m_##name.m_value = v != 0; \
-	}
-
-#define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
-	else if(varName == m_##name.m_name) \
-	{ \
-		setStringVar(value, m_##name); \
+		err = value.toNumber(v); \
+		if(!err) \
+		{ \
+			static_cast<NumericCVar<type>&>(*foundCVar).set(v); \
+		} \
+		break; \
 	}
 
-#include <AnKi/Core/AllConfigVars.defs.h>
-#undef ANKI_NUMERIC
+			Error err = Error::kNone;
+			switch(foundCVar->m_type)
+			{
+			case CVar::Type::kString:
+				static_cast<StringCVar&>(*foundCVar).set(value);
+				break;
+			case CVar::Type::kBool:
+			{
+				U32 v;
+				err = value.toNumber(v);
+				if(!err)
+				{
+					static_cast<BoolCVar&>(*foundCVar).set(v != 0);
+				}
+				break;
+			}
+				ANKI_CVAR_NUMERIC_SET(U8)
+				ANKI_CVAR_NUMERIC_SET(U32)
+				ANKI_CVAR_NUMERIC_SET(PtrSize)
+				ANKI_CVAR_NUMERIC_SET(F32)
+			default:
+				ANKI_ASSERT(0);
+			}
+
+			if(err)
+			{
+				foundCVar->getFullNameInternal(fullnameArr);
+				ANKI_CORE_LOGE("Wrong value for %s. Value will not be set", &fullnameArr[0]);
+			}
+		}
 		else
 		{
 			ANKI_CORE_LOGW("Can't recognize command line argument: %s. Skipping", varName.cstr());

+ 164 - 119
AnKi/Core/ConfigSet.h

@@ -9,6 +9,7 @@
 #include <AnKi/Util/List.h>
 #include <AnKi/Util/String.h>
 #include <AnKi/Util/Singleton.h>
+#include <AnKi/Util/Enum.h>
 #include <AnKi/Math/Functions.h>
 
 namespace anki {
@@ -16,163 +17,207 @@ namespace anki {
 /// @addtogroup core
 /// @{
 
-/// A storage of configuration variables.
-class ConfigSet : public MakeSingleton<ConfigSet>
+enum class CVarSubsystem : U32
 {
-	template<typename>
-	friend class MakeSingleton;
+	kCore,
+	kRenderer,
+	kGr,
+	kResource,
+	kScene,
+
+	kCount,
+	kFirst = 0
+};
+ANKI_ENUM_ALLOW_NUMERIC_OPERATIONS(CVarSubsystem)
+
+/// Config variable base.
+class CVar : public IntrusiveListEnabled<CVar>
+{
+	friend class CVarSet;
 
 public:
-	ConfigSet(const ConfigSet& b) = delete; // Non-copyable
+	CVar(const CVar&) = delete;
 
-	ConfigSet& operator=(const ConfigSet& b) = delete; // Non-copyable
+	CVar& operator=(const CVar&) = delete;
 
-	Error loadFromFile(CString filename);
+	CoreString getFullName() const;
 
-	Error saveToFile(CString filename) const;
+protected:
+	CString m_name;
+	CString m_descr;
+	CVarSubsystem m_subsystem;
 
-	Error setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[]);
+	enum class Type : U32
+	{
+		kString,
+		kBool,
+		kNumericU8,
+		kNumericU32,
+		kNumericPtrSize,
+		kNumericF32
+	};
 
-	// Define getters and setters
-#if ANKI_EXTRA_CHECKS
-#	define ANKI_CONFIG_VAR_GET(type, name, defaultValue, minValue, maxValue, description) \
-		type get##name() const \
-		{ \
-			ANKI_ASSERT(isInitialized()); \
-			m_##name.m_timesAccessed.fetchAdd(1); \
-			return m_##name.m_value; \
-		}
-#else
-#	define ANKI_CONFIG_VAR_GET(type, name, defaultValue, minValue, maxValue, description) \
-		type get##name() const \
-		{ \
-			ANKI_ASSERT(isInitialized()); \
-			return m_##name.m_value; \
-		}
-#endif
-#define ANKI_CONFIG_VAR_SET(type, name, defaultValue, minValue, maxValue, description) \
-	void set##name(type value) \
-	{ \
-		ANKI_ASSERT(isInitialized()); \
-		const type newValue = clamp(value, m_##name.m_min, m_##name.m_max); \
-		if(newValue != value) \
-		{ \
-			ANKI_CORE_LOGW("Out of range value set for config var: %s", m_##name.m_name.cstr()); \
-		} \
-		m_##name.m_value = newValue; \
-	}
-#define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_GET(U8, name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_SET(U8, name, defaultValue, minValue, maxValue, description)
-#define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_GET(U32, name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_SET(U32, name, defaultValue, minValue, maxValue, description)
-#define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_GET(PtrSize, name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_SET(PtrSize, name, defaultValue, minValue, maxValue, description)
-#define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_GET(F32, name, defaultValue, minValue, maxValue, description) \
-	ANKI_CONFIG_VAR_SET(F32, name, defaultValue, minValue, maxValue, description)
-#define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) \
-	ANKI_CONFIG_VAR_GET(Bool, name, defaultValue, minValue, maxValue, description) \
-	void set##name(Bool value) \
-	{ \
-		ANKI_ASSERT(isInitialized()); \
-		m_##name.m_value = value; \
-	}
-#define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
-	ANKI_CONFIG_VAR_GET(CString, name, defaultValue, minValue, maxValue, description) \
-	void set##name(CString value) \
-	{ \
-		ANKI_ASSERT(isInitialized()); \
-		setStringVar(value, m_##name); \
+	Type m_type;
+
+	CVar(Type type, CVarSubsystem subsystem, CString name, CString descr = {})
+		: m_name(name)
+		, m_descr((!descr.isEmpty()) ? descr : "No description")
+		, m_subsystem(subsystem)
+		, m_type(type)
+	{
+		ANKI_ASSERT(subsystem < CVarSubsystem::kCount);
+		registerSelf();
 	}
-#include <AnKi/Core/AllConfigVars.defs.h>
-#undef ANKI_CONFIG_VAR_GET
-#undef ANKI_CONFIG_VAR_SET
 
 private:
-	class Var : public IntrusiveListEnabled<Var>
-	{
-	public:
-		CString m_name;
-		CString m_description;
-#if ANKI_EXTRA_CHECKS
-		mutable Atomic<U32> m_timesAccessed = {0};
-#endif
-	};
+	void registerSelf();
 
-	template<typename T>
-	class NumberVar : public Var
+	void getFullNameInternal(Array<Char, 256>& arr) const;
+};
+
+/// Numeric config variable.
+template<typename TNumber>
+class NumericCVar : public CVar
+{
+public:
+	NumericCVar(CVarSubsystem subsystem, CString name, TNumber defaultVal, TNumber min = getMinNumericLimit<TNumber>(),
+				TNumber max = getMaxNumericLimit<TNumber>(), CString descr = CString())
+		: CVar(getCVarType(), subsystem, name, descr)
+		, m_value(defaultVal)
+		, m_min(min)
+		, m_max(max)
 	{
-	public:
-		T m_value;
-		T m_min;
-		T m_max;
-	};
+		ANKI_ASSERT(min <= max);
+		ANKI_ASSERT(defaultVal >= min && defaultVal <= max);
+	}
 
-	class StringVar : public Var
+	void set(TNumber val)
 	{
-	public:
-		Char* m_value = nullptr;
-	};
+		const TNumber newVal = clamp(val, m_min, m_max);
+		if(newVal != val)
+		{
+			ANKI_CORE_LOGW("Out of range value set for config var: %s", m_name.cstr());
+		}
+		m_value = newVal;
+	}
 
-	class BoolVar : public Var
+	TNumber get() const
 	{
-	public:
-		Bool m_value;
-	};
+		return m_value;
+	}
+
+private:
+	TNumber m_value;
+	TNumber m_min;
+	TNumber m_max;
+
+	static Type getCVarType();
+};
 
-	HeapMemoryPool m_pool;
-	IntrusiveList<Var> m_vars;
+#define ANKI_CVAR_NUMERIC_TYPE(type) \
+	template<> \
+	inline CVar::Type NumericCVar<type>::getCVarType() \
+	{ \
+		return Type::kNumeric##type; \
+	}
 
-#define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) NumberVar<U8> m_##name;
-#define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) NumberVar<U32> m_##name;
-#define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) NumberVar<PtrSize> m_##name;
-#define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) NumberVar<F32> m_##name;
-#define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) BoolVar m_##name;
-#define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) StringVar m_##name;
-#include <AnKi/Core/AllConfigVars.defs.h>
+ANKI_CVAR_NUMERIC_TYPE(U8)
+ANKI_CVAR_NUMERIC_TYPE(U32)
+ANKI_CVAR_NUMERIC_TYPE(PtrSize)
+ANKI_CVAR_NUMERIC_TYPE(F32)
+#undef ANKI_CVAR_NUMERIC_TYPE
 
-	ConfigSet(AllocAlignedCallback allocCb, void* allocCbUserData)
+/// String config variable.
+class StringCVar : public CVar
+{
+public:
+	StringCVar(CVarSubsystem subsystem, CString name, CString value, CString descr = CString())
+		: CVar(Type::kString, subsystem, name, descr)
 	{
-		init(allocCb, allocCbUserData);
+		set(value);
 	}
 
-	~ConfigSet();
+	~StringCVar()
+	{
+		if(m_str)
+		{
+			free(m_str);
+		}
+	}
 
-	void init(AllocAlignedCallback allocCb, void* allocCbUserData);
+	void set(CString name)
+	{
+		ANKI_ASSERT(name.getLength() > 0);
+		if(m_str)
+		{
+			free(m_str);
+		}
+		const U len = name.getLength();
+		m_str = static_cast<Char*>(malloc(len + 1));
+		memcpy(m_str, name.cstr(), len + 1);
+	}
 
-	Bool isInitialized() const
+	CString get() const
 	{
-		return !m_vars.isEmpty();
+		return m_str;
 	}
 
-	Var* tryFind(CString name);
-	const Var* tryFind(CString name) const;
+private:
+	Char* m_str;
+};
 
-	Var& find(CString name)
+/// Boolean config variable.
+class BoolCVar : public CVar
+{
+public:
+	BoolCVar(CVarSubsystem subsystem, CString name, Bool defaultVal, CString descr = CString())
+		: CVar(Type::kBool, subsystem, name, descr)
+		, m_val(defaultVal)
 	{
-		Var* o = tryFind(name);
-		ANKI_ASSERT(o && "Couldn't find config option");
-		return *o;
 	}
 
-	const Var& find(CString name) const
+	void set(Bool val)
 	{
-		const Var* o = tryFind(name);
-		ANKI_ASSERT(o && "Couldn't find config option");
-		return *o;
+		m_val = val;
 	}
 
-	void setStringVar(CString val, StringVar& var)
+	Bool get() const
 	{
-		m_pool.free(var.m_value);
-		const U32 len = val.getLength();
-		var.m_value = static_cast<Char*>(m_pool.allocate(len + 1, alignof(Char)));
-		memcpy(var.m_value, val.getBegin(), len + 1);
+		return m_val;
 	}
+
+private:
+	Bool m_val;
+};
+
+/// Access all configuration variables.
+class CVarSet : public MakeSingletonLazyInit<CVarSet>
+{
+	friend class CVar;
+
+public:
+	CVarSet() = default;
+
+	CVarSet(const CVarSet& b) = delete; // Non-copyable
+
+	CVarSet& operator=(const CVarSet& b) = delete; // Non-copyable
+
+	Error loadFromFile(CString filename);
+
+	Error saveToFile(CString filename) const;
+
+	Error setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[]);
+
+private:
+	IntrusiveList<CVar> m_cvars;
+
+	void registerCVar(CVar* var);
 };
+
+inline void CVar::registerSelf()
+{
+	CVarSet::getSingleton().registerCVar(this);
+}
 /// @}
 
 } // end namespace anki

+ 0 - 24
AnKi/Core/ConfigVars.defs.h

@@ -1,24 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-ANKI_CONFIG_VAR_GROUP(CORE)
-
-ANKI_CONFIG_VAR_PTR_SIZE(CoreRebarGpuMemorySize, 24_MB, 1_MB, 1_GB, "ReBAR: always mapped GPU memory")
-ANKI_CONFIG_VAR_PTR_SIZE(CoreGlobalVertexMemorySize, 128_MB, 16_MB, 2_GB, "Global index and vertex buffer size")
-ANKI_CONFIG_VAR_PTR_SIZE(CoreGpuSceneInitialSize, 64_MB, 16_MB, 2_GB, "Global memory for the GPU scene")
-
-ANKI_CONFIG_VAR_BOOL(CoreMaliHwCounters, false, "Enable Mali counters")
-
-ANKI_CONFIG_VAR_U32(Width, 1920, 16, 16 * 1024, "Width")
-ANKI_CONFIG_VAR_U32(Height, 1080, 16, 16 * 1024, "Height")
-ANKI_CONFIG_VAR_U32(WindowFullscreen, 1, 0, 2, "0: windowed, 1: borderless fullscreen, 2: exclusive fullscreen")
-
-ANKI_CONFIG_VAR_U32(CoreTargetFps, 60u, 1u, kMaxU32, "Target FPS")
-ANKI_CONFIG_VAR_U32(CoreJobThreadCount, max(2u, getCpuCoresCount() / 2u), 2u, 1024u, "Number of job thread")
-ANKI_CONFIG_VAR_U32(CoreDisplayStats, 0, 0, 2, "Display stats, 0: None, 1: Simple, 2: Detailed")
-ANKI_CONFIG_VAR_BOOL(CoreClearCaches, false, "Clear all caches")
-ANKI_CONFIG_VAR_BOOL(CoreVerboseLog, false, "Verbose logging")
-ANKI_CONFIG_VAR_BOOL(CoreBenchmarkMode, false, "Run in a benchmark mode. Fixed timestep, unlimited target FPS")
-ANKI_CONFIG_VAR_U32(CoreBenchmarkModeFrameCount, 60 * 60 * 2, 1, kMaxU32, "How many frames the benchmark will run before it quits")

+ 4 - 1
AnKi/Core/GpuMemory/GpuSceneBuffer.cpp

@@ -17,9 +17,12 @@ static StatCounter g_gpuSceneBufferAllocatedSize(StatCategory::kGpuMem, "GPU sce
 static StatCounter g_gpuSceneBufferTotal(StatCategory::kGpuMem, "GPU scene total", StatFlag::kBytes);
 static StatCounter g_gpuSceneBufferFragmentation(StatCategory::kGpuMem, "GPU scene fragmentation", StatFlag::kFloat);
 
+static NumericCVar<PtrSize> g_gpuSceneInitialSizeCVar(CVarSubsystem::kCore, "GpuSceneInitialSize", 64_MB, 16_MB, 2_GB,
+													  "Global memory for the GPU scene");
+
 void GpuSceneBuffer::init()
 {
-	const PtrSize poolSize = ConfigSet::getSingleton().getCoreGpuSceneInitialSize();
+	const PtrSize poolSize = g_gpuSceneInitialSizeCVar.get();
 
 	const Array classes = {32_B, 64_B, 128_B, 256_B, poolSize};
 

+ 4 - 1
AnKi/Core/GpuMemory/RebarTransientMemoryPool.cpp

@@ -14,6 +14,9 @@ namespace anki {
 
 static StatCounter g_rebarUserMemory(StatCategory::kGpuMem, "ReBAR used mem", StatFlag::kBytes);
 
+static NumericCVar<PtrSize> g_rebarGpuMemorySizeCvar(CVarSubsystem::kCore, "RebarGpuMemorySize", 24_MB, 1_MB, 1_GB,
+													 "ReBAR: always mapped GPU memory");
+
 RebarTransientMemoryPool::~RebarTransientMemoryPool()
 {
 	GrManager::getSingleton().finish();
@@ -26,7 +29,7 @@ void RebarTransientMemoryPool::init()
 {
 	BufferInitInfo buffInit("ReBar");
 	buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
-	buffInit.m_size = ConfigSet::getSingleton().getCoreRebarGpuMemorySize();
+	buffInit.m_size = g_rebarGpuMemorySizeCvar.get();
 	buffInit.m_usage = BufferUsageBit::kAllUniform | BufferUsageBit::kAllStorage | BufferUsageBit::kVertex | BufferUsageBit::kIndex
 					   | BufferUsageBit::kShaderBindingTable | BufferUsageBit::kAllIndirect;
 	m_buffer = GrManager::getSingleton().newBuffer(buffInit);

+ 4 - 1
AnKi/Core/GpuMemory/UnifiedGeometryBuffer.cpp

@@ -14,9 +14,12 @@ static StatCounter g_unifiedGeomBufferAllocatedSize(StatCategory::kGpuMem, "UGB
 static StatCounter g_unifiedGeomBufferTotal(StatCategory::kGpuMem, "UGB total", StatFlag::kBytes);
 static StatCounter g_unifiedGeomBufferFragmentation(StatCategory::kGpuMem, "UGB fragmentation", StatFlag::kFloat);
 
+static NumericCVar<PtrSize> g_unifiedGometryBufferSizeCvar(CVarSubsystem::kCore, "UnifiedGeometryBufferSize", 128_MB, 16_MB, 2_GB,
+														   "Global index and vertex buffer size");
+
 void UnifiedGeometryBuffer::init()
 {
-	const PtrSize poolSize = ConfigSet::getSingleton().getCoreGlobalVertexMemorySize();
+	const PtrSize poolSize = g_unifiedGometryBufferSizeCvar.get();
 
 	const Array classes = {1_KB, 8_KB, 32_KB, 128_KB, 512_KB, 4_MB, 8_MB, 16_MB, poolSize};
 

+ 0 - 23
AnKi/Gr/ConfigVars.defs.h

@@ -1,23 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-ANKI_CONFIG_VAR_GROUP(GR)
-
-ANKI_CONFIG_VAR_BOOL(GrValidation, false, "Enable or not validation")
-ANKI_CONFIG_VAR_BOOL(GrDebugPrintf, false, "Enable or not debug printf")
-ANKI_CONFIG_VAR_BOOL(GrDebugMarkers, false, "Enable or not debug markers")
-ANKI_CONFIG_VAR_BOOL(GrVsync, false, "Enable or not vsync")
-ANKI_CONFIG_VAR_U8(GrDevice, 0, 0, 16, "Choose an available device. Devices are sorted by performance")
-
-ANKI_CONFIG_VAR_PTR_SIZE(GrDiskShaderCacheMaxSize, 128_MB, 1_MB, 1_GB, "Max size of the pipeline cache file")
-
-ANKI_CONFIG_VAR_BOOL(GrRayTracing, false, "Try enabling ray tracing")
-ANKI_CONFIG_VAR_BOOL(Gr64bitAtomics, true, "Enable or not 64bit atomics")
-ANKI_CONFIG_VAR_BOOL(GrSamplerFilterMinMax, true, "Enable or not min/max sample filtering")
-ANKI_CONFIG_VAR_BOOL(GrVrs, false, "Enable or not VRS")
-ANKI_CONFIG_VAR_BOOL(GrAsyncCompute, true, "Enable or not async compute")
-
-ANKI_CONFIG_VAR_U8(GrVkMinor, 1, 1, 1, "Vulkan minor version")
-ANKI_CONFIG_VAR_U8(GrVkMajor, 1, 1, 1, "Vulkan major version")

+ 2 - 0
AnKi/Gr/GrManager.h

@@ -8,11 +8,13 @@
 #include <AnKi/Gr/Common.h>
 #include <AnKi/Gr/GrObject.h>
 #include <AnKi/Util/String.h>
+#include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
 
 // Forward
 class NativeWindow;
+extern BoolCVar g_vsyncCVar;
 
 /// @addtogroup graphics
 /// @{

+ 0 - 1
AnKi/Gr/Vulkan/Common.h

@@ -74,7 +74,6 @@ enum class VulkanExtensions : U32
 	kKHR_swapchain = 1 << 6,
 	kKHR_surface = 1 << 7,
 	kEXT_debug_utils = 1 << 8,
-	kAMD_shader_info = 1 << 9,
 	kAMD_rasterization_order = 1 << 10,
 	kKHR_ray_tracing = 1 << 11,
 	kKHR_pipeline_executable_properties = 1 << 12,

+ 38 - 92
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -11,10 +11,23 @@
 #include <AnKi/Gr/Vulkan/FenceImpl.h>
 #include <AnKi/Util/Functions.h>
 #include <AnKi/Util/StringList.h>
-#include <AnKi/Core/ConfigSet.h>
+#include <AnKi/Core/App.h>
 
 namespace anki {
 
+static BoolCVar g_validationCVar(CVarSubsystem::kGr, "Validation", false, "Enable or not validation");
+static BoolCVar g_debugPrintfCVar(CVarSubsystem::kGr, "DebugPrintf", false, "Enable or not debug printf");
+static BoolCVar g_debugMarkersCVar(CVarSubsystem::kGr, "DebugMarkers", false, "Enable or not debug markers");
+BoolCVar g_vsyncCVar(CVarSubsystem::kGr, "Vsync", false, "Enable or not vsync");
+static NumericCVar<U8> g_deviceCVar(CVarSubsystem::kGr, "Device", 0, 0, 16, "Choose an available device. Devices are sorted by performance");
+static BoolCVar g_rayTracingCVar(CVarSubsystem::kGr, "RayTracing", false, "Try enabling ray tracing");
+static BoolCVar g_64bitAtomicsCVar(CVarSubsystem::kGr, "64bitAtomics", true, "Enable or not 64bit atomics");
+static BoolCVar g_samplerFilterMinMaxCVar(CVarSubsystem::kGr, "SamplerFilterMinMax", true, "Enable or not min/max sample filtering");
+static BoolCVar g_vrsCVar(CVarSubsystem::kGr, "Vrs", false, "Enable or not VRS");
+static BoolCVar g_asyncComputeCVar(CVarSubsystem::kGr, "AsyncCompute", true, "Enable or not async compute");
+static NumericCVar<U8> g_vkMinorCVar(CVarSubsystem::kGr, "VkMinor", 1, 1, 1, "Vulkan minor version");
+static NumericCVar<U8> g_vkMajorCVar(CVarSubsystem::kGr, "VkMajor", 1, 1, 1, "Vulkan major version");
+
 // DLSS related
 #define ANKI_VK_NVX_BINARY_IMPORT "VK_NVX_binary_import"
 
@@ -143,7 +156,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		}
 	}
 
-	m_swapchainFactory.init(ConfigSet::getSingleton().getGrVsync());
+	m_swapchainFactory.init(g_vsyncCVar.get());
 
 	m_crntSwapchain = m_swapchainFactory.newInstance();
 
@@ -208,8 +221,8 @@ Error GrManagerImpl::initInstance()
 
 	// Create the instance
 	//
-	const U8 vulkanMinor = ConfigSet::getSingleton().getGrVkMinor();
-	const U8 vulkanMajor = ConfigSet::getSingleton().getGrVkMajor();
+	const U8 vulkanMinor = g_vkMinorCVar.get();
+	const U8 vulkanMajor = g_vkMajorCVar.get();
 
 	VkApplicationInfo app = {};
 	app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -242,7 +255,7 @@ Error GrManagerImpl::initInstance()
 				CString layerName = layer.layerName;
 
 				static constexpr const Char* kValidationName = "VK_LAYER_KHRONOS_validation";
-				if((ConfigSet::getSingleton().getGrValidation() || ConfigSet::getSingleton().getGrDebugPrintf()) && layerName == kValidationName)
+				if((g_validationCVar.get() || g_debugMarkersCVar.get()) && layerName == kValidationName)
 				{
 					layersToEnable.emplaceBack(kValidationName);
 				}
@@ -265,12 +278,12 @@ Error GrManagerImpl::initInstance()
 	// Validation features
 	GrDynamicArray<VkValidationFeatureEnableEXT> enabledValidationFeatures;
 	GrDynamicArray<VkValidationFeatureDisableEXT> disabledValidationFeatures;
-	if(ConfigSet::getSingleton().getGrDebugPrintf())
+	if(g_debugPrintfCVar.get())
 	{
 		enabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT);
 	}
 
-	if(!ConfigSet::getSingleton().getGrValidation())
+	if(!g_validationCVar.get())
 	{
 		disabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_DISABLE_ALL_EXT);
 	}
@@ -350,8 +363,7 @@ Error GrManagerImpl::initInstance()
 				instExtensions[instExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;
 			}
 			else if(extensionName == VK_EXT_DEBUG_UTILS_EXTENSION_NAME
-					&& (ConfigSet::getSingleton().getGrDebugMarkers() || ConfigSet::getSingleton().getGrValidation()
-						|| ConfigSet::getSingleton().getGrDebugPrintf()))
+					&& (g_debugMarkersCVar.get() || g_validationCVar.get() || g_debugPrintfCVar.get()))
 			{
 				m_extensions |= VulkanExtensions::kEXT_debug_utils;
 				instExtensions[instExtensionCount++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
@@ -468,7 +480,7 @@ Error GrManagerImpl::initInstance()
 			}
 		});
 
-		const U32 chosenPhysDevIdx = min<U32>(ConfigSet::getSingleton().getGrDevice(), devs.getSize() - 1);
+		const U32 chosenPhysDevIdx = min<U32>(g_deviceCVar.get(), devs.getSize() - 1);
 
 		ANKI_VK_LOGI("Physical devices:");
 		for(U32 devIdx = 0; devIdx < count; ++devIdx)
@@ -597,7 +609,7 @@ Error GrManagerImpl::initDevice()
 		return Error::kFunctionFailed;
 	}
 
-	if(!ConfigSet::getSingleton().getGrAsyncCompute())
+	if(!g_asyncComputeCVar.get())
 	{
 		m_queueFamilyIndices[VulkanQueueType::kCompute] = kMaxU32;
 	}
@@ -659,44 +671,39 @@ Error GrManagerImpl::initDevice()
 				m_extensions |= VulkanExtensions::kKHR_swapchain;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_AMD_SHADER_INFO_EXTENSION_NAME && ConfigSet::getSingleton().getCoreDisplayStats())
-			{
-				m_extensions |= VulkanExtensions::kAMD_shader_info;
-				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
-			}
 			else if(extensionName == VK_AMD_RASTERIZATION_ORDER_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::kAMD_rasterization_order;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME && ConfigSet::getSingleton().getGrRayTracing())
+			else if(extensionName == VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME && g_rayTracingCVar.get())
 			{
 				m_extensions |= VulkanExtensions::kKHR_ray_tracing;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 				m_capabilities.m_rayTracingEnabled = true;
 			}
-			else if(extensionName == VK_KHR_RAY_QUERY_EXTENSION_NAME && ConfigSet::getSingleton().getGrRayTracing())
+			else if(extensionName == VK_KHR_RAY_QUERY_EXTENSION_NAME && g_rayTracingCVar.get())
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME && ConfigSet::getSingleton().getGrRayTracing())
+			else if(extensionName == VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME && g_rayTracingCVar.get())
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME && ConfigSet::getSingleton().getGrRayTracing())
+			else if(extensionName == VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME && g_rayTracingCVar.get())
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME && ConfigSet::getSingleton().getGrRayTracing())
+			else if(extensionName == VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME && g_rayTracingCVar.get())
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME && ConfigSet::getSingleton().getCoreDisplayStats() > 1)
+			else if(extensionName == VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME && g_displayStatsCVar.get() > 1)
 			{
 				m_extensions |= VulkanExtensions::kKHR_pipeline_executable_properties;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME && ConfigSet::getSingleton().getGrDebugPrintf())
+			else if(extensionName == VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME && g_debugPrintfCVar.get())
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
@@ -725,7 +732,7 @@ Error GrManagerImpl::initDevice()
 				m_extensions |= VulkanExtensions::kKHR_shader_float16_int8;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME && ConfigSet::getSingleton().getGr64bitAtomics())
+			else if(extensionName == VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME && g_64bitAtomicsCVar.get())
 			{
 				m_extensions |= VulkanExtensions::kKHR_shader_atomic_int64;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
@@ -740,7 +747,7 @@ Error GrManagerImpl::initDevice()
 				m_extensions |= VulkanExtensions::kKHR_shader_float_controls;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME && ConfigSet::getSingleton().getGrSamplerFilterMinMax())
+			else if(extensionName == VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME && g_samplerFilterMinMaxCVar.get())
 			{
 				m_extensions |= VulkanExtensions::kKHR_sampler_filter_min_max;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
@@ -750,7 +757,7 @@ Error GrManagerImpl::initDevice()
 				m_extensions |= VulkanExtensions::kKHR_create_renderpass_2;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME && ConfigSet::getSingleton().getGrVrs())
+			else if(extensionName == VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME && g_vrsCVar.get())
 			{
 				m_extensions |= VulkanExtensions::kKHR_fragment_shading_rate;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
@@ -808,7 +815,7 @@ Error GrManagerImpl::initDevice()
 		devFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
 		vkGetPhysicalDeviceFeatures2(m_physicalDevice, &devFeatures);
 		m_devFeatures = devFeatures.features;
-		m_devFeatures.robustBufferAccess = (ConfigSet::getSingleton().getGrValidation() && m_devFeatures.robustBufferAccess) ? true : false;
+		m_devFeatures.robustBufferAccess = (g_validationCVar.get() && m_devFeatures.robustBufferAccess) ? true : false;
 		ANKI_VK_LOGI("Robust buffer access is %s", (m_devFeatures.robustBufferAccess) ? "enabled" : "disabled");
 
 		ci.pEnabledFeatures = &m_devFeatures;
@@ -891,8 +898,7 @@ Error GrManagerImpl::initDevice()
 		features.pNext = &m_deviceBufferFeatures;
 		vkGetPhysicalDeviceFeatures2(m_physicalDevice, &features);
 
-		m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay =
-			m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay && ConfigSet::getSingleton().getGrDebugMarkers();
+		m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay = m_deviceBufferFeatures.bufferDeviceAddressCaptureReplay && g_debugMarkersCVar.get();
 		m_deviceBufferFeatures.bufferDeviceAddressMultiDevice = false;
 
 		m_deviceBufferFeatures.pNext = const_cast<void*>(ci.pNext);
@@ -1111,16 +1117,6 @@ Error GrManagerImpl::initDevice()
 
 	ANKI_VK_CHECK(vkCreateDevice(m_physicalDevice, &ci, nullptr, &m_device));
 
-	// Get VK_AMD_shader_info entry points
-	if(!!(m_extensions & VulkanExtensions::kAMD_shader_info))
-	{
-		m_pfnGetShaderInfoAMD = reinterpret_cast<PFN_vkGetShaderInfoAMD>(vkGetDeviceProcAddr(m_device, "vkGetShaderInfoAMD"));
-		if(!m_pfnGetShaderInfoAMD)
-		{
-			ANKI_VK_LOGW("VK_AMD_shader_info is present but vkGetShaderInfoAMD is not there");
-		}
-	}
-
 	if(!(m_extensions & VulkanExtensions::kKHR_spirv_1_4))
 	{
 		ANKI_VK_LOGE(VK_KHR_SPIRV_1_4_EXTENSION_NAME " is not supported");
@@ -1520,66 +1516,16 @@ VkBool32 GrManagerImpl::debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBi
 	return false;
 }
 
-void GrManagerImpl::printPipelineShaderInfo(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash) const
+void GrManagerImpl::printPipelineShaderInfo(VkPipeline ppline, CString name, U64 hash) const
 {
-	if(printPipelineShaderInfoInternal(ppline, name, stages, hash))
+	if(printPipelineShaderInfoInternal(ppline, name, hash))
 	{
 		ANKI_VK_LOGE("Ignoring previous errors");
 	}
 }
 
-Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash) const
+Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString name, U64 hash) const
 {
-	if(m_pfnGetShaderInfoAMD)
-	{
-		VkShaderStatisticsInfoAMD stats = {};
-
-		LockGuard<SpinLock> lock(m_shaderStatsFileMtx);
-
-		// Open the file
-		if(!m_shaderStatsFile.isOpen())
-		{
-			ANKI_CHECK(m_shaderStatsFile.open(GrString().sprintf("%s/../ppline_stats.csv", m_cacheDir.cstr()).toCString(), FileOpenFlag::kWrite));
-
-			ANKI_CHECK(m_shaderStatsFile.writeText("ppline name,hash,"
-												   "stage 0 VGPR,stage 0 SGPR,"
-												   "stage 1 VGPR,stage 1 SGPR,"
-												   "stage 2 VGPR,stage 2 SGPR,"
-												   "stage 3 VGPR,stage 3 SGPR,"
-												   "stage 4 VGPR,stage 4 SGPR,"
-												   "stage 5 VGPR,stage 5 SGPR\n"));
-		}
-
-		ANKI_CHECK(m_shaderStatsFile.writeTextf("%s,0x%" PRIx64 ",", name.cstr(), hash));
-
-		GrString str;
-
-		for(ShaderType type = ShaderType::kFirst; type < ShaderType::kCount; ++type)
-		{
-			ShaderTypeBit stage = stages & ShaderTypeBit(1 << type);
-			if(!stage)
-			{
-				ANKI_CHECK(m_shaderStatsFile.writeText((type != ShaderType::kLast) ? "0,0," : "0,0\n"));
-				continue;
-			}
-
-			size_t size = sizeof(stats);
-			ANKI_VK_CHECK(m_pfnGetShaderInfoAMD(m_device, ppline, VkShaderStageFlagBits(convertShaderTypeBit(stage)),
-												VK_SHADER_INFO_TYPE_STATISTICS_AMD, &size, &stats));
-
-			str += GrString().sprintf("Stage %u: VGRPS %02u, SGRPS %02u ", U32(type), stats.resourceUsage.numUsedVgprs,
-									  stats.resourceUsage.numUsedSgprs);
-
-			ANKI_CHECK(m_shaderStatsFile.writeTextf((type != ShaderType::kLast) ? "%u,%u," : "%u,%u\n", stats.resourceUsage.numUsedVgprs,
-													stats.resourceUsage.numUsedSgprs));
-		}
-
-		ANKI_VK_LOGV("Pipeline \"%s\" (0x%016" PRIx64 ") stats: %s", name.cstr(), hash, str.cstr());
-
-		// Flush the file just in case
-		ANKI_CHECK(m_shaderStatsFile.flush());
-	}
-
 	if(!!(m_extensions & VulkanExtensions::kKHR_pipeline_executable_properties))
 	{
 		GrStringList log;

+ 2 - 3
AnKi/Gr/Vulkan/GrManagerImpl.h

@@ -188,7 +188,7 @@ public:
 	/// @}
 
 	/// @note It's thread-safe.
-	void printPipelineShaderInfo(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash = 0) const;
+	void printPipelineShaderInfo(VkPipeline ppline, CString name, U64 hash = 0) const;
 
 	FrameGarbageCollector& getFrameGarbageCollector()
 	{
@@ -243,7 +243,6 @@ private:
 
 	VkDebugUtilsMessengerEXT m_debugUtilsMessager = VK_NULL_HANDLE;
 
-	PFN_vkGetShaderInfoAMD m_pfnGetShaderInfoAMD = nullptr;
 	mutable File m_shaderStatsFile;
 	mutable SpinLock m_shaderStatsFileMtx;
 
@@ -324,7 +323,7 @@ private:
 	static VkBool32 debugReportCallbackEXT(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
 										   const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData);
 
-	Error printPipelineShaderInfoInternal(VkPipeline ppline, CString name, ShaderTypeBit stages, U64 hash) const;
+	Error printPipelineShaderInfoInternal(VkPipeline ppline, CString name, U64 hash) const;
 };
 /// @}
 

+ 1 - 1
AnKi/Gr/Vulkan/Pipeline.cpp

@@ -490,7 +490,7 @@ void PipelineFactory::getOrCreatePipeline(PipelineStateTracker& state, Pipeline&
 	ppline.m_handle = pp.m_handle;
 
 	// Print shader info
-	getGrManagerImpl().printPipelineShaderInfo(pp.m_handle, state.m_state.m_prog->getName(), state.m_state.m_prog->getStages(), hash);
+	getGrManagerImpl().printPipelineShaderInfo(pp.m_handle, state.m_state.m_prog->getName(), hash);
 }
 
 } // end namespace anki

+ 4 - 1
AnKi/Gr/Vulkan/PipelineCache.cpp

@@ -11,10 +11,13 @@
 
 namespace anki {
 
+static NumericCVar<PtrSize> g_diskShaderCacheMaxSizeCVar(CVarSubsystem::kGr, "DiskShaderCacheMaxSize", 128_MB, 1_MB, 1_GB,
+														 "Max size of the pipeline cache file");
+
 Error PipelineCache::init(CString cacheDir)
 {
 	ANKI_ASSERT(cacheDir);
-	m_dumpSize = ConfigSet::getSingleton().getGrDiskShaderCacheMaxSize();
+	m_dumpSize = g_diskShaderCacheMaxSizeCVar.get();
 	m_dumpFilename.sprintf("%s/VkPipelineCache", cacheDir.cstr());
 
 	// Try read the pipeline cache file.

+ 1 - 1
AnKi/Gr/Vulkan/ShaderProgramImpl.cpp

@@ -244,7 +244,7 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 
 		ANKI_TRACE_SCOPED_EVENT(VkPipelineCreate);
 		ANKI_VK_CHECK(vkCreateComputePipelines(getVkDevice(), getGrManagerImpl().getPipelineCache(), 1, &ci, nullptr, &m_compute.m_ppline));
-		getGrManagerImpl().printPipelineShaderInfo(m_compute.m_ppline, getName(), ShaderTypeBit::kCompute);
+		getGrManagerImpl().printPipelineShaderInfo(m_compute.m_ppline, getName());
 	}
 
 	// Create the RT pipeline

+ 12 - 10
AnKi/Renderer/Bloom.cpp

@@ -12,6 +12,9 @@
 
 namespace anki {
 
+NumericCVar<F32> g_bloomThresholdCVar(CVarSubsystem::kRenderer, "BloomThreshold", 2.5f, 0.0f, 256.0f, "Bloom threshold");
+static NumericCVar<F32> g_bloomScaleCVar(CVarSubsystem::kRenderer, "BloomScale", 2.5f, 0.0f, 256.0f, "Bloom scale");
+
 Bloom::Bloom()
 {
 	registerDebugRenderTarget("Bloom");
@@ -42,12 +45,11 @@ Error Bloom::initExposure()
 	m_exposure.m_rtDescr.bake();
 
 	// init shaders
-	CString progFname =
-		(ConfigSet::getSingleton().getRPreferCompute()) ? "ShaderBinaries/BloomCompute.ankiprogbin" : "ShaderBinaries/BloomRaster.ankiprogbin";
+	CString progFname = (g_preferComputeCVar.get()) ? "ShaderBinaries/BloomCompute.ankiprogbin" : "ShaderBinaries/BloomRaster.ankiprogbin";
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource(progFname, m_exposure.m_prog));
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_exposure.m_prog);
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		variantInitInfo.addConstant("kViewport", UVec2(m_exposure.m_width, m_exposure.m_height));
 	}
@@ -69,13 +71,13 @@ Error Bloom::initUpscale()
 	m_upscale.m_rtDescr.bake();
 
 	// init shaders
-	CString progFname = (ConfigSet::getSingleton().getRPreferCompute()) ? "ShaderBinaries/BloomUpscaleCompute.ankiprogbin"
-																		: "ShaderBinaries/BloomUpscaleRaster.ankiprogbin";
+	CString progFname =
+		(g_preferComputeCVar.get()) ? "ShaderBinaries/BloomUpscaleCompute.ankiprogbin" : "ShaderBinaries/BloomUpscaleRaster.ankiprogbin";
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource(progFname, m_upscale.m_prog));
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_upscale.m_prog);
 	variantInitInfo.addConstant("kInputTextureSize", UVec2(m_exposure.m_width, m_exposure.m_height));
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		variantInitInfo.addConstant("kViewport", UVec2(m_upscale.m_width, m_upscale.m_height));
 	}
@@ -93,7 +95,7 @@ Error Bloom::initUpscale()
 void Bloom::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 
 	// Main pass
 	{
@@ -136,12 +138,12 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 			rgraphCtx.bindTexture(0, 1, getRenderer().getDownscaleBlur().getRt(), inputTexSubresource);
 
-			const Vec4 uniforms(ConfigSet::getSingleton().getRBloomThreshold(), ConfigSet::getSingleton().getRBloomScale(), 0.0f, 0.0f);
+			const Vec4 uniforms(g_bloomThresholdCVar.get(), g_bloomScaleCVar.get(), 0.0f, 0.0f);
 			cmdb.setPushConstants(&uniforms, sizeof(uniforms));
 
 			rgraphCtx.bindImage(0, 2, getRenderer().getTonemapping().getRt());
 
-			if(ConfigSet::getSingleton().getRPreferCompute())
+			if(g_preferComputeCVar.get())
 			{
 				rgraphCtx.bindImage(0, 3, m_runCtx.m_exposureRt, TextureSubresourceInfo());
 
@@ -192,7 +194,7 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindColorTexture(0, 1, m_runCtx.m_exposureRt);
 			cmdb.bindTexture(0, 2, &m_upscale.m_lensDirtImage->getTextureView());
 
-			if(ConfigSet::getSingleton().getRPreferCompute())
+			if(g_preferComputeCVar.get())
 			{
 				rgraphCtx.bindImage(0, 3, m_runCtx.m_upscaleRt, TextureSubresourceInfo());
 

+ 3 - 0
AnKi/Renderer/Bloom.h

@@ -11,6 +11,9 @@
 
 namespace anki {
 
+// Forward
+extern NumericCVar<F32> g_bloomThresholdCVar;
+
 /// @addtogroup renderer
 /// @{
 

+ 1 - 0
AnKi/Renderer/Common.h

@@ -7,6 +7,7 @@
 
 #include <AnKi/Gr.h>
 #include <AnKi/Util/Ptr.h>
+#include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Shaders/Include/MiscRendererTypes.h>
 #include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
 #include <AnKi/Scene/ContiguousArrayAllocator.h>

+ 0 - 84
AnKi/Renderer/ConfigVars.defs.h

@@ -1,84 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-ANKI_CONFIG_VAR_GROUP(R)
-
-ANKI_CONFIG_VAR_U8(RTextureAnisotropy, ((ANKI_PLATFORM_MOBILE) ? 1 : 8), 1, 16, "Texture anisotropy for the main passes")
-ANKI_CONFIG_VAR_U32(RTileSize, 64, 8, 256, "Tile lighting tile size")
-ANKI_CONFIG_VAR_U32(RZSplitCount, 64, 8, kMaxZsplitCount, "Clusterer number of Z splits")
-ANKI_CONFIG_VAR_BOOL(RPreferCompute, !ANKI_PLATFORM_MOBILE, "Prefer compute shaders")
-ANKI_CONFIG_VAR_BOOL(RHighQualityHdr, !ANKI_PLATFORM_MOBILE, "If true use R16G16B16 for HDR images. Alternatively use B10G11R11")
-
-ANKI_CONFIG_VAR_F32(RInternalRenderScaling, 1.0f, 0.5f, 1.0f, "A factor over the requested swapchain resolution. Applies to all passes up to TAA")
-ANKI_CONFIG_VAR_F32(RRenderScaling, 1.0f, 0.5f, 8.0f, "A factor over the requested swapchain resolution. Applies to post-processing and UI")
-
-ANKI_CONFIG_VAR_F32(RVolumetricLightingAccumulationQualityXY, 4.0f, 1.0f, 16.0f, "Quality of XY dimensions of volumetric lights")
-ANKI_CONFIG_VAR_F32(RVolumetricLightingAccumulationQualityZ, 4.0f, 1.0f, 16.0f, "Quality of Z dimension of volumetric lights")
-ANKI_CONFIG_VAR_U32(RVolumetricLightingAccumulationFinalZSplit, 26, 1, 256, "Final cluster split that will recieve volumetric lights")
-
-ANKI_CONFIG_VAR_BOOL(RDbg, false, "Enable or not debug visualization")
-ANKI_CONFIG_VAR_BOOL(RDbgPhysics, false, "Enable or not physics debug visualization")
-
-// VRS
-ANKI_CONFIG_VAR_BOOL(RVrs, true, "Enable VRS in multiple passes")
-ANKI_CONFIG_VAR_BOOL(RGBufferVrs, false, "Enable VRS in GBuffer")
-ANKI_CONFIG_VAR_F32(RVrsThreshold, 0.1f, 0.0f, 1.0f, "Threshold under which a lower shading rate will be applied")
-ANKI_CONFIG_VAR_BOOL(RVrsLimitTo2x2, false, "If true the max rate will be 2x2")
-
-// SSR
-ANKI_CONFIG_VAR_U32(RSsrFirstStepPixels, 32, 1, 256, "The 1st step in ray marching")
-ANKI_CONFIG_VAR_U32(RSsrDepthLod, ((ANKI_PLATFORM_MOBILE) ? 2 : 0), 0, 1000, "Texture LOD of the depth texture that will be raymarched")
-ANKI_CONFIG_VAR_U32(RSsrMaxSteps, 64, 1, 256, "Max SSR raymarching steps")
-ANKI_CONFIG_VAR_BOOL(RSsrStochastic, false, "Stochastic reflections")
-ANKI_CONFIG_VAR_F32(RSsrRoughnessCutoff, ((ANKI_PLATFORM_MOBILE) ? 0.7f : 1.0f), 0.0f, 1.0f,
-					"Materials with roughness higher that this value will fallback to probe reflections")
-
-// GI probes
-ANKI_CONFIG_VAR_U32(RIndirectDiffuseProbeTileResolution, ((ANKI_PLATFORM_MOBILE) ? 16 : 32), 8, 32, "GI tile resolution")
-ANKI_CONFIG_VAR_U32(RIndirectDiffuseProbeShadowMapResolution, 128, 4, 2048, "GI shadowmap resolution")
-
-// GI
-ANKI_CONFIG_VAR_U32(RIndirectDiffuseSsgiSampleCount, 8, 1, 1024, "SSGI sample count")
-ANKI_CONFIG_VAR_F32(RIndirectDiffuseSsgiRadius, 2.0f, 0.1f, 100.0f, "SSGI radius in meters")
-ANKI_CONFIG_VAR_U32(RIndirectDiffuseDenoiseSampleCount, 4, 1, 128, "Indirect diffuse denoise sample count")
-ANKI_CONFIG_VAR_F32(RIndirectDiffuseSsaoStrength, 2.5f, 0.1f, 10.0f, "SSAO strength")
-ANKI_CONFIG_VAR_F32(RIndirectDiffuseSsaoBias, -0.1f, -10.0f, 10.0f, "SSAO bias")
-ANKI_CONFIG_VAR_F32(RIndirectDiffuseVrsDistanceThreshold, 0.01f, 0.00001f, 10.0f, "The meters that control the VRS SRI generation")
-
-// Shadows
-ANKI_CONFIG_VAR_U32(RShadowMappingTileResolution, ((ANKI_PLATFORM_MOBILE) ? 128 : 256), 16, 2048, "Shadowmapping tile resolution")
-ANKI_CONFIG_VAR_U32(RShadowMappingTileCountPerRowOrColumn, 32, 1, 256, "Shadowmapping atlas will have this number squared number of tiles")
-ANKI_CONFIG_VAR_U32(RShadowMappingPcf, ((ANKI_PLATFORM_MOBILE) ? 0 : 1), 0, 1, "Shadow PCF (0: off, 1: on)")
-
-// Probe reflections
-ANKI_CONFIG_VAR_U32(RProbeReflectionIrradianceResolution, 16, 4, 2048, "Reflection probe irradiance resolution")
-ANKI_CONFIG_VAR_U32(RProbeReflectionShadowMapResolution, 64, 4, 2048, "Reflection probe shadow resolution")
-
-// Final composite
-ANKI_CONFIG_VAR_U32(RMotionBlurSamples, 32, 0, 2048, "Max motion blur samples")
-ANKI_CONFIG_VAR_F32(RFilmGrainStrength, 16.0f, 0.0f, 250.0f, "Film grain strength")
-
-// Lens flare
-ANKI_CONFIG_VAR_U8(RLensFlareMaxSpritesPerFlare, 8, 4, 255, "Max sprites per lens flare")
-ANKI_CONFIG_VAR_U8(RLensFlareMaxFlares, 16, 8, 255, "Max flare count")
-
-// Bloom
-ANKI_CONFIG_VAR_F32(RBloomThreshold, 2.5f, 0.0f, 256.0f, "Bloom threshold")
-ANKI_CONFIG_VAR_F32(RBloomScale, 2.5f, 0.0f, 256.0f, "Bloom scale")
-
-ANKI_CONFIG_VAR_BOOL(RSmResolveQuarterRez, ANKI_PLATFORM_MOBILE, "Shadowmapping resolve quality")
-
-ANKI_CONFIG_VAR_BOOL(RRtShadowsSvgf, false, "Enable or not RT shadows SVGF")
-ANKI_CONFIG_VAR_U8(RRtShadowsSvgfAtrousPassCount, 3, 1, 20, "Number of atrous passes of SVGF")
-ANKI_CONFIG_VAR_U32(RRtShadowsRaysPerPixel, 1, 1, 8, "Number of shadow rays per pixel")
-
-ANKI_CONFIG_VAR_U8(RFsrQuality, 1, 0, 2, "0: Use bilinear, 1: FSR low quality, 2: FSR high quality")
-ANKI_CONFIG_VAR_U8(RDlssQuality, 2, 0, 3, "0: Disabled, 1: Performance, 2: Balanced, 3: Quality")
-ANKI_CONFIG_VAR_F32(RSharpness, ((ANKI_PLATFORM_MOBILE) ? 0.0f : 0.8f), 0.0f, 1.0f, "Sharpen the image. It's a factor")
-
-// HZB
-ANKI_CONFIG_VAR_U32(RHzbWidth, 512, 16, 4 * 1024, "HZB map width")
-ANKI_CONFIG_VAR_U32(RHzbHeight, 256, 16, 4 * 1024, "HZB map height")
-ANKI_CONFIG_VAR_U32(RHzbShadowSize, 128, 16, 4 * 1024, "Shadows HZB map width and height")

+ 6 - 3
AnKi/Renderer/Dbg.cpp

@@ -18,6 +18,9 @@
 
 namespace anki {
 
+BoolCVar g_dbgCVar(CVarSubsystem::kRenderer, "Dbg", false, "Enable or not debug visualization");
+static BoolCVar g_dbgPhysicsCVar(CVarSubsystem::kRenderer, "DbgPhysics", false, "Enable or not physics debug visualization");
+
 Dbg::Dbg()
 {
 }
@@ -56,7 +59,7 @@ Error Dbg::init()
 
 void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 {
-	ANKI_ASSERT(ConfigSet::getSingleton().getRDbg());
+	ANKI_ASSERT(g_dbgCVar.get());
 
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
@@ -218,7 +221,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 		}
 	}
 
-	if(threadId == (threadCount - 1) && ConfigSet::getSingleton().getRDbgPhysics())
+	if(threadId == (threadCount - 1) && g_dbgPhysicsCVar.get())
 	{
 		m_physicsDrawer.start(ctx.m_matrices.m_viewProjection, cmdb);
 		m_physicsDrawer.drawWorld(PhysicsWorld::getSingleton());
@@ -231,7 +234,7 @@ void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 
 void Dbg::populateRenderGraph(RenderingContext& ctx)
 {
-	if(!ConfigSet::getSingleton().getRDbg())
+	if(!g_dbgCVar.get())
 	{
 		return;
 	}

+ 3 - 0
AnKi/Renderer/Dbg.h

@@ -13,6 +13,9 @@
 
 namespace anki {
 
+// Forward
+extern BoolCVar g_dbgCVar;
+
 /// @addtogroup renderer
 /// @{
 

+ 2 - 2
AnKi/Renderer/DepthDownscale.cpp

@@ -47,7 +47,7 @@ Error DepthDownscale::initInternal()
 
 	ANKI_R_LOGV("Initializing HiZ. Mip count %u, last mip size %ux%u", m_mipCount, m_lastMipSize.x(), m_lastMipSize.y());
 
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 	const Bool supportsReductionSampler = GrManager::getSingleton().getDeviceCapabilities().m_samplingFilterMinMax;
 
 	// Create RT descr
@@ -179,7 +179,7 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		// Do it with compute
 

+ 3 - 3
AnKi/Renderer/DownscaleBlur.cpp

@@ -30,7 +30,7 @@ Error DownscaleBlur::initInternal()
 	const UVec2 rez = getRenderer().getPostProcessResolution() / 2;
 	ANKI_R_LOGV("Initializing downscale pyramid. Resolution %ux%u, mip count %u", rez.x(), rez.y(), m_passCount);
 
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 
 	// Create the miped texture
 	TextureInitInfo texinit = getRenderer().create2DRenderTargetDescription(rez.x(), rez.y(), getRenderer().getHdrFormat(), "DownscaleBlur");
@@ -83,7 +83,7 @@ void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)
 													"Down/Blur #4", "Down/Blur #5", "Down/Blur #6", "Down/Blur #7"};
 	const RenderTargetHandle inRt =
 		(getRenderer().getScale().hasUpscaledHdrRt()) ? getRenderer().getScale().getUpscaledHdrRt() : getRenderer().getScale().getTonemappedRt();
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		for(U32 i = 0; i < m_passCount; ++i)
 		{
@@ -174,7 +174,7 @@ void DownscaleBlur::run(U32 passIdx, RenderPassWorkContext& rgraphCtx)
 	const UVec4 fbSize(vpWidth, vpHeight, revertTonemap, 0);
 	cmdb.setPushConstants(&fbSize, sizeof(fbSize));
 
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		TextureSubresourceInfo sampleSubresource;
 		sampleSubresource.m_firstMipmap = passIdx;

+ 8 - 5
AnKi/Renderer/FinalComposite.cpp

@@ -20,6 +20,9 @@
 
 namespace anki {
 
+static NumericCVar<U32> g_motionBlurSamplesCVar(CVarSubsystem::kRenderer, "MotionBlurSamples", 32, 0, 2048, "Max motion blur samples");
+static NumericCVar<F32> g_filmGrainStrengthCVar(CVarSubsystem::kRenderer, "FilmGrainStrength", 16.0f, 0.0f, 250.0f, "Film grain strength");
+
 Error FinalComposite::initInternal()
 {
 	ANKI_R_LOGV("Initializing final composite");
@@ -33,11 +36,11 @@ Error FinalComposite::initInternal()
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/FinalComposite.ankiprogbin", m_prog));
 
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
-	variantInitInfo.addMutation("FILM_GRAIN", (ConfigSet::getSingleton().getRFilmGrainStrength() > 0.0) ? 1 : 0);
+	variantInitInfo.addMutation("FILM_GRAIN", (g_filmGrainStrengthCVar.get() > 0.0) ? 1 : 0);
 	variantInitInfo.addMutation("BLOOM_ENABLED", 1);
 	variantInitInfo.addConstant("kLutSize", U32(kLutSize));
 	variantInitInfo.addConstant("kFramebufferSize", getRenderer().getPostProcessResolution());
-	variantInitInfo.addConstant("kMotionBlurSamples", ConfigSet::getSingleton().getRMotionBlurSamples());
+	variantInitInfo.addConstant("kMotionBlurSamples", g_motionBlurSamplesCVar.get());
 
 	for(U32 dbg = 0; dbg < 2; ++dbg)
 	{
@@ -93,7 +96,7 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 
 	pass.newTextureDependency(ctx.m_outRenderTarget, TextureUsageBit::kFramebufferWrite);
 
-	if(ConfigSet::getSingleton().getRDbg())
+	if(g_dbgCVar.get())
 	{
 		pass.newTextureDependency(getRenderer().getDbg().getRt(), TextureUsageBit::kSampledFragment);
 	}
@@ -123,7 +126,7 @@ void FinalComposite::run(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx
 	ANKI_TRACE_SCOPED_EVENT(RFinalComposite);
 
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool dbgEnabled = ConfigSet::getSingleton().getRDbg();
+	const Bool dbgEnabled = g_dbgCVar.get();
 
 	Array<RenderTargetHandle, kMaxDebugRenderTargets> dbgRts;
 	ShaderProgramPtr optionalDebugProgram;
@@ -162,7 +165,7 @@ void FinalComposite::run(RenderingContext& ctx, RenderPassWorkContext& rgraphCtx
 			rgraphCtx.bindColorTexture(0, 8, getRenderer().getDbg().getRt());
 		}
 
-		const UVec4 pc(0, 0, floatBitsToUint(ConfigSet::getSingleton().getRFilmGrainStrength()), getRenderer().getFrameCount() & kMaxU32);
+		const UVec4 pc(0, 0, floatBitsToUint(g_filmGrainStrengthCVar.get()), getRenderer().getFrameCount() & kMaxU32);
 		cmdb.setPushConstants(&pc, sizeof(pc));
 	}
 	else

+ 11 - 9
AnKi/Renderer/GBuffer.cpp

@@ -11,9 +11,14 @@
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Core/ConfigSet.h>
+#include <AnKi/Core/App.h>
 
 namespace anki {
 
+static NumericCVar<U32> g_hzbWidthCVar(CVarSubsystem::kRenderer, "HzbWidth", 512, 16, 4 * 1024, "HZB map width");
+static NumericCVar<U32> g_hzbHeightCVar(CVarSubsystem::kRenderer, "HzbHeight", 256, 16, 4 * 1024, "HZB map height");
+static BoolCVar g_gbufferVrsCVar(CVarSubsystem::kRenderer, "GBufferVrs", false, "Enable VRS in GBuffer");
+
 GBuffer::~GBuffer()
 {
 }
@@ -57,8 +62,8 @@ Error GBuffer::initInternal()
 	{
 		const TextureUsageBit usage = TextureUsageBit::kSampledCompute | TextureUsageBit::kImageComputeWrite;
 
-		TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
-			ConfigSet::getSingleton().getRHzbWidth(), ConfigSet::getSingleton().getRHzbWidth(), Format::kR32_Sfloat, usage, "GBuffer HZB");
+		TextureInitInfo texinit =
+			getRenderer().create2DRenderTargetInitInfo(g_hzbWidthCVar.get(), g_hzbHeightCVar.get(), Format::kR32_Sfloat, usage, "GBuffer HZB");
 		texinit.m_mipmapCount = U8(computeMaxMipmapCount2d(texinit.m_width, texinit.m_height));
 		ClearValue clear;
 		clear.m_colorf = {1.0f, 1.0f, 1.0f, 1.0f};
@@ -85,7 +90,7 @@ Error GBuffer::initInternal()
 	m_fbDescr.m_depthStencilAttachment.m_clearValue.m_depthStencil.m_depth = 1.0f;
 	m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::kDepth;
 
-	if(GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs())
+	if(GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get())
 	{
 		m_fbDescr.m_shadingRateAttachmentTexelWidth = getRenderer().getVrsSriGeneration().getSriTexelDimension();
 		m_fbDescr.m_shadingRateAttachmentTexelHeight = getRenderer().getVrsSriGeneration().getSriTexelDimension();
@@ -106,8 +111,7 @@ void GBuffer::runInThread(const RenderingContext& ctx, const GpuVisibilityOutput
 	cmdb.setViewport(0, 0, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 	cmdb.setRasterizationOrder(RasterizationOrder::kRelaxed);
 
-	const Bool enableVrs =
-		GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs() && ConfigSet::getSingleton().getRGBufferVrs();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get() && g_gbufferVrsCVar.get();
 	if(enableVrs)
 	{
 		// Just set some low value, the attachment will take over
@@ -156,15 +160,13 @@ void GBuffer::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
 	const CommonMatrices& matrices = (getRenderer().getFrameCount() <= 1) ? ctx.m_matrices : ctx.m_prevMatrices;
-	const Array<F32, kMaxLodCount - 1> lodDistances = {ConfigSet::getSingleton().getLod0MaxDistance(),
-													   ConfigSet::getSingleton().getLod1MaxDistance()};
+	const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
 	GpuVisibilityOutput visOut;
 	getRenderer().getGpuVisibility().populateRenderGraph("GBuffer visibility", RenderingTechnique::kGBuffer, matrices.m_viewProjection,
 														 matrices.m_cameraTransform.getTranslationPart().xyz(), lodDistances, &m_runCtx.m_hzbRt,
 														 rgraph, visOut);
 
-	const Bool enableVrs =
-		GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs() && ConfigSet::getSingleton().getRGBufferVrs();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get() && g_gbufferVrsCVar.get();
 	const Bool fbDescrHasVrs = m_fbDescr.m_shadingRateAttachmentTexelWidth > 0;
 
 	if(enableVrs != fbDescrHasVrs)

+ 27 - 15
AnKi/Renderer/IndirectDiffuse.cpp

@@ -16,6 +16,18 @@
 
 namespace anki {
 
+static NumericCVar<U32> g_indirectDiffuseSsgiSampleCountCVar(CVarSubsystem::kRenderer, "IndirectDiffuseSsgiSampleCount", 8, 1, 1024,
+															 "SSGI sample count");
+static NumericCVar<F32> g_indirectDiffuseSsgiRadiusCVar(CVarSubsystem::kRenderer, "IndirectDiffuseSsgiRadius", 2.0f, 0.1f, 100.0f,
+														"SSGI radius in meters");
+static NumericCVar<U32> g_indirectDiffuseDenoiseSampleCountCVar(CVarSubsystem::kRenderer, "IndirectDiffuseDenoiseSampleCount", 4, 1, 128,
+																"Indirect diffuse denoise sample count");
+static NumericCVar<F32> g_indirectDiffuseSsaoStrengthCVar(CVarSubsystem::kRenderer, "IndirectDiffuseSsaoStrength", 2.5f, 0.1f, 10.0f,
+														  "SSAO strength");
+static NumericCVar<F32> g_indirectDiffuseSsaoBiasCVar(CVarSubsystem::kRenderer, "IndirectDiffuseSsaoBias", -0.1f, -10.0f, 10.0f, "SSAO bias");
+static NumericCVar<F32> g_indirectDiffuseVrsDistanceThresholdCVar(CVarSubsystem::kRenderer, "IndirectDiffuseVrsDistanceThreshold", 0.01f, 0.00001f,
+																  10.0f, "The meters that control the VRS SRI generation");
+
 Error IndirectDiffuse::init()
 {
 	const Error err = initInternal();
@@ -33,7 +45,7 @@ Error IndirectDiffuse::initInternal()
 
 	ANKI_R_LOGV("Initializing indirect diffuse. Resolution %ux%u", size.x(), size.y());
 
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 
 	// Init textures
 	TextureUsageBit usage = TextureUsageBit::kAllSampled;
@@ -52,7 +64,7 @@ Error IndirectDiffuse::initInternal()
 	}
 
 	// Init VRS SRI generation
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs() && !preferCompute;
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get() && !preferCompute;
 	if(enableVrs)
 	{
 		m_vrs.m_sriTexelDimension = GrManager::getSingleton().getDeviceCapabilities().m_minShadingRateImageTexelSize;
@@ -84,7 +96,7 @@ Error IndirectDiffuse::initInternal()
 			variantInit.addMutation("SHARED_MEMORY", 1);
 		}
 
-		variantInit.addMutation("LIMIT_RATE_TO_2X2", ConfigSet::getSingleton().getRVrsLimitTo2x2());
+		variantInit.addMutation("LIMIT_RATE_TO_2X2", g_vrsLimitTo2x2CVar.get());
 
 		const ShaderProgramResourceVariant* variant;
 		m_vrs.m_prog->getOrCreateVariant(variantInit, variant);
@@ -132,8 +144,8 @@ Error IndirectDiffuse::initInternal()
 void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs() && !preferCompute;
+	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get() && !preferCompute;
 	const Bool fbDescrHasVrs = m_main.m_fbDescr.m_shadingRateAttachmentTexelWidth > 0;
 
 	if(!preferCompute && enableVrs != fbDescrHasVrs)
@@ -182,7 +194,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 				Mat4 m_invertedProjectionJitter;
 			} pc;
 
-			pc.m_v4 = Vec4(1.0f / Vec2(viewport), ConfigSet::getSingleton().getRIndirectDiffuseVrsDistanceThreshold(), 0.0f);
+			pc.m_v4 = Vec4(1.0f / Vec2(viewport), g_indirectDiffuseVrsDistanceThresholdCVar.get(), 0.0f);
 			pc.m_invertedProjectionJitter = ctx.m_matrices.m_invertedProjectionJitter;
 
 			cmdb.setPushConstants(&pc, sizeof(pc));
@@ -268,7 +280,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindColorTexture(0, 8, getRenderer().getMotionVectors().getMotionVectorsRt());
 			rgraphCtx.bindColorTexture(0, 9, getRenderer().getMotionVectors().getHistoryLengthRt());
 
-			if(ConfigSet::getSingleton().getRPreferCompute())
+			if(g_preferComputeCVar.get())
 			{
 				rgraphCtx.bindImage(0, 10, m_runCtx.m_mainRtHandles[kWrite]);
 			}
@@ -281,14 +293,14 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			unis.m_viewportSizef = Vec2(unis.m_viewportSize);
 			const Mat4& pmat = ctx.m_matrices.m_projection;
 			unis.m_projectionMat = Vec4(pmat(0, 0), pmat(1, 1), pmat(2, 2), pmat(2, 3));
-			unis.m_radius = ConfigSet::getSingleton().getRIndirectDiffuseSsgiRadius();
-			unis.m_sampleCount = ConfigSet::getSingleton().getRIndirectDiffuseSsgiSampleCount();
+			unis.m_radius = g_indirectDiffuseSsgiRadiusCVar.get();
+			unis.m_sampleCount = g_indirectDiffuseSsgiSampleCountCVar.get();
 			unis.m_sampleCountf = F32(unis.m_sampleCount);
-			unis.m_ssaoBias = ConfigSet::getSingleton().getRIndirectDiffuseSsaoBias();
-			unis.m_ssaoStrength = ConfigSet::getSingleton().getRIndirectDiffuseSsaoStrength();
+			unis.m_ssaoBias = g_indirectDiffuseSsaoBiasCVar.get();
+			unis.m_ssaoStrength = g_indirectDiffuseSsaoStrengthCVar.get();
 			cmdb.setPushConstants(&unis, sizeof(unis));
 
-			if(ConfigSet::getSingleton().getRPreferCompute())
+			if(g_preferComputeCVar.get())
 			{
 				dispatchPPCompute(cmdb, 8, 8, unis.m_viewportSize.x(), unis.m_viewportSize.y());
 			}
@@ -347,7 +359,7 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			hizSubresource.m_mipmapCount = 1;
 			rgraphCtx.bindTexture(0, 2, getRenderer().getDepthDownscale().getHiZRt(), hizSubresource);
 
-			if(ConfigSet::getSingleton().getRPreferCompute())
+			if(g_preferComputeCVar.get())
 			{
 				rgraphCtx.bindImage(0, 3, m_runCtx.m_mainRtHandles[!readIdx]);
 			}
@@ -356,12 +368,12 @@ void IndirectDiffuse::populateRenderGraph(RenderingContext& ctx)
 			unis.m_invertedViewProjectionJitterMat = ctx.m_matrices.m_invertedViewProjectionJitter;
 			unis.m_viewportSize = getRenderer().getInternalResolution() / 2u;
 			unis.m_viewportSizef = Vec2(unis.m_viewportSize);
-			unis.m_sampleCountDiv2 = F32(ConfigSet::getSingleton().getRIndirectDiffuseDenoiseSampleCount());
+			unis.m_sampleCountDiv2 = F32(g_indirectDiffuseDenoiseSampleCountCVar.get());
 			unis.m_sampleCountDiv2 = max(1.0f, std::round(unis.m_sampleCountDiv2 / 2.0f));
 
 			cmdb.setPushConstants(&unis, sizeof(unis));
 
-			if(ConfigSet::getSingleton().getRPreferCompute())
+			if(g_preferComputeCVar.get())
 			{
 				dispatchPPCompute(cmdb, 8, 8, unis.m_viewportSize.x(), unis.m_viewportSize.y());
 			}

+ 7 - 2
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -13,6 +13,11 @@
 
 namespace anki {
 
+static NumericCVar<U32> g_indirectDiffuseProbeTileResolutionCVar(CVarSubsystem::kRenderer, "IndirectDiffuseProbeTileResolution",
+																 (ANKI_PLATFORM_MOBILE) ? 16 : 32, 8, 32, "GI tile resolution");
+static NumericCVar<U32> g_indirectDiffuseProbeShadowMapResolutionCVar(CVarSubsystem::kRenderer, "IndirectDiffuseProbeShadowMapResolution", 128, 4,
+																	  2048, "GI shadowmap resolution");
+
 class IndirectDiffuseProbes::InternalContext
 {
 public:
@@ -60,7 +65,7 @@ Error IndirectDiffuseProbes::init()
 
 Error IndirectDiffuseProbes::initInternal()
 {
-	m_tileSize = ConfigSet::getSingleton().getRIndirectDiffuseProbeTileResolution();
+	m_tileSize = g_indirectDiffuseProbeTileResolutionCVar.get();
 
 	ANKI_CHECK(initGBuffer());
 	ANKI_CHECK(initLightShading());
@@ -114,7 +119,7 @@ Error IndirectDiffuseProbes::initGBuffer()
 
 Error IndirectDiffuseProbes::initShadowMapping()
 {
-	const U32 resolution = ConfigSet::getSingleton().getRIndirectDiffuseProbeShadowMapResolution();
+	const U32 resolution = g_indirectDiffuseProbeShadowMapResolutionCVar.get();
 	ANKI_ASSERT(resolution > 8);
 
 	// RT descr

+ 20 - 13
AnKi/Renderer/IndirectSpecular.cpp

@@ -18,6 +18,14 @@
 
 namespace anki {
 
+static NumericCVar<U32> g_ssrFirstStepPixelsCVar(CVarSubsystem::kRenderer, "SsrFirstStepPixels", 32, 1, 256, "The 1st step in ray marching");
+static NumericCVar<U32> g_ssrDepthLodCVar(CVarSubsystem::kRenderer, "SsrDepthLod", (ANKI_PLATFORM_MOBILE) ? 2 : 0, 0, 1000,
+										  "Texture LOD of the depth texture that will be raymarched");
+static NumericCVar<U32> g_ssrMaxStepsCVar(CVarSubsystem::kRenderer, "SsrMaxSteps", 64, 1, 256, "Max SSR raymarching steps");
+static BoolCVar g_ssrStochasticCVar(CVarSubsystem::kRenderer, "SsrStochastic", false, "Stochastic reflections");
+static NumericCVar<F32> g_ssrRoughnessCutoffCVar(CVarSubsystem::kRenderer, "SsrRoughnessCutoff", (ANKI_PLATFORM_MOBILE) ? 0.7f : 1.0f, 0.0f, 1.0f,
+												 "Materials with roughness higher that this value will fallback to probe reflections");
+
 Error IndirectSpecular::init()
 {
 	const Error err = initInternal();
@@ -31,7 +39,7 @@ Error IndirectSpecular::init()
 Error IndirectSpecular::initInternal()
 {
 	const UVec2 size = getRenderer().getInternalResolution() / 2;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 
 	ANKI_R_LOGV("Initializing indirect specular. Resolution %ux%u", size.x(), size.y());
 
@@ -51,14 +59,13 @@ Error IndirectSpecular::initInternal()
 	m_fbDescr.bake();
 
 	// Create shader
-	ANKI_CHECK(ResourceManager::getSingleton().loadResource((ConfigSet::getSingleton().getRPreferCompute())
-																? "ShaderBinaries/IndirectSpecularCompute.ankiprogbin"
-																: "ShaderBinaries/IndirectSpecularRaster.ankiprogbin",
+	ANKI_CHECK(ResourceManager::getSingleton().loadResource((g_preferComputeCVar.get()) ? "ShaderBinaries/IndirectSpecularCompute.ankiprogbin"
+																						: "ShaderBinaries/IndirectSpecularRaster.ankiprogbin",
 															m_prog));
 
 	ShaderProgramResourceVariantInitInfo variantInit(m_prog);
 	variantInit.addMutation("EXTRA_REJECTION", false);
-	variantInit.addMutation("STOCHASTIC", ConfigSet::getSingleton().getRSsrStochastic());
+	variantInit.addMutation("STOCHASTIC", g_ssrStochasticCVar.get());
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInit, variant);
 	m_grProg.reset(&variant->getProgram());
@@ -69,8 +76,8 @@ Error IndirectSpecular::initInternal()
 void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs() && !preferCompute;
+	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get() && !preferCompute;
 	const Bool fbDescrHasVrs = m_fbDescr.m_shadingRateAttachmentTexelWidth > 0;
 
 	// Create/import RTs
@@ -142,7 +149,7 @@ void IndirectSpecular::populateRenderGraph(RenderingContext& ctx)
 		ppass->newTextureDependency(getRenderer().getGBuffer().getColorRt(2), readUsage);
 
 		TextureSubresourceInfo hizSubresource;
-		hizSubresource.m_mipmapCount = min(ConfigSet::getSingleton().getRSsrDepthLod() + 1, getRenderer().getDepthDownscale().getMipmapCount());
+		hizSubresource.m_mipmapCount = min(g_ssrDepthLodCVar.get() + 1, getRenderer().getDepthDownscale().getMipmapCount());
 		ppass->newTextureDependency(getRenderer().getDepthDownscale().getHiZRt(), readUsage, hizSubresource);
 
 		if(getRenderer().getProbeReflections().getHasCurrentlyRefreshedReflectionRt())
@@ -164,7 +171,7 @@ void IndirectSpecular::run(const RenderingContext& ctx, RenderPassWorkContext& r
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 	cmdb.bindShaderProgram(m_grProg.get());
 
-	const U32 depthLod = min(ConfigSet::getSingleton().getRSsrDepthLod(), getRenderer().getDepthDownscale().getMipmapCount() - 1);
+	const U32 depthLod = min(g_ssrDepthLodCVar.get(), getRenderer().getDepthDownscale().getMipmapCount() - 1);
 
 	// Bind uniforms
 	SsrUniforms* unis = allocateAndBindUniforms<SsrUniforms*>(sizeof(SsrUniforms), cmdb, 0, 0);
@@ -172,14 +179,14 @@ void IndirectSpecular::run(const RenderingContext& ctx, RenderPassWorkContext& r
 	unis->m_framebufferSize = UVec2(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y()) / 2;
 	unis->m_frameCount = getRenderer().getFrameCount() & kMaxU32;
 	unis->m_depthMipCount = getRenderer().getDepthDownscale().getMipmapCount();
-	unis->m_maxSteps = ConfigSet::getSingleton().getRSsrMaxSteps();
+	unis->m_maxSteps = g_ssrMaxStepsCVar.get();
 	unis->m_lightBufferMipCount = getRenderer().getDownscaleBlur().getMipmapCount();
-	unis->m_firstStepPixels = ConfigSet::getSingleton().getRSsrFirstStepPixels();
+	unis->m_firstStepPixels = g_ssrFirstStepPixelsCVar.get();
 	unis->m_prevViewProjMatMulInvViewProjMat = ctx.m_prevMatrices.m_viewProjection * ctx.m_matrices.m_viewProjectionJitter.getInverse();
 	unis->m_projMat = ctx.m_matrices.m_projectionJitter;
 	unis->m_invProjMat = ctx.m_matrices.m_projectionJitter.getInverse();
 	unis->m_normalMat = Mat3x4(Vec3(0.0f), ctx.m_matrices.m_view.getRotationPart());
-	unis->m_roughnessCutoff = ConfigSet::getSingleton().getRSsrRoughnessCutoff();
+	unis->m_roughnessCutoff = g_ssrRoughnessCutoffCVar.get();
 
 	// Bind all
 	cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_trilinearClamp.get());
@@ -206,7 +213,7 @@ void IndirectSpecular::run(const RenderingContext& ctx, RenderPassWorkContext& r
 
 	cmdb.bindAllBindless(1);
 
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		rgraphCtx.bindImage(0, 14, m_runCtx.m_rts[kWrite], TextureSubresourceInfo());
 

+ 6 - 2
AnKi/Renderer/LensFlare.cpp

@@ -12,6 +12,10 @@
 
 namespace anki {
 
+static NumericCVar<U8> g_lensFlareMaxSpritesPerFlareCVar(CVarSubsystem::kRenderer, "LensFlareMaxSpritesPerFlare", 8, 4, 255,
+														 "Max sprites per lens flare");
+static NumericCVar<U8> g_lensFlareMaxFlaresCVar(CVarSubsystem::kRenderer, "LensFlareMaxFlares", 16, 8, 255, "Max flare count");
+
 Error LensFlare::init()
 {
 	const Error err = initInternal();
@@ -35,8 +39,8 @@ Error LensFlare::initInternal()
 
 Error LensFlare::initSprite()
 {
-	m_maxSpritesPerFlare = ConfigSet::getSingleton().getRLensFlareMaxSpritesPerFlare();
-	m_maxFlares = ConfigSet::getSingleton().getRLensFlareMaxFlares();
+	m_maxSpritesPerFlare = g_lensFlareMaxSpritesPerFlareCVar.get();
+	m_maxFlares = g_lensFlareMaxFlaresCVar.get();
 
 	if(m_maxSpritesPerFlare < 1 || m_maxFlares < 1)
 	{

+ 3 - 3
AnKi/Renderer/LightShading.cpp

@@ -84,7 +84,7 @@ Error LightShading::initLightShading()
 	m_lightShading.m_fbDescr.m_depthStencilAttachment.m_stencilLoadOperation = AttachmentLoadOperation::kDontCare;
 	m_lightShading.m_fbDescr.m_depthStencilAttachment.m_aspect = DepthStencilAspectBit::kDepth;
 
-	if(GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs())
+	if(GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get())
 	{
 		m_lightShading.m_fbDescr.m_shadingRateAttachmentTexelWidth = getRenderer().getVrsSriGeneration().getSriTexelDimension();
 		m_lightShading.m_fbDescr.m_shadingRateAttachmentTexelHeight = getRenderer().getVrsSriGeneration().getSriTexelDimension();
@@ -145,7 +145,7 @@ void LightShading::run(const RenderingContext& ctx, RenderPassWorkContext& rgrap
 
 	cmdb.setViewport(0, 0, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get();
 	if(enableVrs)
 	{
 		// Just set some low value, the attachment will take over
@@ -310,7 +310,7 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 {
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get();
 	const Bool fbDescrHasVrs = m_lightShading.m_fbDescr.m_shadingRateAttachmentTexelWidth > 0;
 
 	if(enableVrs != fbDescrHasVrs)

+ 2 - 2
AnKi/Renderer/MainRenderer.cpp

@@ -44,7 +44,7 @@ Error MainRenderer::init(const MainRendererInitInfo& inf)
 
 	// Init renderer and manipulate the width/height
 	m_swapchainResolution = inf.m_swapchainSize;
-	m_rDrawToDefaultFb = ConfigSet::getSingleton().getRRenderScaling() == 1.0f;
+	m_rDrawToDefaultFb = g_renderScalingCVar.get() == 1.0f;
 
 	ANKI_R_LOGI("Initializing main renderer. Swapchain resolution %ux%u", m_swapchainResolution.x(), m_swapchainResolution.y());
 
@@ -60,7 +60,7 @@ Error MainRenderer::init(const MainRendererInitInfo& inf)
 		m_blitGrProg.reset(&variant->getProgram());
 
 		// The RT desc
-		UVec2 resolution = UVec2(Vec2(m_swapchainResolution) * ConfigSet::getSingleton().getRRenderScaling());
+		UVec2 resolution = UVec2(Vec2(m_swapchainResolution) * g_renderScalingCVar.get());
 		alignRoundDown(2, resolution.x());
 		alignRoundDown(2, resolution.y());
 		m_tmpRtDesc = m_r->create2DRenderTargetDescription(

+ 6 - 6
AnKi/Renderer/MotionVectors.cpp

@@ -26,8 +26,8 @@ Error MotionVectors::initInternal()
 	ANKI_R_LOGV("Initializing motion vectors");
 
 	// Prog
-	CString progFname = (ConfigSet::getSingleton().getRPreferCompute()) ? "ShaderBinaries/MotionVectorsCompute.ankiprogbin"
-																		: "ShaderBinaries/MotionVectorsRaster.ankiprogbin";
+	CString progFname =
+		(g_preferComputeCVar.get()) ? "ShaderBinaries/MotionVectorsCompute.ankiprogbin" : "ShaderBinaries/MotionVectorsRaster.ankiprogbin";
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource(progFname, m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("kFramebufferSize", UVec2(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y()));
@@ -41,7 +41,7 @@ Error MotionVectors::initInternal()
 	m_motionVectorsRtDescr.bake();
 
 	TextureUsageBit historyLengthUsage = TextureUsageBit::kAllSampled;
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		historyLengthUsage |= TextureUsageBit::kImageComputeWrite;
 	}
@@ -90,7 +90,7 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	RenderPassDescriptionBase* ppass;
 	TextureUsageBit readUsage;
 	TextureUsageBit writeUsage;
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		ComputeRenderPassDescription& pass = rgraph.newComputeRenderPass("MotionVectors");
 
@@ -145,13 +145,13 @@ void MotionVectors::run(const RenderingContext& ctx, RenderPassWorkContext& rgra
 	pc->m_viewProjectionInvMat = ctx.m_matrices.m_invertedViewProjectionJitter;
 	pc->m_prevViewProjectionInvMat = ctx.m_prevMatrices.m_invertedViewProjectionJitter;
 
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		rgraphCtx.bindImage(0, 6, m_runCtx.m_motionVectorsRtHandle, TextureSubresourceInfo());
 		rgraphCtx.bindImage(0, 7, m_runCtx.m_historyLengthWriteRtHandle, TextureSubresourceInfo());
 	}
 
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 	}

+ 10 - 4
AnKi/Renderer/ProbeReflections.cpp

@@ -13,9 +13,15 @@
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Resource/MeshResource.h>
 #include <AnKi/Shaders/Include/TraditionalDeferredShadingTypes.h>
+#include <AnKi/Scene/Components/ReflectionProbeComponent.h>
 
 namespace anki {
 
+static NumericCVar<U32> g_probeReflectionIrradianceResolutionCVar(CVarSubsystem::kRenderer, "ProbeReflectionIrradianceResolution", 16, 4, 2048,
+																  "Reflection probe irradiance resolution");
+static NumericCVar<U32> g_probeReflectionShadowMapResolutionCVar(CVarSubsystem::kRenderer, "ProbeReflectionShadowMapResolution", 64, 4, 2048,
+																 "Reflection probe shadow resolution");
+
 Error ProbeReflections::init()
 {
 	const Error err = initInternal();
@@ -52,7 +58,7 @@ Error ProbeReflections::initInternal()
 
 Error ProbeReflections::initGBuffer()
 {
-	m_gbuffer.m_tileSize = ConfigSet::getSingleton().getSceneReflectionProbeResolution();
+	m_gbuffer.m_tileSize = g_reflectionProbeResolutionCVar.get();
 
 	// Create RT descriptions
 	{
@@ -96,7 +102,7 @@ Error ProbeReflections::initGBuffer()
 
 Error ProbeReflections::initLightShading()
 {
-	m_lightShading.m_tileSize = ConfigSet::getSingleton().getSceneReflectionProbeResolution();
+	m_lightShading.m_tileSize = g_reflectionProbeResolutionCVar.get();
 	m_lightShading.m_mipCount = computeMaxMipmapCount2d(m_lightShading.m_tileSize, m_lightShading.m_tileSize, 8);
 
 	for(U32 faceIdx = 0; faceIdx < 6; ++faceIdx)
@@ -118,7 +124,7 @@ Error ProbeReflections::initLightShading()
 
 Error ProbeReflections::initIrradiance()
 {
-	m_irradiance.m_workgroupSize = ConfigSet::getSingleton().getRProbeReflectionIrradianceResolution();
+	m_irradiance.m_workgroupSize = g_probeReflectionIrradianceResolutionCVar.get();
 
 	// Create prog
 	{
@@ -156,7 +162,7 @@ Error ProbeReflections::initIrradianceToRefl()
 
 Error ProbeReflections::initShadowMapping()
 {
-	const U32 resolution = ConfigSet::getSingleton().getRProbeReflectionShadowMapResolution();
+	const U32 resolution = g_probeReflectionShadowMapResolutionCVar.get();
 	ANKI_ASSERT(resolution > 8);
 
 	// RT descr

+ 22 - 7
AnKi/Renderer/Renderer.cpp

@@ -14,6 +14,7 @@
 #include <AnKi/Collision/Functions.h>
 #include <AnKi/Shaders/Include/ClusteredShadingTypes.h>
 #include <AnKi/Core/GpuMemory/GpuSceneBuffer.h>
+#include <AnKi/Scene/Components/CameraComponent.h>
 
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Renderer/GBuffer.h>
@@ -48,6 +49,20 @@
 
 namespace anki {
 
+static NumericCVar<F32> g_internalRenderScalingCVar(CVarSubsystem::kRenderer, "InternalRenderScaling", 1.0f, 0.5f, 1.0f,
+													"A factor over the requested swapchain resolution. Applies to all passes up to TAA");
+NumericCVar<F32> g_renderScalingCVar(CVarSubsystem::kRenderer, "RenderScaling", 1.0f, 0.5f, 8.0f,
+									 "A factor over the requested swapchain resolution. Applies to post-processing and UI");
+static NumericCVar<U32> g_tileSizeCVar(CVarSubsystem::kRenderer, "TileSize", 64, 8, 256, "Tile lighting tile size");
+static NumericCVar<U32> g_zSplitCountCVar(CVarSubsystem::kRenderer, "ZSplitCount", 64, 8, kMaxZsplitCount, "Clusterer number of Z splits");
+static NumericCVar<U8> g_textureAnisotropyCVar(CVarSubsystem::kRenderer, "TextureAnisotropy", (ANKI_PLATFORM_MOBILE) ? 1 : 8, 1, 16,
+											   "Texture anisotropy for the main passes");
+BoolCVar g_preferComputeCVar(CVarSubsystem::kRenderer, "PreferCompute", !ANKI_PLATFORM_MOBILE, "Prefer compute shaders");
+static BoolCVar g_highQualityHdrCVar(CVarSubsystem::kRenderer, "HighQualityHdr", !ANKI_PLATFORM_MOBILE,
+									 "If true use R16G16B16 for HDR images. Alternatively use B10G11R11");
+BoolCVar g_vrsLimitTo2x2CVar(CVarSubsystem::kRenderer, "VrsLimitTo2x2", false, "If true the max rate will be 2x2");
+BoolCVar g_vrsCVar(CVarSubsystem::kRenderer, "Vrs", true, "Enable VRS in multiple passes");
+
 /// Generate a Halton jitter in [-0.5, 0.5]
 static Vec2 generateJitter(U32 frame)
 {
@@ -107,21 +122,21 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 	m_frameCount = 0;
 
 	// Set from the config
-	m_postProcessResolution = UVec2(Vec2(swapchainResolution) * ConfigSet::getSingleton().getRRenderScaling());
+	m_postProcessResolution = UVec2(Vec2(swapchainResolution) * g_renderScalingCVar.get());
 	alignRoundDown(2, m_postProcessResolution.x());
 	alignRoundDown(2, m_postProcessResolution.y());
 
-	m_internalResolution = UVec2(Vec2(m_postProcessResolution) * ConfigSet::getSingleton().getRInternalRenderScaling());
+	m_internalResolution = UVec2(Vec2(m_postProcessResolution) * g_internalRenderScalingCVar.get());
 	alignRoundDown(2, m_internalResolution.x());
 	alignRoundDown(2, m_internalResolution.y());
 
 	ANKI_R_LOGI("Initializing offscreen renderer. Resolution %ux%u. Internal resolution %ux%u", m_postProcessResolution.x(),
 				m_postProcessResolution.y(), m_internalResolution.x(), m_internalResolution.y());
 
-	m_tileSize = ConfigSet::getSingleton().getRTileSize();
+	m_tileSize = g_tileSizeCVar.get();
 	m_tileCounts.x() = (m_internalResolution.x() + m_tileSize - 1) / m_tileSize;
 	m_tileCounts.y() = (m_internalResolution.y() + m_tileSize - 1) / m_tileSize;
-	m_zSplitCount = ConfigSet::getSingleton().getRZSplitCount();
+	m_zSplitCount = g_zSplitCountCVar.get();
 
 	// A few sanity checks
 	if(m_internalResolution.x() < 64 || m_internalResolution.y() < 64)
@@ -223,7 +238,7 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 	m_indirectDiffuse.reset(newInstance<IndirectDiffuse>(RendererMemoryPool::getSingleton()));
 	ANKI_CHECK(m_indirectDiffuse->init());
 
-	if(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && ConfigSet::getSingleton().getSceneRayTracedShadows())
+	if(GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rayTracedShadowsCVar.get())
 	{
 		m_accelerationStructureBuilder.reset(newInstance<AccelerationStructureBuilder>(RendererMemoryPool::getSingleton()));
 		ANKI_CHECK(m_accelerationStructureBuilder->init());
@@ -267,7 +282,7 @@ Error Renderer::initInternal(UVec2 swapchainResolution)
 		m_samplers.m_trilinearRepeat = GrManager::getSingleton().newSampler(sinit);
 
 		sinit.setName("TrilinearRepeatAniso");
-		sinit.m_anisotropyLevel = ConfigSet::getSingleton().getRTextureAnisotropy();
+		sinit.m_anisotropyLevel = g_textureAnisotropyCVar.get();
 		m_samplers.m_trilinearRepeatAniso = GrManager::getSingleton().newSampler(sinit);
 
 		sinit.setName("TrilinearRepeatAnisoRezScalingBias");
@@ -654,7 +669,7 @@ void Renderer::setCurrentDebugRenderTarget(CString rtName)
 Format Renderer::getHdrFormat() const
 {
 	Format out;
-	if(!ConfigSet::getSingleton().getRHighQualityHdr())
+	if(!g_highQualityHdrCVar.get())
 	{
 		out = Format::kB10G11R11_Ufloat_Pack32;
 	}

+ 6 - 0
AnKi/Renderer/Renderer.h

@@ -17,6 +17,12 @@
 
 namespace anki {
 
+// Forward
+extern BoolCVar g_vrsCVar;
+extern BoolCVar g_vrsLimitTo2x2CVar;
+extern BoolCVar g_preferComputeCVar;
+extern NumericCVar<F32> g_renderScalingCVar;
+
 /// @addtogroup renderer
 /// @{
 

+ 8 - 3
AnKi/Renderer/RtShadows.cpp

@@ -22,6 +22,11 @@
 
 namespace anki {
 
+static BoolCVar g_rtShadowsSvgfCVar(CVarSubsystem::kRenderer, "RtShadowsSvgf", false, "Enable or not RT shadows SVGF");
+static NumericCVar<U8> g_rtShadowsSvgfAtrousPassCountCVar(CVarSubsystem::kRenderer, "RtShadowsSvgfAtrousPassCount", 3, 1, 20,
+														  "Number of atrous passes of SVGF");
+static NumericCVar<U32> g_rtShadowsRaysPerPixelCVar(CVarSubsystem::kRenderer, "RtShadowsRaysPerPixel", 1, 1, 8, "Number of shadow rays per pixel");
+
 Error RtShadows::init()
 {
 	const Error err = initInternal();
@@ -37,8 +42,8 @@ Error RtShadows::initInternal()
 {
 	ANKI_R_LOGV("Initializing RT shadows");
 
-	m_useSvgf = ConfigSet::getSingleton().getRRtShadowsSvgf();
-	m_atrousPassCount = ConfigSet::getSingleton().getRRtShadowsSvgfAtrousPassCount();
+	m_useSvgf = g_rtShadowsSvgfCVar.get();
+	m_atrousPassCount = g_rtShadowsSvgfAtrousPassCountCVar.get();
 
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_blueNoiseImage));
 
@@ -47,7 +52,7 @@ Error RtShadows::initInternal()
 		ANKI_CHECK(ResourceManager::getSingleton().loadResource("ShaderBinaries/RtShadowsRayGen.ankiprogbin", m_rayGenProg));
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_rayGenProg);
-		variantInitInfo.addMutation("RAYS_PER_PIXEL", ConfigSet::getSingleton().getRRtShadowsRaysPerPixel());
+		variantInitInfo.addMutation("RAYS_PER_PIXEL", g_rtShadowsRaysPerPixelCVar.get());
 
 		const ShaderProgramResourceVariant* variant;
 		m_rayGenProg->getOrCreateVariant(variantInitInfo, variant);

+ 14 - 9
AnKi/Renderer/Scale.cpp

@@ -32,18 +32,23 @@
 
 namespace anki {
 
+static NumericCVar<U8> g_fsrQualityCVar(CVarSubsystem::kRenderer, "FsrQuality", 1, 0, 2, "0: Use bilinear, 1: FSR low quality, 2: FSR high quality");
+static NumericCVar<U8> g_dlssQualityCVar(CVarSubsystem::kRenderer, "DlssQuality", 2, 0, 3, "0: Disabled, 1: Performance, 2: Balanced, 3: Quality");
+static NumericCVar<F32> g_sharpnessCVar(CVarSubsystem::kRenderer, "Sharpness", (ANKI_PLATFORM_MOBILE) ? 0.0f : 0.8f, 0.0f, 1.0f,
+										"Sharpen the image. It's a factor");
+
 Error Scale::init()
 {
 	const Bool needsScaling = getRenderer().getPostProcessResolution() != getRenderer().getInternalResolution();
-	const Bool needsSharpening = ConfigSet::getSingleton().getRSharpness() > 0.0f;
+	const Bool needsSharpening = g_sharpnessCVar.get() > 0.0f;
 	if(!needsScaling && !needsSharpening)
 	{
 		return Error::kNone;
 	}
 
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
-	const U32 dlssQuality = ConfigSet::getSingleton().getRDlssQuality();
-	const U32 fsrQuality = ConfigSet::getSingleton().getRFsrQuality();
+	const Bool preferCompute = g_preferComputeCVar.get();
+	const U32 dlssQuality = g_dlssQualityCVar.get();
+	const U32 fsrQuality = g_fsrQualityCVar.get();
 
 	if(needsScaling)
 	{
@@ -178,7 +183,7 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 	}
 
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 
 	// Step 1: Upscaling
 	if(m_upscalingMethod == UpscalingMethod::kGr)
@@ -312,7 +317,7 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 void Scale::runFsrOrBilinearScaling(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 	const RenderTargetHandle inRt = getRenderer().getTemporalAA().getTonemappedRt();
 	const RenderTargetHandle outRt = m_runCtx.m_upscaledTonemappedRt;
 
@@ -376,7 +381,7 @@ void Scale::runFsrOrBilinearScaling(RenderPassWorkContext& rgraphCtx)
 void Scale::runRcasSharpening(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 	const RenderTargetHandle inRt = m_runCtx.m_tonemappedRt;
 	const RenderTargetHandle outRt = m_runCtx.m_sharpenedRt;
 
@@ -401,7 +406,7 @@ void Scale::runRcasSharpening(RenderPassWorkContext& rgraphCtx)
 		UVec2 m_padding;
 	} pc;
 
-	F32 sharpness = ConfigSet::getSingleton().getRSharpness(); // [0, 1]
+	F32 sharpness = g_sharpnessCVar.get(); // [0, 1]
 	sharpness *= 3.0f; // [0, 3]
 	sharpness = 3.0f - sharpness; // [3, 0], RCAS translates 0 to max sharpness
 	FsrRcasCon(&pc.m_fsrConsts0[0], sharpness);
@@ -444,7 +449,7 @@ void Scale::runGrUpscaling(RenderingContext& ctx, RenderPassWorkContext& rgraphC
 void Scale::runTonemapping(RenderPassWorkContext& rgraphCtx)
 {
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 	const RenderTargetHandle inRt = m_runCtx.m_upscaledHdrRt;
 	const RenderTargetHandle outRt = m_runCtx.m_tonemappedRt;
 

+ 15 - 9
AnKi/Renderer/ShadowMapping.cpp

@@ -7,12 +7,19 @@
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/RenderQueue.h>
-#include <AnKi/Core/ConfigSet.h>
+#include <AnKi/Core/App.h>
 #include <AnKi/Util/ThreadHive.h>
 #include <AnKi/Util/Tracer.h>
 
 namespace anki {
 
+static NumericCVar<U32> g_shadowMappingTileResolutionCVar(CVarSubsystem::kRenderer, "ShadowMappingTileResolution", (ANKI_PLATFORM_MOBILE) ? 128 : 256,
+														  16, 2048, "Shadowmapping tile resolution");
+static NumericCVar<U32> g_shadowMappingTileCountPerRowOrColumnCVar(CVarSubsystem::kRenderer, "ShadowMappingTileCountPerRowOrColumn", 32, 1, 256,
+																   "Shadowmapping atlas will have this number squared number of tiles");
+NumericCVar<U32> g_shadowMappingPcfCVar(CVarSubsystem::kRenderer, "ShadowMappingPcf", (ANKI_PLATFORM_MOBILE) ? 0 : 1, 0, 1,
+										"Shadow PCF (CVarSubsystem::kRenderer, 0: off, 1: on)");
+
 class ShadowMapping::ViewportWorkItem
 {
 public:
@@ -38,8 +45,8 @@ Error ShadowMapping::initInternal()
 {
 	// Init RT
 	{
-		m_tileResolution = ConfigSet::getSingleton().getRShadowMappingTileResolution();
-		m_tileCountBothAxis = ConfigSet::getSingleton().getRShadowMappingTileCountPerRowOrColumn();
+		m_tileResolution = g_shadowMappingTileResolutionCVar.get();
+		m_tileCountBothAxis = g_shadowMappingTileCountPerRowOrColumnCVar.get();
 
 		ANKI_R_LOGV("Initializing shadowmapping. Atlas resolution %ux%u", m_tileResolution * m_tileCountBothAxis,
 					m_tileResolution * m_tileCountBothAxis);
@@ -156,7 +163,7 @@ void ShadowMapping::chooseDetail(const Vec4& cameraOrigin, const PointLightQueue
 								 U32& renderQueueElementsLod) const
 {
 	const F32 distFromTheCamera = (cameraOrigin - light.m_worldPosition.xyz0()).getLength() - light.m_radius;
-	if(distFromTheCamera < ConfigSet::getSingleton().getLod0MaxDistance())
+	if(distFromTheCamera < g_lod0MaxDistanceCVar.get())
 	{
 		tileAllocatorHierarchy = kPointLightMaxTileAllocHierarchy;
 		renderQueueElementsLod = 0;
@@ -182,12 +189,12 @@ void ShadowMapping::chooseDetail(const Vec4& cameraOrigin, const SpotLightQueueE
 	const F32 V1len = V.dot(coneDir);
 	const F32 distFromTheCamera = cos(coneAngle) * sqrt(VlenSq - V1len * V1len) - V1len * sin(coneAngle);
 
-	if(distFromTheCamera < ConfigSet::getSingleton().getLod0MaxDistance())
+	if(distFromTheCamera < g_lod0MaxDistanceCVar.get())
 	{
 		tileAllocatorHierarchy = kSpotLightMaxTileAllocHierarchy;
 		renderQueueElementsLod = 0;
 	}
-	else if(distFromTheCamera < ConfigSet::getSingleton().getLod1MaxDistance())
+	else if(distFromTheCamera < g_lod1MaxDistanceCVar.get())
 	{
 		tileAllocatorHierarchy = max(kSpotLightMaxTileAllocHierarchy, 1u) - 1;
 		renderQueueElementsLod = kMaxLodCount - 1;
@@ -248,8 +255,7 @@ void ShadowMapping::newWorkItem(const UVec4& atlasViewport, const RenderQueue& q
 {
 	ViewportWorkItem& work = *workItems.emplaceBack();
 
-	const Array<F32, kMaxLodCount - 1> lodDistances = {ConfigSet::getSingleton().getLod0MaxDistance(),
-													   ConfigSet::getSingleton().getLod1MaxDistance()};
+	const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
 	getRenderer().getGpuVisibility().populateRenderGraph("Shadowmapping visibility", RenderingTechnique::kDepth, queue.m_viewProjectionMatrix,
 														 queue.m_cameraTransform.getTranslationPart().xyz(), lodDistances, hzbRt, rgraph,
 														 work.m_visOut);
@@ -373,7 +379,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 
 			// Remove a few texels to avoid bilinear filtering bleeding
 			F32 texelsBorder;
-			if(ConfigSet::getSingleton().getRShadowMappingPcf())
+			if(g_shadowMappingPcfCVar.get())
 			{
 				texelsBorder = 2.0f; // 2 texels
 			}

+ 1 - 0
AnKi/Renderer/ShadowMapping.h

@@ -15,6 +15,7 @@ namespace anki {
 // Forward
 class PointLightQueueElement;
 class SpotLightQueueElement;
+extern NumericCVar<U32> g_shadowMappingPcfCVar;
 
 /// @addtogroup renderer
 /// @{

+ 8 - 7
AnKi/Renderer/ShadowmapsResolve.cpp

@@ -14,6 +14,8 @@
 
 namespace anki {
 
+static BoolCVar g_smResolveQuarterRezCVar(CVarSubsystem::kRenderer, "SmResolveQuarterRez", ANKI_PLATFORM_MOBILE, "Shadowmapping resolve quality");
+
 Error ShadowmapsResolve::init()
 {
 	const Error err = initInternal();
@@ -27,7 +29,7 @@ Error ShadowmapsResolve::init()
 
 Error ShadowmapsResolve::initInternal()
 {
-	m_quarterRez = ConfigSet::getSingleton().getRSmResolveQuarterRez();
+	m_quarterRez = g_smResolveQuarterRezCVar.get();
 	const U32 width = getRenderer().getInternalResolution().x() / (m_quarterRez + 1);
 	const U32 height = getRenderer().getInternalResolution().y() / (m_quarterRez + 1);
 
@@ -41,16 +43,15 @@ Error ShadowmapsResolve::initInternal()
 	m_fbDescr.bake();
 
 	// Prog
-	ANKI_CHECK(ResourceManager::getSingleton().loadResource((ConfigSet::getSingleton().getRPreferCompute())
-																? "ShaderBinaries/ShadowmapsResolveCompute.ankiprogbin"
-																: "ShaderBinaries/ShadowmapsResolveRaster.ankiprogbin",
+	ANKI_CHECK(ResourceManager::getSingleton().loadResource((g_preferComputeCVar.get()) ? "ShaderBinaries/ShadowmapsResolveCompute.ankiprogbin"
+																						: "ShaderBinaries/ShadowmapsResolveRaster.ankiprogbin",
 															m_prog));
 	ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 	variantInitInfo.addConstant("kFramebufferSize", UVec2(width, height));
 	variantInitInfo.addConstant("kTileCount", getRenderer().getTileCounts());
 	variantInitInfo.addConstant("kZSplitCount", getRenderer().getZSplitCount());
 	variantInitInfo.addConstant("kTileSize", getRenderer().getTileSize());
-	variantInitInfo.addMutation("PCF", ConfigSet::getSingleton().getRShadowMappingPcf());
+	variantInitInfo.addMutation("PCF", g_shadowMappingPcfCVar.get() != 0);
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInitInfo, variant);
 	m_grProg.reset(&variant->getProgram());
@@ -65,7 +66,7 @@ void ShadowmapsResolve::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphDescription& rgraph = ctx.m_renderGraphDescr;
 	m_runCtx.m_rt = rgraph.newRenderTarget(m_rtDescr);
 
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		ComputeRenderPassDescription& rpass = rgraph.newComputeRenderPass("ResolveShadows");
 
@@ -124,7 +125,7 @@ void ShadowmapsResolve::run(RenderPassWorkContext& rgraphCtx)
 	}
 	cmdb.bindTexture(0, 9, &m_noiseImage->getTextureView());
 
-	if(ConfigSet::getSingleton().getRPreferCompute())
+	if(g_preferComputeCVar.get())
 	{
 		rgraphCtx.bindImage(0, 10, m_runCtx.m_rt, TextureSubresourceInfo());
 		dispatchPPCompute(cmdb, 8, 8, m_rtDescr.m_width, m_rtDescr.m_height);

+ 6 - 8
AnKi/Renderer/TemporalAA.cpp

@@ -28,10 +28,8 @@ Error TemporalAA::initInternal()
 {
 	ANKI_R_LOGV("Initializing TAA");
 
-	ANKI_CHECK(ResourceManager::getSingleton().loadResource((ConfigSet::getSingleton().getRPreferCompute())
-																? "ShaderBinaries/TemporalAACompute.ankiprogbin"
-																: "ShaderBinaries/TemporalAARaster.ankiprogbin",
-															m_prog));
+	ANKI_CHECK(ResourceManager::getSingleton().loadResource(
+		(g_preferComputeCVar.get()) ? "ShaderBinaries/TemporalAACompute.ankiprogbin" : "ShaderBinaries/TemporalAARaster.ankiprogbin", m_prog));
 
 	{
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
@@ -40,7 +38,7 @@ Error TemporalAA::initInternal()
 		variantInitInfo.addMutation("VARIANCE_CLIPPING", 1);
 		variantInitInfo.addMutation("YCBCR", 0);
 
-		if(ConfigSet::getSingleton().getRPreferCompute())
+		if(g_preferComputeCVar.get())
 		{
 			variantInitInfo.addConstant("kFramebufferSize",
 										UVec2(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y()));
@@ -54,7 +52,7 @@ Error TemporalAA::initInternal()
 	for(U i = 0; i < 2; ++i)
 	{
 		TextureUsageBit usage = TextureUsageBit::kSampledFragment | TextureUsageBit::kSampledCompute;
-		usage |= (ConfigSet::getSingleton().getRPreferCompute()) ? TextureUsageBit::kImageComputeWrite : TextureUsageBit::kFramebufferWrite;
+		usage |= (g_preferComputeCVar.get()) ? TextureUsageBit::kImageComputeWrite : TextureUsageBit::kFramebufferWrite;
 
 		TextureInitInfo texinit = getRenderer().create2DRenderTargetInitInfo(
 			getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), getRenderer().getHdrFormat(), usage, "TemporalAA");
@@ -80,7 +78,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 
 	const U32 historyRtIdx = (getRenderer().getFrameCount() + 1) & 1;
 	const U32 renderRtIdx = !historyRtIdx;
-	const Bool preferCompute = ConfigSet::getSingleton().getRPreferCompute();
+	const Bool preferCompute = g_preferComputeCVar.get();
 
 	// Import RTs
 	if(m_rtTexturesImportedOnce[historyRtIdx]) [[likely]]
@@ -139,7 +137,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 		rgraphCtx.bindColorTexture(0, 3, getRenderer().getMotionVectors().getMotionVectorsRt());
 		rgraphCtx.bindImage(0, 4, getRenderer().getTonemapping().getRt());
 
-		if(ConfigSet::getSingleton().getRPreferCompute())
+		if(g_preferComputeCVar.get())
 		{
 			rgraphCtx.bindImage(0, 5, m_runCtx.m_renderRt, TextureSubresourceInfo());
 			rgraphCtx.bindImage(0, 6, m_runCtx.m_tonemappedRt, TextureSubresourceInfo());

+ 3 - 3
AnKi/Renderer/VolumetricFog.cpp

@@ -17,9 +17,9 @@ namespace anki {
 Error VolumetricFog::init()
 {
 	// Misc
-	const F32 qualityXY = ConfigSet::getSingleton().getRVolumetricLightingAccumulationQualityXY();
-	const F32 qualityZ = ConfigSet::getSingleton().getRVolumetricLightingAccumulationQualityZ();
-	m_finalZSplit = min(getRenderer().getZSplitCount() - 1, ConfigSet::getSingleton().getRVolumetricLightingAccumulationFinalZSplit());
+	const F32 qualityXY = g_volumetricLightingAccumulationQualityXYCVar.get();
+	const F32 qualityZ = g_volumetricLightingAccumulationQualityZCVar.get();
+	m_finalZSplit = min(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar.get());
 
 	m_volumeSize[0] = U32(F32(getRenderer().getTileCounts().x()) * qualityXY);
 	m_volumeSize[1] = U32(F32(getRenderer().getTileCounts().y()) * qualityXY);

+ 10 - 3
AnKi/Renderer/VolumetricLightingAccumulation.cpp

@@ -14,12 +14,19 @@
 
 namespace anki {
 
+NumericCVar<F32> g_volumetricLightingAccumulationQualityXYCVar(CVarSubsystem::kRenderer, "VolumetricLightingAccumulationQualityXY", 4.0f, 1.0f, 16.0f,
+															   "Quality of XY dimensions of volumetric lights");
+NumericCVar<F32> g_volumetricLightingAccumulationQualityZCVar(CVarSubsystem::kRenderer, "VolumetricLightingAccumulationQualityZ", 4.0f, 1.0f, 16.0f,
+															  "Quality of Z dimension of volumetric lights");
+NumericCVar<U32> g_volumetricLightingAccumulationFinalZSplitCVar(CVarSubsystem::kRenderer, "VolumetricLightingAccumulationFinalZSplit", 26, 1, 256,
+																 "Final cluster split that will recieve volumetric lights");
+
 Error VolumetricLightingAccumulation::init()
 {
 	// Misc
-	const F32 qualityXY = ConfigSet::getSingleton().getRVolumetricLightingAccumulationQualityXY();
-	const F32 qualityZ = ConfigSet::getSingleton().getRVolumetricLightingAccumulationQualityZ();
-	m_finalZSplit = min(getRenderer().getZSplitCount() - 1, ConfigSet::getSingleton().getRVolumetricLightingAccumulationFinalZSplit());
+	const F32 qualityXY = g_volumetricLightingAccumulationQualityXYCVar.get();
+	const F32 qualityZ = g_volumetricLightingAccumulationQualityZCVar.get();
+	m_finalZSplit = min(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar.get());
 
 	m_volumeSize[0] = U32(F32(getRenderer().getTileCounts().x()) * qualityXY);
 	m_volumeSize[1] = U32(F32(getRenderer().getTileCounts().y()) * qualityXY);

+ 5 - 0
AnKi/Renderer/VolumetricLightingAccumulation.h

@@ -9,6 +9,11 @@
 
 namespace anki {
 
+// Forward
+extern NumericCVar<F32> g_volumetricLightingAccumulationQualityXYCVar;
+extern NumericCVar<F32> g_volumetricLightingAccumulationQualityZCVar;
+extern NumericCVar<U32> g_volumetricLightingAccumulationFinalZSplitCVar;
+
 /// @addtogroup renderer
 /// @{
 

+ 7 - 4
AnKi/Renderer/VrsSriGeneration.cpp

@@ -10,6 +10,9 @@
 
 namespace anki {
 
+static NumericCVar<F32> g_vrsThresholdCVar(CVarSubsystem::kRenderer, "VrsThreshold", 0.1f, 0.0f, 1.0f,
+										   "Threshold under which a lower shading rate will be applied");
+
 Error VrsSriGeneration::init()
 {
 	const Error err = initInternal();
@@ -64,7 +67,7 @@ Error VrsSriGeneration::initInternal()
 		variantInit.addMutation("SHARED_MEMORY", 1);
 	}
 
-	variantInit.addMutation("LIMIT_RATE_TO_2X2", ConfigSet::getSingleton().getRVrsLimitTo2x2());
+	variantInit.addMutation("LIMIT_RATE_TO_2X2", g_vrsLimitTo2x2CVar.get());
 
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInit, variant);
@@ -99,7 +102,7 @@ void VrsSriGeneration::getDebugRenderTarget(CString rtName, Array<RenderTargetHa
 
 void VrsSriGeneration::importRenderTargets(RenderingContext& ctx)
 {
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get();
 	if(!enableVrs)
 	{
 		return;
@@ -120,7 +123,7 @@ void VrsSriGeneration::importRenderTargets(RenderingContext& ctx)
 
 void VrsSriGeneration::populateRenderGraph(RenderingContext& ctx)
 {
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && ConfigSet::getSingleton().getRVrs();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get();
 	if(!enableVrs)
 	{
 		return;
@@ -143,7 +146,7 @@ void VrsSriGeneration::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindColorTexture(0, 0, getRenderer().getLightShading().getRt());
 			cmdb.bindSampler(0, 1, getRenderer().getSamplers().m_nearestNearestClamp.get());
 			rgraphCtx.bindImage(0, 2, m_runCtx.m_rt);
-			const Vec4 pc(1.0f / Vec2(getRenderer().getInternalResolution()), ConfigSet::getSingleton().getRVrsThreshold(), 0.0f);
+			const Vec4 pc(1.0f / Vec2(getRenderer().getInternalResolution()), g_vrsThresholdCVar.get(), 0.0f);
 			cmdb.setPushConstants(&pc, sizeof(pc));
 
 			const U32 fakeWorkgroupSizeXorY = m_sriTexelDimension;

+ 0 - 15
AnKi/Resource/ConfigVars.defs.h

@@ -1,15 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-ANKI_CONFIG_VAR_GROUP(RSRC)
-
-ANKI_CONFIG_VAR_U32(RsrcMaxImageSize, 1024u * 1024u, 4u, kMaxU32, "Max image size to load")
-ANKI_CONFIG_VAR_STRING(RsrcDataPaths, ".",
-					   "The engine loads assets only in from these paths. Separate them with : (it's smart enough to identify drive "
-					   "letters in Windows)")
-ANKI_CONFIG_VAR_STRING(RsrcDataPathExcludedStrings, "AndroidProject",
-					   "A list of string separated by : that will be used to exclude paths from rsrc_dataPaths")
-ANKI_CONFIG_VAR_PTR_SIZE(RsrcTransferScratchMemorySize, 256_MB, 1_MB, 4_GB, "Memory that is used fot texture and buffer uploads")
-ANKI_CONFIG_VAR_BOOL(RsrcForceFullFpPrecision, false, "Force full floating point precision")

+ 3 - 1
AnKi/Resource/ImageResource.cpp

@@ -12,6 +12,8 @@
 
 namespace anki {
 
+static NumericCVar<U32> g_maxImageSizeCVar(CVarSubsystem::kResource, "MaxImageSize", 1024u * 1024u, 4u, kMaxU32, "Max image size to load");
+
 class ImageResource::LoadingContext
 {
 public:
@@ -66,7 +68,7 @@ Error ImageResource::load(const ResourceFilename& filename, Bool async)
 	ResourceFilePtr file;
 	ANKI_CHECK(openFile(filename, file));
 
-	ANKI_CHECK(loader.load(file, filename, ConfigSet::getSingleton().getRsrcMaxImageSize()));
+	ANKI_CHECK(loader.load(file, filename, g_maxImageSizeCVar.get()));
 
 	// Various sizes
 	init.m_width = loader.getWidth();

+ 9 - 3
AnKi/Resource/ResourceFilesystem.cpp

@@ -14,6 +14,12 @@
 
 namespace anki {
 
+StringCVar g_dataPathsCVar(CVarSubsystem::kResource, "DataPaths", ".",
+						   "The engine loads assets only in from these paths. Separate them with : (it's smart enough to identify drive "
+						   "letters in Windows)");
+static StringCVar g_dataPathExcludeStringsCVar(CVarSubsystem::kResource, "DataPathExcludedStrings", "AndroidProject",
+											   "A list of string separated by : that will be used to exclude paths from rsrc_dataPaths");
+
 /// C resource file
 class CResourceFile final : public ResourceFile
 {
@@ -192,10 +198,10 @@ ResourceFilesystem::~ResourceFilesystem()
 Error ResourceFilesystem::init()
 {
 	ResourceStringList paths;
-	paths.splitString(ConfigSet::getSingleton().getRsrcDataPaths(), ':');
+	paths.splitString(g_dataPathsCVar.get(), ':');
 
 	ResourceStringList excludedStrings;
-	excludedStrings.splitString(ConfigSet::getSingleton().getRsrcDataPathExcludedStrings(), ':');
+	excludedStrings.splitString(g_dataPathExcludeStringsCVar.get(), ':');
 
 	// Workaround the fact that : is used in drives in Windows
 #if ANKI_OS_WINDOWS
@@ -224,7 +230,7 @@ Error ResourceFilesystem::init()
 
 	if(paths.getSize() < 1)
 	{
-		ANKI_RESOURCE_LOGE("Config option \"RsrcDataPaths\" is empty");
+		ANKI_RESOURCE_LOGE("Config option \"g_dataPathsCVar\" is empty");
 		return Error::kUserData;
 	}
 

+ 4 - 0
AnKi/Resource/ResourceFilesystem.h

@@ -10,9 +10,13 @@
 #include <AnKi/Util/StringList.h>
 #include <AnKi/Util/File.h>
 #include <AnKi/Util/Ptr.h>
+#include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
 
+// Forward
+extern StringCVar g_dataPathsCVar;
+
 /// @addtogroup resource
 /// @{
 

+ 4 - 1
AnKi/Resource/ResourceManager.cpp

@@ -25,6 +25,9 @@
 
 namespace anki {
 
+static NumericCVar<PtrSize> g_transferScratchMemorySizeCVar(CVarSubsystem::kResource, "TransferScratchMemorySize", 256_MB, 1_MB, 4_GB,
+															"Memory that is used fot texture and buffer uploads");
+
 ResourceManager::ResourceManager()
 {
 }
@@ -54,7 +57,7 @@ Error ResourceManager::init(AllocAlignedCallback allocCallback, void* allocCallb
 	m_asyncLoader = newInstance<AsyncLoader>(ResourceMemoryPool::getSingleton());
 
 	m_transferGpuAlloc = newInstance<TransferGpuAllocator>(ResourceMemoryPool::getSingleton());
-	ANKI_CHECK(m_transferGpuAlloc->init(ConfigSet::getSingleton().getRsrcTransferScratchMemorySize()));
+	ANKI_CHECK(m_transferGpuAlloc->init(g_transferScratchMemorySizeCVar.get()));
 
 	// Init the programs
 	m_shaderProgramSystem = newInstance<ShaderProgramResourceSystem>(ResourceMemoryPool::getSingleton());

+ 28 - 13
AnKi/Scene/Components/CameraComponent.cpp

@@ -7,42 +7,57 @@
 #include <AnKi/Scene/Components/MoveComponent.h>
 #include <AnKi/Scene/SceneNode.h>
 #include <AnKi/Gr/GrManager.h>
-#include <AnKi/Core/ConfigSet.h>
+#include <AnKi/Core/App.h>
 
 namespace anki {
 
+static NumericCVar<U8> g_shadowCascadeCountCVar(CVarSubsystem::kScene, "ShadowCascadeCount", (ANKI_PLATFORM_MOBILE) ? 2 : kMaxShadowCascades, 1,
+												kMaxShadowCascades, "Max number of shadow cascades for directional lights");
+static NumericCVar<F32> g_shadowCascade0DistanceCVar(CVarSubsystem::kScene, "ShadowCascade0Distance", 18.0, 1.0, kMaxF32,
+													 "The distance of the 1st cascade");
+static NumericCVar<F32> g_shadowCascade1DistanceCVar(CVarSubsystem::kScene, "ShadowCascade1Distance", 40.0, 1.0, kMaxF32,
+													 "The distance of the 2nd cascade");
+static NumericCVar<F32> g_shadowCascade2DistanceCVar(CVarSubsystem::kScene, "ShadowCascade2Distance", 80.0, 1.0, kMaxF32,
+													 "The distance of the 3rd cascade");
+static NumericCVar<F32> g_shadowCascade3DistanceCVar(CVarSubsystem::kScene, "ShadowCascade3Distance", 200.0, 1.0, kMaxF32,
+													 "The distance of the 4th cascade");
+static NumericCVar<F32> g_earyZDistanceCVar(CVarSubsystem::kScene, "EarlyZDistance", (ANKI_PLATFORM_MOBILE) ? 0.0f : 10.0f, 0.0f, kMaxF32,
+											"Objects with distance lower than that will be used in early Z");
+BoolCVar g_rayTracedShadowsCVar(CVarSubsystem::kScene, "RayTracedShadows", true, "Enable or not ray traced shadows. Ignored if RT is not supported");
+static NumericCVar<F32>
+	g_rayTracingExtendedFrustumDistanceCVar(CVarSubsystem::kScene, "RayTracingExtendedFrustumDistance", 100.0f, 10.0f, 10000.0f,
+											"Every object that its distance from the camera is bellow that value will take part in ray tracing");
+
 CameraComponent::CameraComponent(SceneNode* node)
 	: SceneComponent(node, getStaticClassId())
 {
-	const ConfigSet& config = ConfigSet::getSingleton();
-
 	// Init main frustum
 	m_frustum.init(FrustumType::kPerspective);
 
-	m_frustum.setLodDistance(0, config.getLod0MaxDistance());
-	m_frustum.setLodDistance(1, config.getLod1MaxDistance());
-	m_frustum.setShadowCascadeCount(config.getSceneShadowCascadeCount());
+	m_frustum.setLodDistance(0, g_lod0MaxDistanceCVar.get());
+	m_frustum.setLodDistance(1, g_lod1MaxDistanceCVar.get());
+	m_frustum.setShadowCascadeCount(g_shadowCascadeCountCVar.get());
 
 	static_assert(kMaxShadowCascades == 4);
-	m_frustum.setShadowCascadeDistance(0, config.getSceneShadowCascade0Distance());
-	m_frustum.setShadowCascadeDistance(1, config.getSceneShadowCascade1Distance());
-	m_frustum.setShadowCascadeDistance(2, config.getSceneShadowCascade2Distance());
-	m_frustum.setShadowCascadeDistance(3, config.getSceneShadowCascade3Distance());
+	m_frustum.setShadowCascadeDistance(0, g_shadowCascade0DistanceCVar.get());
+	m_frustum.setShadowCascadeDistance(1, g_shadowCascade1DistanceCVar.get());
+	m_frustum.setShadowCascadeDistance(2, g_shadowCascade2DistanceCVar.get());
+	m_frustum.setShadowCascadeDistance(3, g_shadowCascade3DistanceCVar.get());
 
 	m_frustum.setWorldTransform(node->getWorldTransform());
 
-	m_frustum.setEarlyZDistance(config.getSceneEarlyZDistance());
+	m_frustum.setEarlyZDistance(g_earyZDistanceCVar.get());
 
 	m_frustum.update();
 
 	// Init extended frustum
-	m_usesExtendedFrustum = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && config.getSceneRayTracedShadows();
+	m_usesExtendedFrustum = GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled && g_rayTracedShadowsCVar.get();
 
 	if(m_usesExtendedFrustum)
 	{
 		m_extendedFrustum.init(FrustumType::kOrthographic);
 
-		const F32 dist = config.getSceneRayTracingExtendedFrustumDistance();
+		const F32 dist = g_rayTracingExtendedFrustumDistanceCVar.get();
 
 		m_extendedFrustum.setOrthographic(0.1f, dist * 2.0f, dist, -dist, dist, -dist);
 		m_extendedFrustum.setWorldTransform(computeExtendedFrustumTransform(node->getWorldTransform()));

+ 3 - 0
AnKi/Scene/Components/CameraComponent.h

@@ -10,6 +10,9 @@
 
 namespace anki {
 
+// Forward
+extern BoolCVar g_rayTracedShadowsCVar;
+
 /// @addtogroup scene
 /// @{
 

+ 2 - 2
AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp

@@ -136,9 +136,9 @@ Error GlobalIlluminationProbeComponent::update(SceneComponentUpdateInfo& info, B
 
 		F32 effectiveDistance = max(m_halfSize.x(), m_halfSize.y());
 		effectiveDistance = max(effectiveDistance, m_halfSize.z());
-		effectiveDistance = max(effectiveDistance, ConfigSet::getSingleton().getSceneProbeEffectiveDistance());
+		effectiveDistance = max(effectiveDistance, g_probeEffectiveDistanceCVar.get());
 
-		const F32 shadowCascadeDistance = min(effectiveDistance, ConfigSet::getSingleton().getSceneProbeShadowEffectiveDistance());
+		const F32 shadowCascadeDistance = min(effectiveDistance, g_probeShadowEffectiveDistanceCVar.get());
 
 		for(U32 i = 0; i < 6; ++i)
 		{

+ 6 - 3
AnKi/Scene/Components/ReflectionProbeComponent.cpp

@@ -11,6 +11,9 @@
 
 namespace anki {
 
+NumericCVar<U32> g_reflectionProbeResolutionCVar(CVarSubsystem::kScene, "ReflectionProbeResolution", 128, 8, 2048,
+												 "The resolution of the reflection probe's reflection");
+
 ReflectionProbeComponent::ReflectionProbeComponent(SceneNode* node)
 	: QueryableSceneComponent<ReflectionProbeComponent>(node, getStaticClassId())
 	, m_spatial(this)
@@ -46,7 +49,7 @@ Error ReflectionProbeComponent::update(SceneComponentUpdateInfo& info, Bool& upd
 		TextureInitInfo texInit("ReflectionProbe");
 		texInit.m_format = (GrManager::getSingleton().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::kR16G16B16_Sfloat
 																											: Format::kR16G16B16A16_Sfloat;
-		texInit.m_width = ConfigSet::getSingleton().getSceneReflectionProbeResolution();
+		texInit.m_width = g_reflectionProbeResolutionCVar.get();
 		texInit.m_height = texInit.m_width;
 		texInit.m_mipmapCount = U8(computeMaxMipmapCount2d(texInit.m_width, texInit.m_height, 8));
 		texInit.m_type = TextureType::kCube;
@@ -69,9 +72,9 @@ Error ReflectionProbeComponent::update(SceneComponentUpdateInfo& info, Bool& upd
 
 		F32 effectiveDistance = max(m_halfSize.x(), m_halfSize.y());
 		effectiveDistance = max(effectiveDistance, m_halfSize.z());
-		effectiveDistance = max(effectiveDistance, ConfigSet::getSingleton().getSceneProbeEffectiveDistance());
+		effectiveDistance = max(effectiveDistance, g_probeEffectiveDistanceCVar.get());
 
-		const F32 shadowCascadeDistance = min(effectiveDistance, ConfigSet::getSingleton().getSceneProbeShadowEffectiveDistance());
+		const F32 shadowCascadeDistance = min(effectiveDistance, g_probeShadowEffectiveDistanceCVar.get());
 
 		for(U32 i = 0; i < 6; ++i)
 		{

+ 2 - 0
AnKi/Scene/Components/ReflectionProbeComponent.h

@@ -13,6 +13,8 @@
 
 namespace anki {
 
+extern NumericCVar<U32> g_reflectionProbeResolutionCVar;
+
 /// @addtogroup scene
 /// @{
 

+ 0 - 40
AnKi/Scene/ConfigVars.defs.h

@@ -1,40 +0,0 @@
-// Copyright (C) 2009-2023, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-ANKI_CONFIG_VAR_GROUP(SCENE)
-
-ANKI_CONFIG_VAR_F32(Lod0MaxDistance, 20.0f, 1.0f, kMaxF32, "Distance that will be used to calculate the LOD 0")
-ANKI_CONFIG_VAR_F32(Lod1MaxDistance, 40.0f, 2.0f, kMaxF32, "Distance that will be used to calculate the LOD 1")
-
-ANKI_CONFIG_VAR_U8(SceneShadowCascadeCount, (ANKI_PLATFORM_MOBILE) ? 2 : kMaxShadowCascades, 1, kMaxShadowCascades,
-				   "Max number of shadow cascades for directional lights")
-ANKI_CONFIG_VAR_F32(SceneShadowCascade0Distance, 18.0, 1.0, kMaxF32, "The distance of the 1st cascade")
-ANKI_CONFIG_VAR_F32(SceneShadowCascade1Distance, 40.0, 1.0, kMaxF32, "The distance of the 2nd cascade")
-ANKI_CONFIG_VAR_F32(SceneShadowCascade2Distance, 80.0, 1.0, kMaxF32, "The distance of the 3rd cascade")
-ANKI_CONFIG_VAR_F32(SceneShadowCascade3Distance, 200.0, 1.0, kMaxF32, "The distance of the 4th cascade")
-
-ANKI_CONFIG_VAR_U32(SceneOctreeMaxDepth, 5, 2, 10, "The max depth of the octree")
-ANKI_CONFIG_VAR_F32(SceneEarlyZDistance, (ANKI_PLATFORM_MOBILE) ? 0.0f : 10.0f, 0.0f, kMaxF32,
-					"Objects with distance lower than that will be used in early Z")
-
-ANKI_CONFIG_VAR_F32(SceneProbeEffectiveDistance, 256.0f, 1.0f, kMaxF32, "How far various probes can render")
-ANKI_CONFIG_VAR_F32(SceneProbeShadowEffectiveDistance, 32.0f, 1.0f, kMaxF32, "How far to render shadows for the various probes")
-
-ANKI_CONFIG_VAR_BOOL(SceneRayTracedShadows, true, "Enable or not ray traced shadows. Ignored if RT is not supported")
-ANKI_CONFIG_VAR_F32(SceneRayTracingExtendedFrustumDistance, 100.0f, 10.0f, 10000.0f,
-					"Every object that its distance from the camera is bellow that value will take part in ray tracing")
-
-ANKI_CONFIG_VAR_U32(SceneReflectionProbeResolution, 128, 8, 2048, "The resolution of the reflection probe's reflection")
-
-// GPU scene
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneTransforms, 2 * 10 * 1024, 8, 100 * 1024, "The min number of transforms stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneMeshes, 8 * 1024, 8, 100 * 1024, "The min number of meshes stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneParticleEmitters, 1 * 1024, 8, 100 * 1024, "The min number of particle emitters stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneLights, 2 * 1024, 8, 100 * 1024, "The min number of lights stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneReflectionProbes, 128, 8, 100 * 1024, "The min number of reflection probes stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneGlobalIlluminationProbes, 128, 8, 100 * 1024, "The min number of GI probes stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneDecals, 2 * 1024, 8, 100 * 1024, "The min number of decals stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneFogDensityVolumes, 512, 8, 100 * 1024, "The min number fog density volumes stored in the GPU scene")
-ANKI_CONFIG_VAR_U32(SceneMinGpuSceneRenderables, 10 * 1024, 8, 100 * 1024, "The min number of renderables stored in the GPU scene")

+ 25 - 7
AnKi/Scene/ContiguousArrayAllocator.cpp

@@ -9,6 +9,25 @@
 
 namespace anki {
 
+static NumericCVar<U32> g_minGpuSceneTransformsCVar(CVarSubsystem::kScene, "MinGpuSceneTransforms", 2 * 10 * 1024, 8, 100 * 1024,
+													"The min number of transforms stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneMeshesCVar(CVarSubsystem::kScene, "MinGpuSceneMeshes", 8 * 1024, 8, 100 * 1024,
+												"The min number of meshes stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneParticleEmittersCVar(CVarSubsystem::kScene, "MinGpuSceneParticleEmitters", 1 * 1024, 8, 100 * 1024,
+														  "The min number of particle emitters stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneLightsCVar(CVarSubsystem::kScene, "MinGpuSceneLights", 2 * 1024, 8, 100 * 1024,
+												"The min number of lights stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneReflectionProbesCVar(CVarSubsystem::kScene, "MinGpuSceneReflectionProbes", 128, 8, 100 * 1024,
+														  "The min number of reflection probes stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneGlobalIlluminationProbesCVar(CVarSubsystem::kScene, "MinGpuSceneGlobalIlluminationProbes", 128, 8, 100 * 1024,
+																  "The min number of GI probes stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneDecalsCVar(CVarSubsystem::kScene, "MinGpuSceneDecals", 2 * 1024, 8, 100 * 1024,
+												"The min number of decals stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneFogDensityVolumesCVar(CVarSubsystem::kScene, "MinGpuSceneFogDensityVolumes", 512, 8, 100 * 1024,
+														   "The min number fog density volumes stored in the GPU scene");
+static NumericCVar<U32> g_minGpuSceneRenderablesCVar(CVarSubsystem::kScene, "MinGpuSceneRenderables", 10 * 1024, 8, 100 * 1024,
+													 "The min number of renderables stored in the GPU scene");
+
 void GpuSceneContiguousArrays::ContiguousArrayAllocator::destroy()
 {
 	for(U32 i = 0; i < kMaxFramesInFlight; ++i)
@@ -94,16 +113,15 @@ void GpuSceneContiguousArrays::ContiguousArrayAllocator::collectGarbage(U32 newF
 
 GpuSceneContiguousArrays::GpuSceneContiguousArrays()
 {
-	const ConfigSet& cfg = ConfigSet::getSingleton();
 	constexpr F32 kGrowRate = 2.0;
 
 	const Array<U32, U32(GpuSceneContiguousArrayType::kCount)> minElementCount = {
-		cfg.getSceneMinGpuSceneTransforms(),       cfg.getSceneMinGpuSceneMeshes(),
-		cfg.getSceneMinGpuSceneParticleEmitters(), cfg.getSceneMinGpuSceneLights(),
-		cfg.getSceneMinGpuSceneReflectionProbes(), cfg.getSceneMinGpuSceneGlobalIlluminationProbes(),
-		cfg.getSceneMinGpuSceneDecals(),           cfg.getSceneMinGpuSceneFogDensityVolumes(),
-		cfg.getSceneMinGpuSceneRenderables(),      cfg.getSceneMinGpuSceneRenderables(),
-		cfg.getSceneMinGpuSceneRenderables(),      cfg.getSceneMinGpuSceneRenderables()};
+		g_minGpuSceneTransformsCVar.get(),       g_minGpuSceneMeshesCVar.get(),
+		g_minGpuSceneParticleEmittersCVar.get(), g_minGpuSceneLightsCVar.get(),
+		g_minGpuSceneReflectionProbesCVar.get(), g_minGpuSceneGlobalIlluminationProbesCVar.get(),
+		g_minGpuSceneDecalsCVar.get(),           g_minGpuSceneFogDensityVolumesCVar.get(),
+		g_minGpuSceneRenderablesCVar.get(),      g_minGpuSceneRenderablesCVar.get(),
+		g_minGpuSceneRenderablesCVar.get(),      g_minGpuSceneRenderablesCVar.get()};
 
 	for(GpuSceneContiguousArrayType type : EnumIterable<GpuSceneContiguousArrayType>())
 	{

+ 8 - 1
AnKi/Scene/SceneGraph.cpp

@@ -22,6 +22,13 @@ static StatCounter g_sceneUpdateTime(StatCategory::kTime, "All scene update", St
 static StatCounter g_sceneVisibilityTime(StatCategory::kTime, "Scene visibility", StatFlag::kMilisecond | StatFlag::kShowAverage);
 static StatCounter g_scenePhysicsTime(StatCategory::kTime, "Physics", StatFlag::kMilisecond | StatFlag::kShowAverage);
 
+static NumericCVar<U32> g_octreeMaxDepthCVar(CVarSubsystem::kScene, "OctreeMaxDepth", 5, 2, 10, "The max depth of the octree");
+
+NumericCVar<F32> g_probeEffectiveDistanceCVar(CVarSubsystem::kScene, "ProbeEffectiveDistance", 256.0f, 1.0f, kMaxF32,
+											  "How far various probes can render");
+NumericCVar<F32> g_probeShadowEffectiveDistanceCVar(CVarSubsystem::kScene, "ProbeShadowEffectiveDistance", 32.0f, 1.0f, kMaxF32,
+													"How far to render shadows for the various probes");
+
 constexpr U32 kUpdateNodeBatchSize = 10;
 
 class SceneGraph::UpdateSceneNodesCtx
@@ -65,7 +72,7 @@ Error SceneGraph::init(AllocAlignedCallback allocCallback, void* allocCallbackDa
 	m_framePool.init(allocCallback, allocCallbackData, 1_MB, 2.0, 0, true, ANKI_SAFE_ALIGNMENT, "SceneGraphFramePool");
 
 	m_octree = newInstance<Octree>(SceneMemoryPool::getSingleton());
-	m_octree->init(m_sceneMin, m_sceneMax, ConfigSet::getSingleton().getSceneOctreeMaxDepth());
+	m_octree->init(m_sceneMin, m_sceneMax, g_octreeMaxDepthCVar.get());
 
 	// Init the default main camera
 	ANKI_CHECK(newSceneNode<SceneNode>("mainCamera", m_defaultMainCam));

+ 3 - 0
AnKi/Scene/SceneGraph.h

@@ -11,12 +11,15 @@
 #include <AnKi/Util/HashMap.h>
 #include <AnKi/Scene/Events/EventManager.h>
 #include <AnKi/Resource/Common.h>
+#include <AnKi/Core/ConfigSet.h>
 
 namespace anki {
 
 // Forward
 class Octree;
 class RenderQueue;
+extern NumericCVar<F32> g_probeEffectiveDistanceCVar;
+extern NumericCVar<F32> g_probeShadowEffectiveDistanceCVar;
 
 /// @addtogroup scene
 /// @{

+ 18 - 0
AnKi/Util/Singleton.h

@@ -127,6 +127,24 @@ private:
 
 template<typename T>
 T MakeSingletonSimple<T>::m_global;
+
+/// If class inherits that it will become a singleton. This is a simple version with implicit init.
+template<typename T>
+class MakeSingletonLazyInit
+{
+public:
+	ANKI_FORCE_INLINE static T& getSingleton()
+	{
+		if(m_global == nullptr) [[unlikely]]
+		{
+			m_global = new T;
+		}
+		return *m_global;
+	}
+
+private:
+	static inline T* m_global = nullptr;
+};
 /// @}
 
 } // end namespace anki

+ 7 - 8
Samples/Common/SampleApp.cpp

@@ -10,7 +10,7 @@ using namespace anki;
 Error SampleApp::init(int argc, char** argv, CString sampleName)
 {
 	// Init the super class
-	ConfigSet::getSingleton().setWindowFullscreen(true);
+	g_windowFullscreenCVar.set(1);
 
 #if !ANKI_OS_ANDROID
 	CString mainDataPath = ANKI_SOURCE_DIRECTORY;
@@ -26,12 +26,11 @@ Error SampleApp::init(int argc, char** argv, CString sampleName)
 	}
 	else
 	{
-		ConfigSet::getSingleton().setRsrcDataPaths(
-			BaseString<MemoryPoolPtrWrapper<HeapMemoryPool>>(&tmpPool).sprintf("%s:%s", mainDataPath.cstr(), assetsDataPath.cstr()));
+		g_dataPathsCVar.set(BaseString<MemoryPoolPtrWrapper<HeapMemoryPool>>(&tmpPool).sprintf("%s:%s", mainDataPath.cstr(), assetsDataPath.cstr()));
 	}
 #endif
 
-	ANKI_CHECK(ConfigSet::getSingleton().setFromCommandLineArguments(argc - 1, argv + 1));
+	ANKI_CHECK(CVarSet::getSingleton().setFromCommandLineArguments(argc - 1, argv + 1));
 	ANKI_CHECK(App::init());
 
 	ANKI_CHECK(sampleExtraInit());
@@ -133,7 +132,7 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::kJ) == 1)
 	{
-		ConfigSet::getSingleton().setRVrs(!ConfigSet::getSingleton().getRVrs());
+		g_vrsCVar.set(!g_vrsCVar.get());
 	}
 
 	static Vec2 mousePosOn1stClick = in.getMousePosition();
@@ -149,17 +148,17 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 		mode = (mode + 1) % 3;
 		if(mode == 0)
 		{
-			ConfigSet::getSingleton().setRDbg(false);
+			g_dbgCVar.set(false);
 		}
 		else if(mode == 1)
 		{
-			ConfigSet::getSingleton().setRDbg(true);
+			g_dbgCVar.set(true);
 			renderer.getDbg().setDepthTestEnabled(true);
 			renderer.getDbg().setDitheredDepthTestEnabled(false);
 		}
 		else
 		{
-			ConfigSet::getSingleton().setRDbg(true);
+			g_dbgCVar.set(true);
 			renderer.getDbg().setDepthTestEnabled(false);
 			renderer.getDbg().setDitheredDepthTestEnabled(true);
 		}

+ 4 - 4
Samples/PhysicsPlayground/Main.cpp

@@ -242,7 +242,7 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 
 	if(Input::getSingleton().getKey(KeyCode::kJ) == 1)
 	{
-		ConfigSet::getSingleton().setRVrs(!ConfigSet::getSingleton().getRVrs());
+		g_vrsCVar.set(!g_vrsCVar.get());
 	}
 
 	if(Input::getSingleton().getKey(KeyCode::kF1) == 1)
@@ -251,17 +251,17 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 		mode = (mode + 1) % 3;
 		if(mode == 0)
 		{
-			ConfigSet::getSingleton().setRDbg(false);
+			g_dbgCVar.set(false);
 		}
 		else if(mode == 1)
 		{
-			ConfigSet::getSingleton().setRDbg(true);
+			g_dbgCVar.set(true);
 			MainRenderer::getSingleton().getDbg().setDepthTestEnabled(true);
 			MainRenderer::getSingleton().getDbg().setDitheredDepthTestEnabled(false);
 		}
 		else
 		{
-			ConfigSet::getSingleton().setRDbg(true);
+			g_dbgCVar.set(true);
 			MainRenderer::getSingleton().getDbg().setDepthTestEnabled(false);
 			MainRenderer::getSingleton().getDbg().setDitheredDepthTestEnabled(true);
 		}

+ 1 - 1
Samples/SkeletalAnimation/Main.cpp

@@ -30,7 +30,7 @@ public:
 		animInfo.m_repeatTimes = -1.0;
 		SceneGraph::getSingleton().findSceneNode("droid.001").getFirstComponentOfType<SkinComponent>().playAnimation(0, m_floatAnim, animInfo);
 
-		ConfigSet::getSingleton().setRBloomThreshold(5.0f);
+		g_bloomThresholdCVar.set(5.0f);
 		return Error::kNone;
 	}
 

+ 10 - 10
Sandbox/Main.cpp

@@ -36,9 +36,9 @@ Error MyApp::init(int argc, char* argv[])
 
 	// Config
 #if ANKI_OS_ANDROID
-	ANKI_CHECK(ConfigSet::getSingleton().setFromCommandLineArguments(argc - 1, argv + 1));
+	ANKI_CHECK(CVarSet::getSingleton().setFromCommandLineArguments(argc - 1, argv + 1));
 #else
-	ANKI_CHECK(ConfigSet::getSingleton().setFromCommandLineArguments(argc - 2, argv + 2));
+	ANKI_CHECK(CVarSet::getSingleton().setFromCommandLineArguments(argc - 2, argv + 2));
 #endif
 
 	// Init super class
@@ -50,7 +50,7 @@ Error MyApp::init(int argc, char* argv[])
 	if(getenv("PROFILE"))
 	{
 		m_profile = true;
-		ConfigSet::getSingleton().setCoreTargetFps(240);
+		g_targetFpsCVar.set(240);
 		Tracer::getSingleton().setEnabled(true);
 	}
 
@@ -122,17 +122,17 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 		mode = (mode + 1) % 3;
 		if(mode == 0)
 		{
-			ConfigSet::getSingleton().setRDbg(false);
+			g_dbgCVar.set(false);
 		}
 		else if(mode == 1)
 		{
-			ConfigSet::getSingleton().setRDbg(true);
+			g_dbgCVar.set(true);
 			renderer.getDbg().setDepthTestEnabled(true);
 			renderer.getDbg().setDitheredDepthTestEnabled(false);
 		}
 		else
 		{
-			ConfigSet::getSingleton().setRDbg(true);
+			g_dbgCVar.set(true);
 			renderer.getDbg().setDepthTestEnabled(false);
 			renderer.getDbg().setDitheredDepthTestEnabled(true);
 		}
@@ -190,17 +190,17 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 			mode = (mode + 1) % 3;
 			if(mode == 0)
 			{
-				ConfigSet::getSingleton().setRDbg(false);
+				g_dbgCVar.set(false);
 			}
 			else if(mode == 1)
 			{
-				ConfigSet::getSingleton().setRDbg(true);
+				g_dbgCVar.set(true);
 				renderer.getDbg().setDepthTestEnabled(true);
 				renderer.getDbg().setDitheredDepthTestEnabled(false);
 			}
 			else
 			{
-				ConfigSet::getSingleton().setRDbg(true);
+				g_dbgCVar.set(true);
 				renderer.getDbg().setDepthTestEnabled(false);
 				renderer.getDbg().setDitheredDepthTestEnabled(true);
 			}
@@ -399,7 +399,7 @@ Error MyApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 	if(in.getKey(KeyCode::kJ) == 1)
 	{
-		ConfigSet::getSingleton().setRVrs(!ConfigSet::getSingleton().getRVrs());
+		g_vrsCVar.set(!g_vrsCVar.get());
 	}
 
 	if(in.getEvent(InputEvent::kWindowClosed))

+ 3 - 5
Tools/Image/ImageViewerMain.cpp

@@ -273,11 +273,9 @@ public:
 			return Error::kUserData;
 		}
 
-		ConfigSet::getSingleton().setWindowFullscreen(false);
-		ConfigSet::getSingleton().setRsrcDataPaths(ANKI_SOURCE_DIRECTORY);
-		ConfigSet::getSingleton().setGrValidation(false);
-		ConfigSet::getSingleton().setGrDebugMarkers(false);
-		ANKI_CHECK(ConfigSet::getSingleton().setFromCommandLineArguments(argc - 2, argv + 2));
+		g_windowFullscreenCVar.set(0);
+		g_dataPathsCVar.set(ANKI_SOURCE_DIRECTORY);
+		ANKI_CHECK(CVarSet::getSingleton().setFromCommandLineArguments(argc - 2, argv + 2));
 
 		ANKI_CHECK(App::init());