Browse Source

Bloom and CVars refactoring

Panagiotis Christopoulos Charitos 1 year ago
parent
commit
e50f7362e0
100 changed files with 1069 additions and 1341 deletions
  1. 1 1
      AnKi/Core.h
  2. 25 43
      AnKi/Core/App.cpp
  3. 23 11
      AnKi/Core/App.h
  4. 0 2
      AnKi/Core/CMakeLists.txt
  5. 0 5
      AnKi/Core/CoreTracer.cpp
  6. 3 3
      AnKi/Core/CoreTracer.h
  7. 4 9
      AnKi/Core/GpuMemory/GpuSceneBuffer.cpp
  8. 4 1
      AnKi/Core/GpuMemory/GpuSceneBuffer.h
  9. 2 7
      AnKi/Core/GpuMemory/RebarTransientMemoryPool.cpp
  10. 4 1
      AnKi/Core/GpuMemory/RebarTransientMemoryPool.h
  11. 4 9
      AnKi/Core/GpuMemory/UnifiedGeometryBuffer.cpp
  12. 5 1
      AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h
  13. 5 0
      AnKi/Core/StatsSet.cpp
  14. 0 12
      AnKi/Gr/BackendCommon/Common.cpp
  15. 0 3
      AnKi/Gr/BackendCommon/Common.h
  16. 0 1
      AnKi/Gr/CMakeLists.txt
  17. 31 0
      AnKi/Gr/Common.h
  18. 1 1
      AnKi/Gr/D3D/D3DCommandBuffer.cpp
  19. 9 20
      AnKi/Gr/D3D/D3DDescriptor.cpp
  20. 12 23
      AnKi/Gr/D3D/D3DGrManager.cpp
  21. 2 2
      AnKi/Gr/D3D/D3DSwapchainFactory.cpp
  22. 1 5
      AnKi/Gr/GrManager.h
  23. 1 1
      AnKi/Gr/Vulkan/VkDescriptor.cpp
  24. 24 41
      AnKi/Gr/Vulkan/VkGrManager.cpp
  25. 1 4
      AnKi/Gr/Vulkan/VkGraphicsState.cpp
  26. 0 7
      AnKi/Math/Functions.h
  27. 1 2
      AnKi/Renderer.h
  28. 2 6
      AnKi/Renderer/AccelerationStructureBuilder.cpp
  29. 4 0
      AnKi/Renderer/AccelerationStructureBuilder.h
  30. 0 197
      AnKi/Renderer/Bloom.cpp
  31. 0 84
      AnKi/Renderer/Bloom.h
  32. 270 0
      AnKi/Renderer/Bloom2.cpp
  33. 72 0
      AnKi/Renderer/Bloom2.h
  34. 1 1
      AnKi/Renderer/Common.h
  35. 3 6
      AnKi/Renderer/Dbg.cpp
  36. 3 3
      AnKi/Renderer/Dbg.h
  37. 3 3
      AnKi/Renderer/DepthDownscale.cpp
  38. 0 152
      AnKi/Renderer/DownscaleBlur.cpp
  39. 0 71
      AnKi/Renderer/DownscaleBlur.h
  40. 9 13
      AnKi/Renderer/FinalComposite.cpp
  41. 3 0
      AnKi/Renderer/FinalComposite.h
  42. 2 2
      AnKi/Renderer/ForwardShading.cpp
  43. 6 12
      AnKi/Renderer/GBuffer.cpp
  44. 6 0
      AnKi/Renderer/GBuffer.h
  45. 5 10
      AnKi/Renderer/IndirectDiffuseProbes.cpp
  46. 5 0
      AnKi/Renderer/IndirectDiffuseProbes.h
  47. 2 6
      AnKi/Renderer/LensFlare.cpp
  48. 3 0
      AnKi/Renderer/LensFlare.h
  49. 3 3
      AnKi/Renderer/LightShading.cpp
  50. 4 4
      AnKi/Renderer/MotionVectors.cpp
  51. 7 11
      AnKi/Renderer/ProbeReflections.cpp
  52. 5 0
      AnKi/Renderer/ProbeReflections.h
  53. 16 47
      AnKi/Renderer/Renderer.cpp
  54. 26 15
      AnKi/Renderer/Renderer.h
  55. 1 1
      AnKi/Renderer/RendererObject.cpp
  56. 3 4
      AnKi/Renderer/RendererObject.def.h
  57. 5 10
      AnKi/Renderer/RtShadows.cpp
  58. 4 0
      AnKi/Renderer/RtShadows.h
  59. 9 14
      AnKi/Renderer/Scale.cpp
  60. 4 0
      AnKi/Renderer/Scale.h
  61. 15 22
      AnKi/Renderer/ShadowMapping.cpp
  62. 7 2
      AnKi/Renderer/ShadowMapping.h
  63. 7 9
      AnKi/Renderer/ShadowmapsResolve.cpp
  64. 2 0
      AnKi/Renderer/ShadowmapsResolve.h
  65. 17 24
      AnKi/Renderer/Ssao.cpp
  66. 6 0
      AnKi/Renderer/Ssao.h
  67. 11 17
      AnKi/Renderer/Ssr.cpp
  68. 6 0
      AnKi/Renderer/Ssr.h
  69. 4 4
      AnKi/Renderer/TemporalAA.cpp
  70. 6 7
      AnKi/Renderer/Tonemapping.cpp
  71. 3 2
      AnKi/Renderer/Utils/GpuVisibility.cpp
  72. 4 4
      AnKi/Renderer/VolumetricFog.cpp
  73. 5 12
      AnKi/Renderer/VolumetricLightingAccumulation.cpp
  74. 7 5
      AnKi/Renderer/VolumetricLightingAccumulation.h
  75. 5 8
      AnKi/Renderer/VrsSriGeneration.cpp
  76. 2 0
      AnKi/Renderer/VrsSriGeneration.h
  77. 2 4
      AnKi/Resource/ImageResource.cpp
  78. 2 0
      AnKi/Resource/ImageResource.h
  79. 1 1
      AnKi/Resource/MaterialResource.cpp
  80. 2 4
      AnKi/Resource/MeshResource.cpp
  81. 2 4
      AnKi/Resource/ModelResource.cpp
  82. 3 3
      AnKi/Resource/ResourceFilesystem.cpp
  83. 1 1
      AnKi/Resource/ResourceFilesystem.h
  84. 2 5
      AnKi/Resource/ResourceManager.cpp
  85. 3 0
      AnKi/Resource/ResourceManager.h
  86. 1 1
      AnKi/Resource/ShaderProgramResource.cpp
  87. 1 1
      AnKi/Resource/ShaderProgramResourceSystem.cpp
  88. 0 1
      AnKi/Scene/Components/CameraComponent.h
  89. 3 3
      AnKi/Scene/Components/GlobalIlluminationProbeComponent.cpp
  90. 1 1
      AnKi/Scene/Components/ModelComponent.cpp
  91. 4 7
      AnKi/Scene/Components/ReflectionProbeComponent.cpp
  92. 3 2
      AnKi/Scene/Components/ReflectionProbeComponent.h
  93. 1 1
      AnKi/Scene/DeveloperConsoleUiNode.cpp
  94. 4 31
      AnKi/Scene/SceneGraph.cpp
  95. 26 6
      AnKi/Scene/SceneGraph.h
  96. 1 0
      AnKi/Scene/StatsUiNode.cpp
  97. 0 71
      AnKi/Shaders/Bloom.ankiprog
  98. 250 0
      AnKi/Shaders/Bloom2.ankiprog
  99. 0 125
      AnKi/Shaders/BloomUpscale.ankiprog
  100. 0 63
      AnKi/Shaders/DownscaleBlur.ankiprog

+ 1 - 1
AnKi/Core.h

@@ -6,5 +6,5 @@
 #pragma once
 
 #include <AnKi/Core/App.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Core/CoreTracer.h>

+ 25 - 43
AnKi/Core/App.cpp

@@ -5,7 +5,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Core/App.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/File.h>
@@ -44,32 +44,14 @@ namespace anki {
 android_app* g_androidApp = nullptr;
 #endif
 
-StatCounter g_cpuTotalTimeStatVar(StatCategory::kTime, "CPU total", StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
-static StatCounter g_cpuAllocatedMemStatVar(StatCategory::kCpuMem, "Total", StatFlag::kBytes);
-static StatCounter g_cpuAllocationCountStatVar(StatCategory::kCpuMem, "Allocations/frame", StatFlag::kBytes | StatFlag::kZeroEveryFrame);
-static StatCounter g_cpuFreesCountStatVar(StatCategory::kCpuMem, "Frees/frame", StatFlag::kBytes | StatFlag::kZeroEveryFrame);
-
-NumericCVar<U32> g_windowWidthCVar(CVarSubsystem::kCore, "Width", 1920, 16, 16 * 1024, "Width");
-NumericCVar<U32> g_windowHeightCVar(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");
-BoolCVar g_meshletRenderingCVar(CVarSubsystem::kCore, "MeshletRendering", false, "Do meshlet culling and rendering");
+StatCounter g_cpuAllocatedMemStatVar(StatCategory::kCpuMem, "Total", StatFlag::kBytes);
+StatCounter g_cpuAllocationCountStatVar(StatCategory::kCpuMem, "Allocations/frame", StatFlag::kBytes | StatFlag::kZeroEveryFrame);
+StatCounter g_cpuFreesCountStatVar(StatCategory::kCpuMem, "Frees/frame", StatFlag::kBytes | StatFlag::kZeroEveryFrame);
 
 #if ANKI_PLATFORM_MOBILE
-static StatCounter g_maliGpuActiveStatVar(StatCategory::kGpuMisc, "Mali active cycles", StatFlag::kMainThreadUpdates);
-static StatCounter g_maliGpuReadBandwidthStatVar(StatCategory::kGpuMisc, "Mali read bandwidth", StatFlag::kMainThreadUpdates);
-static StatCounter g_maliGpuWriteBandwidthStatVar(StatCategory::kGpuMisc, "Mali write bandwidth", StatFlag::kMainThreadUpdates);
-
-static BoolCVar g_maliHwCountersCVar(CVarSubsystem::kCore, "MaliHwCounters", false, "Enable Mali counters");
+inline StatCounter g_maliGpuActiveStatVar(StatCategory::kGpuMisc, "Mali active cycles", StatFlag::kMainThreadUpdates);
+inline StatCounter g_maliGpuReadBandwidthStatVar(StatCategory::kGpuMisc, "Mali read bandwidth", StatFlag::kMainThreadUpdates);
+inline StatCounter g_maliGpuWriteBandwidthStatVar(StatCategory::kGpuMisc, "Mali write bandwidth", StatFlag::kMainThreadUpdates);
 #endif
 
 void* App::statsAllocCallback(void* userData, void* ptr, PtrSize size, [[maybe_unused]] PtrSize alignment)
@@ -189,7 +171,7 @@ Error App::init()
 Error App::initInternal()
 {
 	StatsSet::getSingleton().initFromMainThread();
-	Logger::getSingleton().enableVerbosity(g_verboseLogCVar.get());
+	Logger::getSingleton().enableVerbosity(g_verboseLogCVar);
 
 	AllocAlignedCallback allocCb = m_originalAllocCallback;
 	void* allocCbUserData = m_originalAllocUserData;
@@ -237,9 +219,9 @@ Error App::initInternal()
 	}
 #endif
 
-	ANKI_CORE_LOGI("Number of job threads: %u", g_jobThreadCountCVar.get());
+	ANKI_CORE_LOGI("Number of job threads: %u", U32(g_jobThreadCountCVar));
 
-	if(g_benchmarkModeCVar.get() && g_vsyncCVar.get())
+	if(g_benchmarkModeCVar && g_vsyncCVar)
 	{
 		ANKI_CORE_LOGW("Vsync is enabled and benchmark mode as well. Will turn vsync off");
 		g_vsyncCVar.set(false);
@@ -258,13 +240,13 @@ Error App::initInternal()
 	// Window
 	//
 	NativeWindowInitInfo nwinit;
-	nwinit.m_width = g_windowWidthCVar.get();
-	nwinit.m_height = g_windowHeightCVar.get();
+	nwinit.m_width = g_windowWidthCVar;
+	nwinit.m_height = g_windowHeightCVar;
 	nwinit.m_depthBits = 0;
 	nwinit.m_stencilBits = 0;
-	nwinit.m_fullscreenDesktopRez = g_windowFullscreenCVar.get() > 0;
-	nwinit.m_exclusiveFullscreen = g_windowFullscreenCVar.get() == 2;
-	nwinit.m_targetFps = g_targetFpsCVar.get();
+	nwinit.m_fullscreenDesktopRez = g_windowFullscreenCVar > 0;
+	nwinit.m_exclusiveFullscreen = g_windowFullscreenCVar == 2;
+	nwinit.m_targetFps = g_targetFpsCVar;
 	NativeWindow::allocateSingleton();
 	ANKI_CHECK(NativeWindow::getSingleton().init(nwinit));
 
@@ -278,7 +260,7 @@ Error App::initInternal()
 	// ThreadPool
 	//
 	const Bool pinThreads = !ANKI_OS_ANDROID;
-	CoreThreadJobManager::allocateSingleton(g_jobThreadCountCVar.get(), pinThreads);
+	CoreThreadJobManager::allocateSingleton(U32(g_jobThreadCountCVar), pinThreads);
 
 	//
 	// Graphics API
@@ -293,7 +275,7 @@ Error App::initInternal()
 	// Mali HW counters
 	//
 #if ANKI_PLATFORM_MOBILE
-	if(ANKI_STATS_ENABLED && GrManager::getSingleton().getDeviceCapabilities().m_gpuVendor == GpuVendor::kArm && g_maliHwCountersCVar.get())
+	if(ANKI_STATS_ENABLED && GrManager::getSingleton().getDeviceCapabilities().m_gpuVendor == GpuVendor::kArm && g_maliHwCountersCVar)
 	{
 		MaliHwCounters::allocateSingleton();
 	}
@@ -327,7 +309,7 @@ Error App::initInternal()
 	extraPaths += "|ankiprogbin"; // Shaders
 	extraPaths += ":" ANKI_SOURCE_DIRECTORY "|EngineAssets,!AndroidProject"; // EngineAssets
 	extraPaths += ":";
-	extraPaths += g_dataPathsCVar.get();
+	extraPaths += g_dataPathsCVar;
 	g_dataPathsCVar.set(extraPaths);
 #endif
 
@@ -393,7 +375,7 @@ Error App::initDirs()
 	m_cacheDir.sprintf("%s/cache", &m_settingsDir[0]);
 
 	const Bool cacheDirExists = directoryExists(m_cacheDir.toCString());
-	if(g_clearCachesCVar.get() && cacheDirExists)
+	if(g_clearCachesCVar && cacheDirExists)
 	{
 		ANKI_CORE_LOGI("Will delete the cache dir and start fresh: %s", m_cacheDir.cstr());
 		ANKI_CHECK(removeDirectory(m_cacheDir.toCString()));
@@ -417,7 +399,7 @@ Error App::mainLoop()
 	Second crntTime = prevUpdateTime;
 
 	// Benchmark mode stuff:
-	const Bool benchmarkMode = g_benchmarkModeCVar.get();
+	const Bool benchmarkMode = g_benchmarkModeCVar;
 	Second aggregatedCpuTime = 0.0;
 	Second aggregatedGpuTime = 0.0;
 	constexpr U32 kBenchmarkFramesToGatherBeforeFlush = 60;
@@ -454,14 +436,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 || g_displayStatsCVar.get() > 0) [[unlikely]]
+			if(benchmarkMode || g_displayStatsCVar > 0) [[unlikely]]
 			{
 				grTime = HighRezTimer::getCurrentTime();
 			}
 
 			GrManager::getSingleton().swapBuffers();
 
-			if(benchmarkMode || g_displayStatsCVar.get() > 0) [[unlikely]]
+			if(benchmarkMode || g_displayStatsCVar > 0) [[unlikely]]
 			{
 				grTime = HighRezTimer::getCurrentTime() - grTime;
 			}
@@ -478,7 +460,7 @@ Error App::mainLoop()
 			g_cpuTotalTimeStatVar.set((frameTime - grTime) * 1000.0);
 			if(!benchmarkMode) [[likely]]
 			{
-				const Second timerTick = 1.0_sec / Second(g_targetFpsCVar.get());
+				const Second timerTick = 1.0_sec / Second(g_targetFpsCVar);
 				if(frameTime < timerTick)
 				{
 					ANKI_TRACE_SCOPED_EVENT(TimerTickSleep);
@@ -521,7 +503,7 @@ Error App::mainLoop()
 
 			if(benchmarkMode) [[unlikely]]
 			{
-				if(GlobalFrameIndex::getSingleton().m_value >= g_benchmarkModeFrameCountCVar.get())
+				if(GlobalFrameIndex::getSingleton().m_value >= g_benchmarkModeFrameCountCVar)
 				{
 					quit = true;
 				}
@@ -544,7 +526,7 @@ Error App::mainLoop()
 
 void App::initMemoryCallbacks(AllocAlignedCallback& allocCb, void*& allocCbUserData)
 {
-	if(ANKI_STATS_ENABLED && g_displayStatsCVar.get() > 1)
+	if(ANKI_STATS_ENABLED && g_displayStatsCVar > 1)
 	{
 		allocCb = statsAllocCallback;
 		allocCbUserData = this;

+ 23 - 11
AnKi/Core/App.h

@@ -5,23 +5,35 @@
 
 #pragma once
 
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
+#include <AnKi/Core/StatsSet.h>
 #include <AnKi/Util/String.h>
 #include <AnKi/Util/Ptr.h>
+#include <AnKi/Util/System.h>
+#include <AnKi/Util/Functions.h>
 #include <AnKi/Ui/UiImmediateModeBuilder.h>
 
 namespace anki {
 
-// Forward
-class StatCounter;
-extern NumericCVar<U32> g_windowWidthCVar;
-extern NumericCVar<U32> g_windowHeightCVar;
-extern NumericCVar<U32> g_windowFullscreenCVar;
-extern NumericCVar<U32> g_targetFpsCVar;
-extern NumericCVar<U32> g_displayStatsCVar;
-extern BoolCVar g_meshletRenderingCVar;
-extern StatCounter g_cpuTotalTimeStatVar;
-extern StatCounter g_rendererGpuTimeStatVar;
+inline NumericCVar<U32> g_windowWidthCVar("Core", "Width", 1920, 16, 16 * 1024, "Width");
+inline NumericCVar<U32> g_windowHeightCVar("Core", "Height", 1080, 16, 16 * 1024, "Height");
+inline NumericCVar<U32> g_windowFullscreenCVar("Core", "WindowFullscreen", 1, 0, 2, "0: windowed, 1: borderless fullscreen, 2: exclusive fullscreen");
+inline NumericCVar<U32> g_targetFpsCVar("Core", "TargetFps", 60u, 1u, kMaxU32, "Target FPS");
+inline NumericCVar<U32> g_jobThreadCountCVar("Core", "JobThreadCount", clamp(getCpuCoresCount() / 2u, 2u, 16u), 2u, 1024u, "Number of job thread");
+inline NumericCVar<U32> g_displayStatsCVar("Core", "DisplayStats", 0, 0, 2, "Display stats, 0: None, 1: Simple, 2: Detailed");
+inline BoolCVar g_clearCachesCVar("Core", "ClearCaches", false, "Clear all caches");
+inline BoolCVar g_verboseLogCVar("Core", "VerboseLog", false, "Verbose logging");
+inline BoolCVar g_benchmarkModeCVar("Core", "BenchmarkMode", false, "Run in a benchmark mode. Fixed timestep, unlimited target FPS");
+inline NumericCVar<U32> g_benchmarkModeFrameCountCVar("Core", "BenchmarkModeFrameCount", 60 * 60 * 2, 1, kMaxU32,
+													  "How many frames the benchmark will run before it quits");
+inline BoolCVar g_meshletRenderingCVar("Core", "MeshletRendering", false, "Do meshlet culling and rendering");
+
+#if ANKI_PLATFORM_MOBILE
+inline BoolCVar g_maliHwCountersCVar("Core", "MaliHwCounters", false, "Enable Mali counters");
+#endif
+
+inline StatCounter g_cpuTotalTimeStatVar(StatCategory::kTime, "CPU total",
+										 StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
 
 /// The core class of the engine.
 class App

+ 0 - 2
AnKi/Core/CMakeLists.txt

@@ -1,6 +1,5 @@
 set(sources
 	App.cpp
-	CVarSet.cpp
 	CoreTracer.cpp
 	MaliHwCounters.cpp
 	StatsSet.cpp
@@ -13,7 +12,6 @@ set(sources
 set(headers
 	App.h
 	Common.h
-	CVarSet.h
 	CoreTracer.h
 	MaliHwCounters.h
 	StatsSet.h

+ 0 - 5
AnKi/Core/CoreTracer.cpp

@@ -11,11 +11,6 @@
 
 namespace anki {
 
-BoolCVar g_tracingEnabledCVar(CVarSubsystem::kCore, "Tracing", false, "Enable or disable tracing");
-#if ANKI_OS_ANDROID
-BoolCVar g_streamlineEnabledCVar(CVarSubsystem::kCore, "StreamlineAnnotations", false, "Enable or disable Streamline annotations");
-#endif
-
 #if ANKI_TRACING_ENABLED
 
 static void getSpreadsheetColumnName(U32 column, Array<char, 3>& arr)

+ 3 - 3
AnKi/Core/CoreTracer.h

@@ -9,16 +9,16 @@
 #include <AnKi/Util/Thread.h>
 #include <AnKi/Util/List.h>
 #include <AnKi/Util/File.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 namespace anki {
 
 /// @addtogroup core
 /// @{
 
-extern BoolCVar g_tracingEnabledCVar;
+inline BoolCVar g_tracingEnabledCVar("Core", "Tracing", false, "Enable or disable tracing");
 #if ANKI_OS_ANDROID
-extern BoolCVar g_streamlineEnabledCVar;
+inline BoolCVar g_streamlineEnabledCVar("Core", "StreamlineAnnotations", false, "Enable or disable Streamline annotations");
 #endif
 
 #if ANKI_TRACING_ENABLED

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

@@ -5,26 +5,21 @@
 
 #include <AnKi/Core/GpuMemory/GpuSceneBuffer.h>
 #include <AnKi/Core/GpuMemory/RebarTransientMemoryPool.h>
-#include <AnKi/Core/CVarSet.h>
-#include <AnKi/Core/StatsSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Gr/CommandBuffer.h>
 
 namespace anki {
 
-static StatCounter g_gpuSceneBufferAllocatedSizeStatVar(StatCategory::kGpuMem, "GPU scene allocated",
+inline StatCounter g_gpuSceneBufferAllocatedSizeStatVar(StatCategory::kGpuMem, "GPU scene allocated",
 														StatFlag::kBytes | StatFlag::kMainThreadUpdates);
-static StatCounter g_gpuSceneBufferTotalStatVar(StatCategory::kGpuMem, "GPU scene total", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
-static StatCounter g_gpuSceneBufferFragmentationStatVar(StatCategory::kGpuMem, "GPU scene fragmentation",
+inline StatCounter g_gpuSceneBufferTotalStatVar(StatCategory::kGpuMem, "GPU scene total", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
+inline StatCounter g_gpuSceneBufferFragmentationStatVar(StatCategory::kGpuMem, "GPU scene fragmentation",
 														StatFlag::kFloat | StatFlag::kMainThreadUpdates);
 
-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 = g_gpuSceneInitialSizeCVar.get();
+	const PtrSize poolSize = g_gpuSceneInitialSizeCVar;
 
 	const Array classes = {32_B, 64_B, 128_B, 256_B, poolSize};
 

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

@@ -5,7 +5,8 @@
 
 #pragma once
 
-#include <AnKi/Core/Common.h>
+#include <AnKi/Util/CVarSet.h>
+#include <AnKi/Core/StatsSet.h>
 #include <AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.h>
 #include <AnKi/Resource/ShaderProgramResource.h>
 #include <AnKi/Gr/GrManager.h>
@@ -15,6 +16,8 @@ namespace anki {
 /// @addtogroup core
 /// @{
 
+inline NumericCVar<PtrSize> g_gpuSceneInitialSizeCVar("Core", "GpuSceneInitialSize", 64_MB, 16_MB, 2_GB, "Global memory for the GPU scene");
+
 /// @memberof GpuSceneBuffer
 class GpuSceneBufferAllocation
 {

+ 2 - 7
AnKi/Core/GpuMemory/RebarTransientMemoryPool.cpp

@@ -4,18 +4,13 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Core/GpuMemory/RebarTransientMemoryPool.h>
-#include <AnKi/Core/CVarSet.h>
-#include <AnKi/Core/StatsSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Gr/GrManager.h>
 #include <AnKi/Gr/Buffer.h>
 
 namespace anki {
 
-static StatCounter g_rebarUserMemoryStatVar(StatCategory::kGpuMem, "ReBAR used mem", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
-
-static NumericCVar<PtrSize> g_rebarGpuMemorySizeCvar(CVarSubsystem::kCore, "RebarGpuMemorySize", 24_MB, 1_MB, 1_GB,
-													 "ReBAR: always mapped GPU memory");
+inline StatCounter g_rebarUserMemoryStatVar(StatCategory::kGpuMem, "ReBAR used mem", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
 
 RebarTransientMemoryPool::~RebarTransientMemoryPool()
 {
@@ -29,7 +24,7 @@ void RebarTransientMemoryPool::init()
 {
 	BufferInitInfo buffInit("ReBar");
 	buffInit.m_mapAccess = BufferMapAccessBit::kWrite;
-	buffInit.m_size = g_rebarGpuMemorySizeCvar.get();
+	buffInit.m_size = g_rebarGpuMemorySizeCvar;
 	buffInit.m_usage = BufferUsageBit::kAllConstant | BufferUsageBit::kAllUav | BufferUsageBit::kAllSrv | BufferUsageBit::kVertex
 					   | BufferUsageBit::kIndex | BufferUsageBit::kShaderBindingTable | BufferUsageBit::kAllIndirect | BufferUsageBit::kCopySource;
 	m_buffer = GrManager::getSingleton().newBuffer(buffInit);

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

@@ -5,7 +5,8 @@
 
 #pragma once
 
-#include <AnKi/Core/Common.h>
+#include <AnKi/Util/CVarSet.h>
+#include <AnKi/Core/StatsSet.h>
 #include <AnKi/Gr/Buffer.h>
 #include <AnKi/Gr/GrManager.h>
 
@@ -14,6 +15,8 @@ namespace anki {
 /// @addtogroup core
 /// @{
 
+inline NumericCVar<PtrSize> g_rebarGpuMemorySizeCvar("Core", "RebarGpuMemorySize", 24_MB, 1_MB, 1_GB, "ReBAR: always mapped GPU memory");
+
 /// Manages staging GPU memory.
 class RebarTransientMemoryPool : public MakeSingleton<RebarTransientMemoryPool>
 {

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

@@ -4,23 +4,18 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
-#include <AnKi/Core/CVarSet.h>
-#include <AnKi/Core/StatsSet.h>
 #include <AnKi/Gr/GrManager.h>
 
 namespace anki {
 
-static StatCounter g_unifiedGeomBufferAllocatedSizeStatVar(StatCategory::kGpuMem, "UGB allocated", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
-static StatCounter g_unifiedGeomBufferTotalStatVar(StatCategory::kGpuMem, "UGB total", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
-static StatCounter g_unifiedGeomBufferFragmentationStatVar(StatCategory::kGpuMem, "UGB fragmentation",
+inline StatCounter g_unifiedGeomBufferAllocatedSizeStatVar(StatCategory::kGpuMem, "UGB allocated", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
+inline StatCounter g_unifiedGeomBufferTotalStatVar(StatCategory::kGpuMem, "UGB total", StatFlag::kBytes | StatFlag::kMainThreadUpdates);
+inline StatCounter g_unifiedGeomBufferFragmentationStatVar(StatCategory::kGpuMem, "UGB fragmentation",
 														   StatFlag::kFloat | StatFlag::kMainThreadUpdates);
 
-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 = g_unifiedGometryBufferSizeCvar.get();
+	const PtrSize poolSize = g_unifiedGometryBufferSizeCvar;
 
 	const Array classes = {1_KB, 8_KB, 32_KB, 128_KB, 512_KB, 4_MB, 8_MB, 16_MB, poolSize};
 

+ 5 - 1
AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h

@@ -5,7 +5,8 @@
 
 #pragma once
 
-#include <AnKi/Core/Common.h>
+#include <AnKi/Util/CVarSet.h>
+#include <AnKi/Core/StatsSet.h>
 #include <AnKi/Gr/Utils/SegregatedListsGpuMemoryPool.h>
 
 namespace anki {
@@ -13,6 +14,9 @@ namespace anki {
 /// @addtogroup core
 /// @{
 
+inline NumericCVar<PtrSize> g_unifiedGometryBufferSizeCvar("Core", "UnifiedGeometryBufferSize", 128_MB, 16_MB, 2_GB,
+														   "Global index and vertex buffer size");
+
 /// @memberof UnifiedGeometryBuffer
 class UnifiedGeometryBufferAllocation
 {

+ 5 - 0
AnKi/Core/StatsSet.cpp

@@ -79,6 +79,11 @@ void StatsSet::registerCounter(StatCounter* counter)
 {
 	ANKI_ASSERT(counter);
 
+	for(U32 i = 0; i < m_statCounterArrSize; ++i)
+	{
+		ANKI_ASSERT(m_statCounterArr[i]->m_name != counter->m_name);
+	}
+
 	// Try grow the array
 	if(m_statCounterArrSize + 1 > m_statCounterArrStorageSize)
 	{

+ 0 - 12
AnKi/Gr/BackendCommon/Common.cpp

@@ -1,12 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Gr/BackendCommon/Common.h>
-
-namespace anki {
-
-NumericCVar<U32> g_maxBindlessSampledTextureCountCVar(CVarSubsystem::kGr, "MaxBindlessSampledTextureCountCVar", 512, 16, kMaxU16);
-
-} // end namespace anki

+ 0 - 3
AnKi/Gr/BackendCommon/Common.h

@@ -6,7 +6,6 @@
 #pragma once
 
 #include <AnKi/Gr/Common.h>
-#include <AnKi/Core/CVarSet.h>
 
 namespace anki {
 
@@ -15,6 +14,4 @@ constexpr Second kMaxFenceOrSemaphoreWaitTime = 120.0;
 
 constexpr U32 kMaxQueriesPerQueryChunk = 64;
 
-extern NumericCVar<U32> g_maxBindlessSampledTextureCountCVar;
-
 } // end namespace anki

+ 0 - 1
AnKi/Gr/CMakeLists.txt

@@ -7,7 +7,6 @@ set(backend_sources
 	ShaderProgram.cpp
 	Utils/StackGpuMemoryPool.cpp
 	BackendCommon/Functions.cpp
-	BackendCommon/Common.cpp
 	BackendCommon/GraphicsStateTracker.cpp
 	Utils/SegregatedListsGpuMemoryPool.cpp)
 

+ 31 - 0
AnKi/Gr/Common.h

@@ -10,6 +10,7 @@
 #include <AnKi/Util/String.h>
 #include <AnKi/Util/Enum.h>
 #include <AnKi/Shaders/Include/Common.h>
+#include <AnKi/Util/CVarSet.h>
 
 namespace anki {
 
@@ -34,6 +35,36 @@ class PipelineQueryInitInfo;
 /// @addtogroup graphics
 /// @{
 
+inline BoolCVar g_validationCVar("Gr", "Validation", false, "Enable or not validation");
+inline BoolCVar g_gpuValidationCVar("Gr", "GpuValidation", false, "Enable or not GPU validation");
+inline BoolCVar g_vsyncCVar("Gr", "Vsync", false, "Enable or not vsync");
+inline BoolCVar g_debugMarkersCVar("Gr", "DebugMarkers", false, "Enable or not debug markers");
+inline BoolCVar g_meshShadersCVar("Gr", "MeshShaders", false, "Enable or not mesh shaders");
+inline NumericCVar<U8> g_deviceCVar("Gr", "Device", 0, 0, 16, "Choose an available device. Devices are sorted by performance");
+inline BoolCVar g_rayTracingCVar("Gr", "RayTracing", false, "Try enabling ray tracing");
+inline BoolCVar g_vrsCVar("Gr", "Vrs", false, "Enable or not VRS");
+inline BoolCVar g_workGraphcsCVar("Gr", "WorkGraphs", false, "Enable or not WorkGraphs");
+
+#if ANKI_GR_BACKEND_DIRECT3D
+inline NumericCVar<U16> g_maxRtvDescriptorsCVar("Gr", "MaxRvtDescriptors", 128, 8, kMaxU16, "Max number of RTVs");
+inline NumericCVar<U16> g_maxDsvDescriptorsCVar("Gr", "MaxDsvDescriptors", 128, 8, kMaxU16, "Max number of DSVs");
+inline NumericCVar<U16> g_maxCpuCbvSrvUavDescriptorsCVar("Gr", "MaxCpuCbvSrvUavDescriptors", 1024, 8, kMaxU16,
+														 "Max number of CBV/SRV/UAV descriptors");
+inline NumericCVar<U16> g_maxCpuSamplerDescriptorsCVar("Gr", "MaxCpuSamplerDescriptors", 64, 8, kMaxU16, "Max number of sampler descriptors");
+inline NumericCVar<U16> g_maxGpuCbvSrvUavDescriptorsCVar("Gr", "MaxGpuCbvSrvUavDescriptors", 2 * 1024, 8, kMaxU16,
+														 "Max number of CBV/SRV/UAV descriptors");
+inline NumericCVar<U16> g_maxGpuSamplerDescriptorsCVar("Gr", "MaxGpuSamplerDescriptors", 128, 8, kMaxU16, "Max number of sampler descriptors");
+
+inline BoolCVar g_dredCVar("Gr", "Dred", false, "Enable DRED");
+#else
+inline NumericCVar<U32> g_maxBindlessSampledTextureCountCVar("Gr", "MaxBindlessSampledTextureCountCVar", 512, 16, kMaxU16);
+inline NumericCVar<PtrSize> g_diskShaderCacheMaxSizeCVar("Gr", "DiskShaderCacheMaxSize", 128_MB, 1_MB, 1_GB, "Max size of the pipeline cache file");
+inline BoolCVar g_debugPrintfCVar("Gr", "DebugPrintf", false, "Enable or not debug printf");
+inline BoolCVar g_samplerFilterMinMaxCVar("Gr", "SamplerFilterMinMax", true, "Enable or not min/max sample filtering");
+inline BoolCVar g_asyncComputeCVar("Gr", "AsyncCompute", true, "Enable or not async compute");
+inline StringCVar g_vkLayersCVar("Gr", "VkLayers", "", "VK layers to enable. Seperated by :");
+#endif
+
 #define ANKI_GR_LOGI(...) ANKI_LOG("GR", kNormal, __VA_ARGS__)
 #define ANKI_GR_LOGE(...) ANKI_LOG("GR", kError, __VA_ARGS__)
 #define ANKI_GR_LOGW(...) ANKI_LOG("GR", kWarning, __VA_ARGS__)

+ 1 - 1
AnKi/Gr/D3D/D3DCommandBuffer.cpp

@@ -911,7 +911,7 @@ Error CommandBufferImpl::init(const CommandBufferInitInfo& init)
 
 	m_descriptors.init(m_fastPool);
 
-	m_debugMarkersEnabled = g_debugMarkersCVar.get();
+	m_debugMarkersEnabled = g_debugMarkersCVar;
 
 	m_timestampQueries = {m_fastPool};
 	m_pipelineQueries = {m_fastPool};

+ 9 - 20
AnKi/Gr/D3D/D3DDescriptor.cpp

@@ -4,21 +4,10 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Gr/D3D/D3DDescriptor.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 namespace anki {
 
-static NumericCVar<U16> g_maxRtvDescriptors(CVarSubsystem::kGr, "MaxRvtDescriptors", 128, 8, kMaxU16, "Max number of RTVs");
-static NumericCVar<U16> g_maxDsvDescriptors(CVarSubsystem::kGr, "MaxDsvDescriptors", 128, 8, kMaxU16, "Max number of DSVs");
-static NumericCVar<U16> g_maxCpuCbvSrvUavDescriptors(CVarSubsystem::kGr, "MaxCpuCbvSrvUavDescriptors", 1024, 8, kMaxU16,
-													 "Max number of CBV/SRV/UAV descriptors");
-static NumericCVar<U16> g_maxCpuSamplerDescriptors(CVarSubsystem::kGr, "MaxCpuSamplerDescriptors", 64, 8, kMaxU16,
-												   "Max number of sampler descriptors");
-static NumericCVar<U16> g_maxGpuCbvSrvUavDescriptors(CVarSubsystem::kGr, "MaxGpuCbvSrvUavDescriptors", 2 * 1024, 8, kMaxU16,
-													 "Max number of CBV/SRV/UAV descriptors");
-static NumericCVar<U16> g_maxGpuSamplerDescriptors(CVarSubsystem::kGr, "MaxGpuSamplerDescriptors", 128, 8, kMaxU16,
-												   "Max number of sampler descriptors");
-
 static Error createDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE type, D3D12_DESCRIPTOR_HEAP_FLAGS flags, U32 descriptorCount,
 								  ID3D12DescriptorHeap*& heap, D3D12_CPU_DESCRIPTOR_HANDLE& cpuHeapStart, D3D12_GPU_DESCRIPTOR_HANDLE& gpuHeapStart,
 								  U32& descriptorSize)
@@ -193,14 +182,14 @@ Error DescriptorFactory::init()
 		return Error::kNone;
 	};
 
-	ANKI_CHECK(createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxCpuCbvSrvUavDescriptors.get(),
+	ANKI_CHECK(createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxCpuCbvSrvUavDescriptorsCVar,
 									  m_cpuPersistent.m_cbvSrvUav));
-	ANKI_CHECK(createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxCpuSamplerDescriptors.get(),
+	ANKI_CHECK(createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxCpuSamplerDescriptorsCVar,
 									  m_cpuPersistent.m_sampler));
 	ANKI_CHECK(
-		createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxRtvDescriptors.get(), m_cpuPersistent.m_rtv));
+		createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_RTV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxRtvDescriptorsCVar, m_cpuPersistent.m_rtv));
 	ANKI_CHECK(
-		createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxDsvDescriptors.get(), m_cpuPersistent.m_dsv));
+		createHeapAndAllocator(D3D12_DESCRIPTOR_HEAP_TYPE_DSV, D3D12_DESCRIPTOR_HEAP_FLAG_NONE, g_maxDsvDescriptorsCVar, m_cpuPersistent.m_dsv));
 
 	// Init GPU visible heaps
 	ID3D12DescriptorHeap* heap;
@@ -208,19 +197,19 @@ Error DescriptorFactory::init()
 	D3D12_GPU_DESCRIPTOR_HANDLE gpuHeapStart;
 	U32 descriptorSize;
 	ANKI_CHECK(createDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE,
-									g_maxGpuCbvSrvUavDescriptors.get() + kMaxBindlessTextures, heap, cpuHeapStart, gpuHeapStart, descriptorSize));
+									g_maxGpuCbvSrvUavDescriptorsCVar + kMaxBindlessTextures, heap, cpuHeapStart, gpuHeapStart, descriptorSize));
 	m_descriptorHeaps.emplaceBack(heap);
 
 	m_gpuPersistent.m_cbvSrvUav.init(cpuHeapStart, gpuHeapStart, descriptorSize, kMaxBindlessTextures);
 
 	cpuHeapStart.ptr += descriptorSize * kMaxBindlessTextures;
 	gpuHeapStart.ptr += descriptorSize * kMaxBindlessTextures;
-	m_gpuRing.m_cbvSrvUav.init(cpuHeapStart, gpuHeapStart, descriptorSize, g_maxGpuCbvSrvUavDescriptors.get());
+	m_gpuRing.m_cbvSrvUav.init(cpuHeapStart, gpuHeapStart, descriptorSize, g_maxGpuCbvSrvUavDescriptorsCVar);
 
-	ANKI_CHECK(createDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, g_maxGpuSamplerDescriptors.get(),
+	ANKI_CHECK(createDescriptorHeap(D3D12_DESCRIPTOR_HEAP_TYPE_SAMPLER, D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE, g_maxGpuSamplerDescriptorsCVar,
 									heap, cpuHeapStart, gpuHeapStart, descriptorSize));
 	m_descriptorHeaps.emplaceBack(heap);
-	m_gpuRing.m_sampler.init(cpuHeapStart, gpuHeapStart, descriptorSize, g_maxGpuSamplerDescriptors.get());
+	m_gpuRing.m_sampler.init(cpuHeapStart, gpuHeapStart, descriptorSize, g_maxGpuSamplerDescriptorsCVar);
 
 	// Misc
 	for(D3D12_DESCRIPTOR_HEAP_TYPE type = D3D12_DESCRIPTOR_HEAP_TYPE(0); type < D3D12_DESCRIPTOR_HEAP_TYPE_NUM_TYPES;

+ 12 - 23
AnKi/Gr/D3D/D3DGrManager.cpp

@@ -35,17 +35,6 @@ __declspec(dllexport) extern const char* D3D12SDKPath = ".\\"; // The D3D12Core.
 
 namespace anki {
 
-BoolCVar g_validationCVar(CVarSubsystem::kGr, "Validation", false, "Enable or not validation");
-static BoolCVar g_gpuValidationCVar(CVarSubsystem::kGr, "GpuValidation", false, "Enable or not GPU validation");
-BoolCVar g_vsyncCVar(CVarSubsystem::kGr, "Vsync", false, "Enable or not vsync");
-BoolCVar g_debugMarkersCVar(CVarSubsystem::kGr, "DebugMarkers", false, "Enable or not debug markers");
-BoolCVar g_meshShadersCVar(CVarSubsystem::kGr, "MeshShaders", false, "Enable or not mesh shaders");
-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_dredCVar(CVarSubsystem::kGr, "Dred", false, "Enable DRED");
-static BoolCVar g_vrsCVar(CVarSubsystem::kGr, "Vrs", false, "Enable or not VRS");
-static BoolCVar g_workGraphcsCVar(CVarSubsystem::kGr, "WorkGraphs", false, "Enable or not WorkGraphs");
-
 static void NTAPI d3dDebugMessageCallback([[maybe_unused]] D3D12_MESSAGE_CATEGORY category, D3D12_MESSAGE_SEVERITY severity,
 										  [[maybe_unused]] D3D12_MESSAGE_ID id, LPCSTR pDescription, [[maybe_unused]] void* pContext)
 {
@@ -127,7 +116,7 @@ void GrManager::swapBuffers()
 	ANKI_TRACE_SCOPED_EVENT(D3DSwapBuffers);
 	ANKI_D3D_SELF(GrManagerImpl);
 
-	self.m_crntSwapchain->m_swapchain->Present((g_vsyncCVar.get()) ? 1 : 0, (g_vsyncCVar.get()) ? 0 : DXGI_PRESENT_ALLOW_TEARING);
+	self.m_crntSwapchain->m_swapchain->Present((g_vsyncCVar) ? 1 : 0, (g_vsyncCVar) ? 0 : DXGI_PRESENT_ALLOW_TEARING);
 
 	MicroFencePtr presentFence = FenceFactory::getSingleton().newInstance();
 	presentFence->gpuSignal(GpuQueueType::kGeneral);
@@ -265,7 +254,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 
 	// Validation
 	UINT dxgiFactoryFlags = 0;
-	if(g_validationCVar.get() || g_gpuValidationCVar.get())
+	if(g_validationCVar || g_gpuValidationCVar)
 	{
 		ComPtr<ID3D12Debug> debugInterface;
 		ANKI_D3D_CHECK(D3D12GetDebugInterface(IID_PPV_ARGS(&debugInterface)));
@@ -274,7 +263,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 
 		dxgiFactoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
 
-		if(g_gpuValidationCVar.get())
+		if(g_gpuValidationCVar)
 		{
 			ComPtr<ID3D12Debug1> debugInterface1;
 			ANKI_D3D_CHECK(debugInterface->QueryInterface(IID_PPV_ARGS(&debugInterface1)));
@@ -282,7 +271,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 			debugInterface1->SetEnableGPUBasedValidation(true);
 		}
 
-		ANKI_D3D_LOGI("Validation is enabled (GPU validation %s)", (g_gpuValidationCVar.get()) ? "as well" : "no");
+		ANKI_D3D_LOGI("Validation is enabled (GPU validation %s)", (g_gpuValidationCVar) ? "as well" : "no");
 	}
 
 	ComPtr<IDXGIFactory2> factory2;
@@ -309,7 +298,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		++adapterIdx;
 	}
 
-	const U32 chosenPhysDevIdx = min<U32>(g_deviceCVar.get(), adapters.getSize() - 1);
+	const U32 chosenPhysDevIdx = min<U32>(g_deviceCVar, adapters.getSize() - 1);
 
 	ANKI_D3D_LOGI("Physical devices:");
 	for(U32 i = 0; i < adapters.getSize(); ++i)
@@ -359,7 +348,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	ANKI_D3D_CHECK(D3D12CreateDevice(adapters[chosenPhysDevIdx].m_adapter.Get(), D3D_FEATURE_LEVEL_12_1, IID_PPV_ARGS(&dev)));
 	ANKI_D3D_CHECK(dev->QueryInterface(IID_PPV_ARGS(&m_device)));
 
-	if(g_validationCVar.get())
+	if(g_validationCVar)
 	{
 		ComPtr<ID3D12InfoQueue1> infoq;
 		const HRESULT res = m_device->QueryInterface(IID_PPV_ARGS(&infoq));
@@ -388,7 +377,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		}
 	}
 
-	if(g_dredCVar.get())
+	if(g_dredCVar)
 	{
 		ComPtr<ID3D12DeviceRemovedExtendedDataSettings> dredSettings;
 		ANKI_D3D_CHECK(D3D12GetDebugInterface(IID_PPV_ARGS(&dredSettings)));
@@ -422,11 +411,11 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		D3D12_FEATURE_DATA_D3D12_OPTIONS21 options21;
 		ANKI_D3D_CHECK(m_device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS21, &options21, sizeof(options21)));
 
-		if(g_workGraphcsCVar.get() && options21.WorkGraphsTier == D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
+		if(g_workGraphcsCVar && options21.WorkGraphsTier == D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
 		{
 			ANKI_D3D_LOGW("WorkGraphs can't be enabled. They not supported");
 		}
-		else if(g_workGraphcsCVar.get() && options21.WorkGraphsTier != D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
+		else if(g_workGraphcsCVar && options21.WorkGraphsTier != D3D12_WORK_GRAPHS_TIER_NOT_SUPPORTED)
 		{
 			ANKI_D3D_LOGV("WorkGraphs supported");
 			m_capabilities.m_workGraphs = true;
@@ -449,13 +438,13 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		m_capabilities.m_maxDrawIndirectCount = kMaxU32;
 		m_capabilities.m_discreteGpu = !architecture.UMA;
 		m_capabilities.m_majorApiVersion = 12;
-		m_capabilities.m_rayTracingEnabled = g_rayTracingCVar.get();
+		m_capabilities.m_rayTracingEnabled = g_rayTracingCVar;
 		m_capabilities.m_64bitAtomics = true;
-		m_capabilities.m_vrs = g_vrsCVar.get();
+		m_capabilities.m_vrs = g_vrsCVar;
 		m_capabilities.m_samplingFilterMinMax = true;
 		m_capabilities.m_unalignedBbpTextureFormats = false;
 		m_capabilities.m_dlss = false;
-		m_capabilities.m_meshShaders = g_meshShadersCVar.get();
+		m_capabilities.m_meshShaders = g_meshShadersCVar;
 		m_capabilities.m_pipelineQuery = true;
 		m_capabilities.m_barycentrics = true;
 	}

+ 2 - 2
AnKi/Gr/D3D/D3DSwapchainFactory.cpp

@@ -47,7 +47,7 @@ Error MicroSwapchain::initInternal()
 	const HWND hwnd = wmInfo.info.win.window;
 
 	ComPtr<IDXGIFactory2> factory2;
-	ANKI_D3D_CHECK(CreateDXGIFactory2((g_validationCVar.get()) ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&factory2)));
+	ANKI_D3D_CHECK(CreateDXGIFactory2((g_validationCVar) ? DXGI_CREATE_FACTORY_DEBUG : 0, IID_PPV_ARGS(&factory2)));
 
 	// Describe and create the swap chain.
 	DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
@@ -58,7 +58,7 @@ Error MicroSwapchain::initInternal()
 	swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
 	swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
 	swapChainDesc.SampleDesc.Count = 1;
-	swapChainDesc.Flags |= (!g_vsyncCVar.get()) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
+	swapChainDesc.Flags |= (!g_vsyncCVar) ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0;
 
 	ComPtr<IDXGISwapChain1> swapChain;
 	// Swap chain needs the queue so that it can force a flush on it.

+ 1 - 5
AnKi/Gr/GrManager.h

@@ -9,16 +9,12 @@
 #include <AnKi/Gr/GrObject.h>
 #include <AnKi/Util/String.h>
 #include <AnKi/Util/WeakArray.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 namespace anki {
 
 // Forward
 class NativeWindow;
-extern BoolCVar g_vsyncCVar;
-extern BoolCVar g_validationCVar;
-extern BoolCVar g_debugMarkersCVar;
-extern BoolCVar g_meshShadersCVar;
 
 /// @addtogroup graphics
 /// @{

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

@@ -195,7 +195,7 @@ BindlessDescriptorSet::~BindlessDescriptorSet()
 
 Error BindlessDescriptorSet::init()
 {
-	const U32 bindlessTextureCount = g_maxBindlessSampledTextureCountCVar.get();
+	const U32 bindlessTextureCount = g_maxBindlessSampledTextureCountCVar;
 
 	// Create the layout
 	{

+ 24 - 41
AnKi/Gr/Vulkan/VkGrManager.cpp

@@ -38,22 +38,6 @@
 
 namespace anki {
 
-BoolCVar g_validationCVar(CVarSubsystem::kGr, "Validation", false, "Enable or not validation");
-static BoolCVar g_gpuValidationCVar(CVarSubsystem::kGr, "GpuValidation", false, "Enable or not GPU validation");
-static BoolCVar g_debugPrintfCVar(CVarSubsystem::kGr, "DebugPrintf", false, "Enable or not debug printf");
-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");
-BoolCVar g_meshShadersCVar(CVarSubsystem::kGr, "MeshShaders", false, "Enable or not mesh shaders");
-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");
-static StringCVar g_vkLayers(CVarSubsystem::kGr, "VkLayers", "", "VK layers to enable. Seperated by :");
-
 // DLSS related
 #define ANKI_VK_NVX_BINARY_IMPORT "VK_NVX_binary_import"
 
@@ -410,7 +394,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 		}
 	}
 
-	SwapchainFactory::allocateSingleton(g_vsyncCVar.get());
+	SwapchainFactory::allocateSingleton(U32(g_vsyncCVar));
 	m_crntSwapchain = SwapchainFactory::getSingleton().newInstance();
 
 	PipelineCache::allocateSingleton();
@@ -481,8 +465,8 @@ Error GrManagerImpl::initInstance()
 
 	// Create the instance
 	//
-	const U8 vulkanMinor = g_vkMinorCVar.get();
-	const U8 vulkanMajor = g_vkMajorCVar.get();
+	const U8 vulkanMinor = 1;
+	const U8 vulkanMajor = 1;
 
 	VkApplicationInfo app = {};
 	app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -515,8 +499,8 @@ Error GrManagerImpl::initInstance()
 				ANKI_VK_LOGV("\t%s", layer.layerName);
 				CString layerName = layer.layerName;
 
-				Bool enableLayer = (g_validationCVar.get() || g_debugPrintfCVar.get()) && layerName == "VK_LAYER_KHRONOS_validation";
-				enableLayer = enableLayer || (!g_vkLayers.get().isEmpty() && g_vkLayers.get().find(layerName) != CString::kNpos);
+				Bool enableLayer = (g_validationCVar || g_debugPrintfCVar) && layerName == "VK_LAYER_KHRONOS_validation";
+				enableLayer = enableLayer || (!CString(g_vkLayersCVar).isEmpty() && CString(g_vkLayersCVar).find(layerName) != CString::kNpos);
 
 				if(enableLayer)
 				{
@@ -542,17 +526,17 @@ Error GrManagerImpl::initInstance()
 	// Validation features
 	GrDynamicArray<VkValidationFeatureEnableEXT> enabledValidationFeatures;
 	GrDynamicArray<VkValidationFeatureDisableEXT> disabledValidationFeatures;
-	if(g_debugPrintfCVar.get())
+	if(g_debugPrintfCVar)
 	{
 		enabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT);
 	}
 
-	if(g_debugPrintfCVar.get() && !g_validationCVar.get())
+	if(g_debugPrintfCVar && !g_validationCVar)
 	{
 		disabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_DISABLE_ALL_EXT);
 	}
 
-	if(g_validationCVar.get() && g_gpuValidationCVar.get())
+	if(g_validationCVar && g_gpuValidationCVar)
 	{
 		enabledValidationFeatures.emplaceBack(VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT);
 	}
@@ -626,8 +610,7 @@ Error GrManagerImpl::initInstance()
 				m_extensions |= VulkanExtensions::kKHR_surface;
 				instExtensions[instExtensionCount++] = VK_KHR_SURFACE_EXTENSION_NAME;
 			}
-			else if(extensionName == VK_EXT_DEBUG_UTILS_EXTENSION_NAME
-					&& (g_debugMarkersCVar.get() || g_validationCVar.get() || g_debugPrintfCVar.get()))
+			else if(extensionName == VK_EXT_DEBUG_UTILS_EXTENSION_NAME && (g_debugMarkersCVar || g_validationCVar || g_debugPrintfCVar))
 			{
 				m_extensions |= VulkanExtensions::kEXT_debug_utils;
 				instExtensions[instExtensionCount++] = VK_EXT_DEBUG_UTILS_EXTENSION_NAME;
@@ -744,7 +727,7 @@ Error GrManagerImpl::initInstance()
 			}
 		});
 
-		const U32 chosenPhysDevIdx = min<U32>(g_deviceCVar.get(), devs.getSize() - 1);
+		const U32 chosenPhysDevIdx = min<U32>(g_deviceCVar, devs.getSize() - 1);
 
 		ANKI_VK_LOGI("Physical devices:");
 		for(U32 devIdx = 0; devIdx < count; ++devIdx)
@@ -860,7 +843,7 @@ Error GrManagerImpl::initDevice()
 		return Error::kFunctionFailed;
 	}
 
-	if(!g_asyncComputeCVar.get())
+	if(!g_asyncComputeCVar)
 	{
 		m_queueFamilyIndices[GpuQueueType::kCompute] = kMaxU32;
 	}
@@ -927,34 +910,34 @@ Error GrManagerImpl::initDevice()
 				m_extensions |= VulkanExtensions::kAMD_rasterization_order;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME && g_rayTracingCVar.get())
+			else if(extensionName == VK_KHR_RAY_TRACING_PIPELINE_EXTENSION_NAME && g_rayTracingCVar)
 			{
 				m_extensions |= VulkanExtensions::kKHR_ray_tracing;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 				m_capabilities.m_rayTracingEnabled = true;
 			}
-			else if(extensionName == VK_KHR_RAY_QUERY_EXTENSION_NAME && g_rayTracingCVar.get())
+			else if(extensionName == VK_KHR_RAY_QUERY_EXTENSION_NAME && g_rayTracingCVar)
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME && g_rayTracingCVar.get())
+			else if(extensionName == VK_KHR_ACCELERATION_STRUCTURE_EXTENSION_NAME && g_rayTracingCVar)
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME && g_rayTracingCVar.get())
+			else if(extensionName == VK_KHR_DEFERRED_HOST_OPERATIONS_EXTENSION_NAME && g_rayTracingCVar)
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME && g_rayTracingCVar.get())
+			else if(extensionName == VK_KHR_PIPELINE_LIBRARY_EXTENSION_NAME && g_rayTracingCVar)
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME && g_displayStatsCVar.get() > 1)
+			else if(extensionName == VK_KHR_PIPELINE_EXECUTABLE_PROPERTIES_EXTENSION_NAME && g_displayStatsCVar > 1)
 			{
 				m_extensions |= VulkanExtensions::kKHR_pipeline_executable_properties;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME && g_debugPrintfCVar.get())
+			else if(extensionName == VK_KHR_SHADER_NON_SEMANTIC_INFO_EXTENSION_NAME && g_debugPrintfCVar)
 			{
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
@@ -983,7 +966,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 && g_64bitAtomicsCVar.get())
+			else if(extensionName == VK_KHR_SHADER_ATOMIC_INT64_EXTENSION_NAME)
 			{
 				m_extensions |= VulkanExtensions::kKHR_shader_atomic_int64;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
@@ -998,7 +981,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 && g_samplerFilterMinMaxCVar.get())
+			else if(extensionName == VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME && g_samplerFilterMinMaxCVar)
 			{
 				m_extensions |= VulkanExtensions::kKHR_sampler_filter_min_max;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
@@ -1008,7 +991,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 && g_vrsCVar.get())
+			else if(extensionName == VK_KHR_FRAGMENT_SHADING_RATE_EXTENSION_NAME && g_vrsCVar)
 			{
 				m_extensions |= VulkanExtensions::kKHR_fragment_shading_rate;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
@@ -1048,7 +1031,7 @@ Error GrManagerImpl::initDevice()
 				m_extensions |= VulkanExtensions::kKHR_draw_indirect_count;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
 			}
-			else if(extensionName == VK_EXT_MESH_SHADER_EXTENSION_NAME && g_meshShadersCVar.get())
+			else if(extensionName == VK_EXT_MESH_SHADER_EXTENSION_NAME && g_meshShadersCVar)
 			{
 				m_extensions |= VulkanExtensions::kEXT_mesh_shader;
 				extensionsToEnable[extensionsToEnableCount++] = extensionName.cstr();
@@ -1092,7 +1075,7 @@ Error GrManagerImpl::initDevice()
 		devFeatures2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
 		vkGetPhysicalDeviceFeatures2(m_physicalDevice, &devFeatures2);
 		devFeatures = devFeatures2.features;
-		devFeatures.robustBufferAccess = (g_validationCVar.get() && devFeatures.robustBufferAccess) ? true : false;
+		devFeatures.robustBufferAccess = (g_validationCVar && devFeatures.robustBufferAccess) ? true : false;
 		ANKI_VK_LOGI("Robust buffer access is %s", (devFeatures.robustBufferAccess) ? "enabled" : "disabled");
 
 		if(devFeatures.pipelineStatisticsQuery)
@@ -1174,7 +1157,7 @@ Error GrManagerImpl::initDevice()
 		deviceBufferFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_DEVICE_ADDRESS_FEATURES_KHR;
 		getPhysicalDevicaFeatures2(deviceBufferFeatures);
 
-		deviceBufferFeatures.bufferDeviceAddressCaptureReplay = deviceBufferFeatures.bufferDeviceAddressCaptureReplay && g_debugMarkersCVar.get();
+		deviceBufferFeatures.bufferDeviceAddressCaptureReplay = deviceBufferFeatures.bufferDeviceAddressCaptureReplay && g_debugMarkersCVar;
 		deviceBufferFeatures.bufferDeviceAddressMultiDevice = false;
 
 		appendPNextList(ci, &deviceBufferFeatures);

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

@@ -11,9 +11,6 @@
 
 namespace anki {
 
-static NumericCVar<PtrSize> g_diskShaderCacheMaxSizeCVar(CVarSubsystem::kGr, "DiskShaderCacheMaxSize", 128_MB, 1_MB, 1_GB,
-														 "Max size of the pipeline cache file");
-
 static VkViewport computeViewport(U32* viewport, U32 fbWidth, U32 fbHeight)
 {
 	const U32 minx = viewport[0];
@@ -403,7 +400,7 @@ void GraphicsPipelineFactory::flushState(GraphicsStateTracker& state, VkCommandB
 Error PipelineCache::init(CString cacheDir)
 {
 	ANKI_ASSERT(cacheDir);
-	m_dumpSize = g_diskShaderCacheMaxSizeCVar.get();
+	m_dumpSize = g_diskShaderCacheMaxSizeCVar;
 	m_dumpFilename.sprintf("%s/VkPipelineCache", cacheDir.cstr());
 
 	// Try read the pipeline cache file.

+ 0 - 7
AnKi/Math/Functions.h

@@ -161,13 +161,6 @@ inline constexpr T toDegrees(const T rad)
 	return rad * (T(180) / kPi);
 }
 
-template<typename T>
-inline constexpr T clamp(T v, T minv, T maxv)
-{
-	ANKI_ASSERT(minv <= maxv);
-	return min<T>(max<T>(minv, v), maxv);
-}
-
 template<typename T>
 inline constexpr T saturate(T v)
 {

+ 1 - 2
AnKi/Renderer.h

@@ -13,7 +13,6 @@
 #include <AnKi/Renderer/FinalComposite.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/ShadowMapping.h>
-#include <AnKi/Renderer/DownscaleBlur.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/LensFlare.h>
 #include <AnKi/Renderer/TemporalAA.h>
@@ -23,7 +22,7 @@
 #include <AnKi/Renderer/UiStage.h>
 #include <AnKi/Renderer/Tonemapping.h>
 #include <AnKi/Renderer/RendererObject.h>
-#include <AnKi/Renderer/Bloom.h>
+#include <AnKi/Renderer/Bloom2.h>
 #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
 #include <AnKi/Renderer/IndirectDiffuseProbes.h>
 #include <AnKi/Renderer/ShadowmapsResolve.h>

+ 2 - 6
AnKi/Renderer/AccelerationStructureBuilder.cpp

@@ -12,10 +12,6 @@
 
 namespace anki {
 
-static NumericCVar<F32>
-	g_rayTracingExtendedFrustumDistanceCVar(CVarSubsystem::kRenderer, "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");
-
 void AccelerationStructureBuilder::populateRenderGraph(RenderingContext& ctx)
 {
 	ANKI_TRACE_SCOPED_EVENT(ASBuilder);
@@ -23,14 +19,14 @@ void AccelerationStructureBuilder::populateRenderGraph(RenderingContext& ctx)
 	// Do visibility
 	GpuVisibilityAccelerationStructuresOutput visOut;
 	{
-		const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+		const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 
 		GpuVisibilityAccelerationStructuresInput in;
 		in.m_passesName = "Main TLAS visiblity";
 		in.m_lodReferencePoint = ctx.m_matrices.m_cameraTransform.getTranslationPart().xyz();
 		in.m_lodDistances = lodDistances;
 		in.m_pointOfTest = in.m_lodReferencePoint;
-		in.m_testRadius = g_rayTracingExtendedFrustumDistanceCVar.get();
+		in.m_testRadius = g_rayTracingExtendedFrustumDistanceCVar;
 		in.m_viewProjectionMatrix = ctx.m_matrices.m_viewProjection;
 		in.m_rgraph = &ctx.m_renderGraphDescr;
 

+ 4 - 0
AnKi/Renderer/AccelerationStructureBuilder.h

@@ -12,6 +12,10 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<F32>
+	g_rayTracingExtendedFrustumDistanceCVar("R", "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");
+
 /// Build acceleration structures.
 class AccelerationStructureBuilder : public RendererObject
 {

+ 0 - 197
AnKi/Renderer/Bloom.cpp

@@ -1,197 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Renderer/Bloom.h>
-#include <AnKi/Renderer/DownscaleBlur.h>
-#include <AnKi/Renderer/FinalComposite.h>
-#include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/Tonemapping.h>
-#include <AnKi/Core/CVarSet.h>
-#include <AnKi/Util/Tracer.h>
-
-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");
-}
-
-Bloom::~Bloom()
-{
-}
-
-Error Bloom::initInternal()
-{
-	ANKI_R_LOGV("Initializing bloom");
-
-	ANKI_CHECK(initExposure());
-	ANKI_CHECK(initUpscale());
-	return Error::kNone;
-}
-
-Error Bloom::initExposure()
-{
-	const U32 width = getRenderer().getDownscaleBlur().getPassWidth(kMaxU32) * 2;
-	const U32 height = getRenderer().getDownscaleBlur().getPassHeight(kMaxU32) * 2;
-
-	// Create RT info
-	m_exposure.m_rtDescr = getRenderer().create2DRenderTargetDescription(width, height, getRenderer().getHdrFormat(), "Bloom Exp");
-	m_exposure.m_rtDescr.bake();
-
-	// init shaders
-	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Bloom.ankiprogbin", m_exposure.m_prog, m_exposure.m_grProg));
-
-	return Error::kNone;
-}
-
-Error Bloom::initUpscale()
-{
-	const U32 width = getRenderer().getPostProcessResolution().x() / kBloomFraction;
-	const U32 height = getRenderer().getPostProcessResolution().y() / kBloomFraction;
-
-	// Create RT descr
-	m_upscale.m_rtDescr = getRenderer().create2DRenderTargetDescription(width, height, getRenderer().getHdrFormat(), "Bloom Upscale");
-	m_upscale.m_rtDescr.bake();
-
-	// init shaders
-	ANKI_CHECK(loadShaderProgram("ShaderBinaries/BloomUpscale.ankiprogbin", m_upscale.m_prog, m_upscale.m_grProg));
-
-	// Textures
-	ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/LensDirt.ankitex", m_upscale.m_lensDirtImage));
-
-	return Error::kNone;
-}
-
-void Bloom::populateRenderGraph(RenderingContext& ctx)
-{
-	ANKI_TRACE_SCOPED_EVENT(Bloom);
-
-	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = g_preferComputeCVar.get();
-
-	// Main pass
-	{
-		// Ask for render target
-		m_runCtx.m_exposureRt = rgraph.newRenderTarget(m_exposure.m_rtDescr);
-
-		// Set the render pass
-		const TextureSubresourceDesc inputTexSubresource =
-			TextureSubresourceDesc::surface(getRenderer().getDownscaleBlur().getMipmapCount() - 1, 0, 0);
-
-		RenderPassBase* prpass;
-		if(preferCompute)
-		{
-			NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("Bloom Main");
-
-			rpass.newTextureDependency(getRenderer().getDownscaleBlur().getRt(), TextureUsageBit::kSrvCompute, inputTexSubresource);
-			rpass.newTextureDependency(m_runCtx.m_exposureRt, TextureUsageBit::kUavCompute);
-
-			prpass = &rpass;
-		}
-		else
-		{
-			GraphicsRenderPass& rpass = rgraph.newGraphicsRenderPass("Bloom Main");
-			rpass.setRenderpassInfo({GraphicsRenderPassTargetDesc(m_runCtx.m_exposureRt)});
-
-			rpass.newTextureDependency(getRenderer().getDownscaleBlur().getRt(), TextureUsageBit::kSrvPixel, inputTexSubresource);
-			rpass.newTextureDependency(m_runCtx.m_exposureRt, TextureUsageBit::kRtvDsvWrite);
-
-			prpass = &rpass;
-		}
-
-		prpass->setWork([this](RenderPassWorkContext& rgraphCtx) {
-			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-
-			cmdb.bindShaderProgram(m_exposure.m_grProg.get());
-
-			const TextureSubresourceDesc inputTexSubresource =
-				TextureSubresourceDesc::surface(getRenderer().getDownscaleBlur().getMipmapCount() - 1, 0, 0);
-
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindSrv(0, 0, getRenderer().getDownscaleBlur().getRt(), inputTexSubresource);
-
-			const Vec4 consts(g_bloomThresholdCVar.get(), g_bloomScaleCVar.get(), 0.0f, 0.0f);
-			cmdb.setFastConstants(&consts, sizeof(consts));
-
-			rgraphCtx.bindUav(0, 0, getRenderer().getTonemapping().getRt());
-
-			if(g_preferComputeCVar.get())
-			{
-				rgraphCtx.bindUav(1, 0, m_runCtx.m_exposureRt);
-
-				dispatchPPCompute(cmdb, 8, 8, m_exposure.m_rtDescr.m_width, m_exposure.m_rtDescr.m_height);
-			}
-			else
-			{
-				cmdb.setViewport(0, 0, m_exposure.m_rtDescr.m_width, m_exposure.m_rtDescr.m_height);
-
-				cmdb.draw(PrimitiveTopology::kTriangles, 3);
-			}
-		});
-	}
-
-	// Upscale & SSLF pass
-	{
-		// Ask for render target
-		m_runCtx.m_upscaleRt = rgraph.newRenderTarget(m_upscale.m_rtDescr);
-
-		// Set the render pass
-		RenderPassBase* prpass;
-		if(preferCompute)
-		{
-			NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("Bloom Upscale");
-
-			rpass.newTextureDependency(m_runCtx.m_exposureRt, TextureUsageBit::kSrvCompute);
-			rpass.newTextureDependency(m_runCtx.m_upscaleRt, TextureUsageBit::kUavCompute);
-
-			prpass = &rpass;
-		}
-		else
-		{
-			GraphicsRenderPass& rpass = rgraph.newGraphicsRenderPass("Bloom Upscale");
-			rpass.setRenderpassInfo({GraphicsRenderPassTargetDesc(m_runCtx.m_upscaleRt)});
-
-			rpass.newTextureDependency(m_runCtx.m_exposureRt, TextureUsageBit::kSrvPixel);
-			rpass.newTextureDependency(m_runCtx.m_upscaleRt, TextureUsageBit::kRtvDsvWrite);
-
-			prpass = &rpass;
-		}
-
-		prpass->setWork([this](RenderPassWorkContext& rgraphCtx) {
-			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-
-			cmdb.bindShaderProgram(m_upscale.m_grProg.get());
-
-			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-			rgraphCtx.bindSrv(0, 0, m_runCtx.m_exposureRt);
-			cmdb.bindSrv(1, 0, TextureView(&m_upscale.m_lensDirtImage->getTexture(), TextureSubresourceDesc::all()));
-
-			if(g_preferComputeCVar.get())
-			{
-				rgraphCtx.bindUav(0, 0, m_runCtx.m_upscaleRt);
-
-				dispatchPPCompute(cmdb, 8, 8, m_upscale.m_rtDescr.m_width, m_upscale.m_rtDescr.m_height);
-			}
-			else
-			{
-				cmdb.setViewport(0, 0, m_upscale.m_rtDescr.m_width, m_upscale.m_rtDescr.m_height);
-
-				cmdb.draw(PrimitiveTopology::kTriangles, 3);
-			}
-		});
-	}
-}
-
-void Bloom::getDebugRenderTarget([[maybe_unused]] CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
-								 [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const
-{
-	ANKI_ASSERT(rtName == "Bloom");
-	handles[0] = m_runCtx.m_upscaleRt;
-}
-
-} // end namespace anki

+ 0 - 84
AnKi/Renderer/Bloom.h

@@ -1,84 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Renderer/RendererObject.h>
-#include <AnKi/Gr.h>
-#include <AnKi/Resource/ImageResource.h>
-
-namespace anki {
-
-// Forward
-extern NumericCVar<F32> g_bloomThresholdCVar;
-
-/// @addtogroup renderer
-/// @{
-
-/// Bloom passes.
-class Bloom : public RendererObject
-{
-public:
-	Bloom();
-
-	~Bloom();
-
-	Error init()
-	{
-		const Error err = initInternal();
-		if(err)
-		{
-			ANKI_R_LOGE("Failed to initialize bloom passes");
-		}
-		return err;
-	}
-
-	/// Populate the rendergraph.
-	void populateRenderGraph(RenderingContext& ctx);
-
-	RenderTargetHandle getRt() const
-	{
-		return m_runCtx.m_upscaleRt;
-	}
-
-private:
-	class
-	{
-	public:
-		ShaderProgramResourcePtr m_prog;
-		ShaderProgramPtr m_grProg;
-
-		RenderTargetDesc m_rtDescr;
-	} m_exposure;
-
-	class
-	{
-	public:
-		ImageResourcePtr m_lensDirtImage;
-		ShaderProgramResourcePtr m_prog;
-		ShaderProgramPtr m_grProg;
-
-		RenderTargetDesc m_rtDescr;
-	} m_upscale;
-
-	class
-	{
-	public:
-		RenderTargetHandle m_exposureRt;
-		RenderTargetHandle m_upscaleRt;
-	} m_runCtx;
-
-	Error initExposure();
-	Error initUpscale();
-
-	Error initInternal();
-
-	void getDebugRenderTarget(CString rtName, Array<RenderTargetHandle, kMaxDebugRenderTargets>& handles,
-							  [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const override;
-};
-
-/// @}
-
-} // end namespace anki

+ 270 - 0
AnKi/Renderer/Bloom2.cpp

@@ -0,0 +1,270 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Renderer/Bloom2.h>
+#include <AnKi/Renderer/Renderer.h>
+#include <AnKi/Renderer/LightShading.h>
+#include <AnKi/Renderer/Tonemapping.h>
+
+namespace anki {
+
+Error Bloom2::init()
+{
+	// Pyramid
+	{
+		const UVec2 pyramidSize = getRenderer().getInternalResolution() / 2;
+		const U32 pyramidMipCount = computeMaxMipmapCount2d(pyramidSize.x(), pyramidSize.y(), g_bloomPyramidLowLimit);
+
+		ANKI_R_LOGV("Initializing bloom downscale pyramid. Resolution %ux%u, mip count %u", pyramidSize.x(), pyramidSize.y(), pyramidMipCount);
+
+		const Bool preferCompute = g_preferComputeCVar;
+
+		// Create the miped texture
+		TextureInitInfo texinit =
+			getRenderer().create2DRenderTargetDescription(pyramidSize.x(), pyramidSize.y(), getRenderer().getHdrFormat(), "Bloom pyramid");
+		texinit.m_usage = TextureUsageBit::kSrvPixel | TextureUsageBit::kSrvCompute;
+		texinit.m_usage |= (preferCompute) ? TextureUsageBit::kUavCompute : TextureUsageBit::kRtvDsvWrite;
+		texinit.m_mipmapCount = U8(pyramidMipCount);
+		m_pyramidTex = getRenderer().createAndClearRenderTarget(texinit, TextureUsageBit::kSrvCompute);
+
+		// Shader programs
+		ANKI_CHECK(loadShaderProgram("ShaderBinaries/Bloom2.ankiprogbin", {}, m_prog, m_downscaleGrProg, "Downscale"));
+	}
+
+	// Exposure
+	{
+		const UVec2 pyramidSmallerMipSize = UVec2(m_pyramidTex->getWidth(), m_pyramidTex->getHeight()) >> (m_pyramidTex->getMipmapCount() - 1);
+
+		const UVec2 expSize = pyramidSmallerMipSize * 2; // Upacale a bit
+
+		// Create RT info
+		m_exposureRtDesc = getRenderer().create2DRenderTargetDescription(expSize.x(), expSize.y(), getRenderer().getHdrFormat(), "Bloom exposure");
+		m_exposureRtDesc.bake();
+
+		// init shaders
+		ANKI_CHECK(loadShaderProgram("ShaderBinaries/Bloom2.ankiprogbin", {}, m_prog, m_exposureGrProg, "Exposure"));
+	}
+
+	// Upscale
+	{
+		const UVec2 size = getRenderer().getPostProcessResolution() / g_bloomUpscaleDivisor;
+
+		// Create RT descr
+		m_finalRtDesc = getRenderer().create2DRenderTargetDescription(size.x(), size.y(), getRenderer().getHdrFormat(), "Bloom final");
+		m_finalRtDesc.bake();
+
+		// init shaders
+		ANKI_CHECK(loadShaderProgram("ShaderBinaries/Bloom2.ankiprogbin", {}, m_prog, m_upscaleGrProg, "Upscale"));
+
+		// Textures
+		ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/LensDirt.ankitex", m_lensDirtImg));
+	}
+
+	return Error::kNone;
+}
+
+void Bloom2::importRenderTargets(RenderingContext& ctx)
+{
+	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
+	m_runCtx.m_pyramidRt = rgraph.importRenderTarget(m_pyramidTex.get(), TextureUsageBit::kSrvCompute);
+}
+
+void Bloom2::populateRenderGraph(RenderingContext& ctx)
+{
+	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
+	const Bool preferCompute = g_preferComputeCVar;
+
+	// Pyramid generation
+	{
+		const U32 passCount = m_pyramidTex->getMipmapCount();
+		const RenderTargetHandle inRt = getRenderer().getLightShading().getRt();
+
+		for(U32 i = 0; i < passCount; ++i)
+		{
+			RenderPassBase* ppass;
+			if(preferCompute)
+			{
+				ppass = &rgraph.newNonGraphicsRenderPass(generateTempPassName("Bloom pyramid %u", i));
+			}
+			else
+			{
+				GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass(generateTempPassName("Bloom pyramid %u", i));
+
+				GraphicsRenderPassTargetDesc rtInf(m_runCtx.m_pyramidRt);
+				rtInf.m_subresource.m_mipmap = i;
+				pass.setRenderpassInfo({rtInf});
+
+				ppass = &pass;
+			}
+
+			const TextureUsageBit readUsage = (preferCompute) ? TextureUsageBit::kSrvCompute : TextureUsageBit::kSrvPixel;
+			const TextureUsageBit writeUsage = (preferCompute) ? TextureUsageBit::kUavCompute : TextureUsageBit::kRtvDsvWrite;
+
+			if(i > 0)
+			{
+				const TextureSubresourceDesc sampleSubresource = TextureSubresourceDesc::surface(i - 1, 0, 0);
+				const TextureSubresourceDesc renderSubresource = TextureSubresourceDesc::surface(i, 0, 0);
+
+				ppass->newTextureDependency(m_runCtx.m_pyramidRt, writeUsage, renderSubresource);
+				ppass->newTextureDependency(m_runCtx.m_pyramidRt, readUsage, sampleSubresource);
+			}
+			else
+			{
+				ppass->newTextureDependency(m_runCtx.m_pyramidRt, writeUsage, TextureSubresourceDesc::firstSurface());
+				ppass->newTextureDependency(inRt, readUsage);
+			}
+
+			ppass->setWork([this, passIdx = i](RenderPassWorkContext& rgraphCtx) {
+				CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+
+				cmdb.bindShaderProgram(m_downscaleGrProg.get());
+
+				const U32 vpWidth = m_pyramidTex->getWidth() >> passIdx;
+				const U32 vpHeight = m_pyramidTex->getHeight() >> passIdx;
+
+				cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
+
+				if(passIdx > 0)
+				{
+					rgraphCtx.bindSrv(0, 0, m_runCtx.m_pyramidRt, TextureSubresourceDesc::surface(passIdx - 1, 0, 0));
+				}
+				else
+				{
+					rgraphCtx.bindSrv(0, 0, getRenderer().getLightShading().getRt());
+				}
+
+				if(g_preferComputeCVar)
+				{
+					const Vec4 fbSize(F32(vpWidth), F32(vpHeight), 0.0f, 0.0f);
+					cmdb.setFastConstants(&fbSize, sizeof(fbSize));
+
+					rgraphCtx.bindUav(1, 0, m_runCtx.m_pyramidRt, TextureSubresourceDesc::surface(passIdx, 0, 0));
+
+					dispatchPPCompute(cmdb, 8, 8, vpWidth, vpHeight);
+				}
+				else
+				{
+					cmdb.setViewport(0, 0, vpWidth, vpHeight);
+
+					cmdb.draw(PrimitiveTopology::kTriangles, 3);
+				}
+			});
+		}
+	}
+
+	// Exposure
+	RenderTargetHandle exposureRt;
+	{
+		// Ask for render target
+		exposureRt = rgraph.newRenderTarget(m_exposureRtDesc);
+
+		// Set the render pass
+		const TextureSubresourceDesc inputTexSubresource = TextureSubresourceDesc::surface(m_pyramidTex->getMipmapCount() - 1, 0, 0);
+
+		RenderPassBase* prpass;
+		if(preferCompute)
+		{
+			NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("Bloom Main");
+
+			rpass.newTextureDependency(m_runCtx.m_pyramidRt, TextureUsageBit::kSrvCompute, inputTexSubresource);
+			rpass.newTextureDependency(exposureRt, TextureUsageBit::kUavCompute);
+
+			prpass = &rpass;
+		}
+		else
+		{
+			GraphicsRenderPass& rpass = rgraph.newGraphicsRenderPass("Bloom Main");
+			rpass.setRenderpassInfo({GraphicsRenderPassTargetDesc(exposureRt)});
+
+			rpass.newTextureDependency(m_runCtx.m_pyramidRt, TextureUsageBit::kSrvPixel, inputTexSubresource);
+			rpass.newTextureDependency(exposureRt, TextureUsageBit::kRtvDsvWrite);
+
+			prpass = &rpass;
+		}
+
+		prpass->setWork([this, exposureRt](RenderPassWorkContext& rgraphCtx) {
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+
+			cmdb.bindShaderProgram(m_exposureGrProg.get());
+
+			const TextureSubresourceDesc inputTexSubresource = TextureSubresourceDesc::surface(m_pyramidTex->getMipmapCount() - 1, 0, 0);
+
+			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindSrv(0, 0, m_runCtx.m_pyramidRt, inputTexSubresource);
+			rgraphCtx.bindUav(0, 0, getRenderer().getTonemapping().getRt());
+
+			const Vec4 consts(g_bloomThresholdCVar, g_bloomScaleCVar, 0.0f, 0.0f);
+			cmdb.setFastConstants(&consts, sizeof(consts));
+
+			if(g_preferComputeCVar)
+			{
+				rgraphCtx.bindUav(1, 0, exposureRt);
+
+				dispatchPPCompute(cmdb, 8, 8, m_exposureRtDesc.m_width, m_exposureRtDesc.m_height);
+			}
+			else
+			{
+				cmdb.setViewport(0, 0, m_exposureRtDesc.m_width, m_exposureRtDesc.m_height);
+
+				cmdb.draw(PrimitiveTopology::kTriangles, 3);
+			}
+		});
+	}
+
+	// Upscale & SSLF pass
+	RenderTargetHandle upscaledRt;
+	{
+		// Ask for render target
+		upscaledRt = rgraph.newRenderTarget(m_finalRtDesc);
+		m_runCtx.m_finalRt = upscaledRt;
+
+		// Set the render pass
+		RenderPassBase* prpass;
+		if(preferCompute)
+		{
+			NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("Bloom Upscale");
+
+			rpass.newTextureDependency(exposureRt, TextureUsageBit::kSrvCompute);
+			rpass.newTextureDependency(upscaledRt, TextureUsageBit::kUavCompute);
+
+			prpass = &rpass;
+		}
+		else
+		{
+			GraphicsRenderPass& rpass = rgraph.newGraphicsRenderPass("Bloom Upscale");
+			rpass.setRenderpassInfo({GraphicsRenderPassTargetDesc(upscaledRt)});
+
+			rpass.newTextureDependency(exposureRt, TextureUsageBit::kSrvPixel);
+			rpass.newTextureDependency(upscaledRt, TextureUsageBit::kRtvDsvWrite);
+
+			prpass = &rpass;
+		}
+
+		prpass->setWork([this, exposureRt, upscaledRt](RenderPassWorkContext& rgraphCtx) {
+			CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
+
+			cmdb.bindShaderProgram(m_upscaleGrProg.get());
+
+			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
+			rgraphCtx.bindSrv(0, 0, exposureRt);
+			cmdb.bindSrv(1, 0, TextureView(&m_lensDirtImg->getTexture(), TextureSubresourceDesc::all()));
+
+			if(g_preferComputeCVar)
+			{
+				rgraphCtx.bindUav(0, 0, upscaledRt);
+
+				dispatchPPCompute(cmdb, 8, 8, m_finalRtDesc.m_width, m_finalRtDesc.m_height);
+			}
+			else
+			{
+				cmdb.setViewport(0, 0, m_finalRtDesc.m_width, m_finalRtDesc.m_height);
+
+				cmdb.draw(PrimitiveTopology::kTriangles, 3);
+			}
+		});
+	}
+}
+
+} // end namespace anki

+ 72 - 0
AnKi/Renderer/Bloom2.h

@@ -0,0 +1,72 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <AnKi/Renderer/RendererObject.h>
+
+namespace anki {
+
+/// @addtogroup renderer
+/// @{
+
+inline NumericCVar<F32> g_bloomThresholdCVar("R", "BloomThreshold", 2.5f, 0.0f, 256.0f, "Bloom threshold");
+inline NumericCVar<F32> g_bloomScaleCVar("R", "BloomScale", 2.5f, 0.0f, 256.0f, "Bloom scale");
+inline NumericCVar<U32> g_bloomPyramidLowLimit("R", "BloomPyramidLowLimit", 32, 8, 1024, "Downscale the boom pyramid up to that size");
+inline NumericCVar<U32> g_bloomUpscaleDivisor("R", "BloomUpscaleDivisor", 4, 1, 1024, "Defines the resolution of the final bloom result");
+
+/// Contains multiple post-process passes that operate on the HDR output.
+class Bloom2 : public RendererObject
+{
+public:
+	Error init();
+
+	void importRenderTargets(RenderingContext& ctx);
+
+	void populateRenderGraph(RenderingContext& ctx);
+
+	RenderTargetHandle getPyramidRt() const
+	{
+		return m_runCtx.m_pyramidRt;
+	}
+
+	UVec2 getPyramidTextureSize() const
+	{
+		return UVec2(m_pyramidTex->getWidth(), m_pyramidTex->getHeight());
+	}
+
+	U32 getPyramidTextureMipmapCount() const
+	{
+		return m_pyramidTex->getMipmapCount();
+	}
+
+	RenderTargetHandle getBloomRt() const
+	{
+		return m_runCtx.m_finalRt;
+	}
+
+private:
+	ShaderProgramResourcePtr m_prog;
+	ShaderProgramPtr m_downscaleGrProg;
+	ShaderProgramPtr m_exposureGrProg;
+	ShaderProgramPtr m_upscaleGrProg;
+
+	TexturePtr m_pyramidTex;
+
+	RenderTargetDesc m_exposureRtDesc;
+	RenderTargetDesc m_finalRtDesc;
+
+	ImageResourcePtr m_lensDirtImg;
+
+	class
+	{
+	public:
+		RenderTargetHandle m_pyramidRt;
+		RenderTargetHandle m_finalRt;
+	} m_runCtx;
+};
+/// @}
+
+} // end namespace anki

+ 1 - 1
AnKi/Renderer/Common.h

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

+ 3 - 6
AnKi/Renderer/Dbg.cpp

@@ -15,15 +15,12 @@
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/Enum.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Collision/ConvexHullShape.h>
 #include <AnKi/Physics/PhysicsWorld.h>
 
 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()
 {
 }
@@ -148,7 +145,7 @@ void Dbg::drawNonRenderable(GpuSceneNonRenderableObjectType type, U32 objCount,
 void Dbg::run(RenderPassWorkContext& rgraphCtx, const RenderingContext& ctx)
 {
 	ANKI_TRACE_SCOPED_EVENT(Dbg);
-	ANKI_ASSERT(g_dbgCVar.get());
+	ANKI_ASSERT(g_dbgCVar);
 
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
@@ -231,7 +228,7 @@ void Dbg::populateRenderGraph(RenderingContext& ctx)
 {
 	ANKI_TRACE_SCOPED_EVENT(Dbg);
 
-	if(!g_dbgCVar.get())
+	if(!g_dbgCVar)
 	{
 		return;
 	}

+ 3 - 3
AnKi/Renderer/Dbg.h

@@ -11,12 +11,12 @@
 
 namespace anki {
 
-// Forward
-extern BoolCVar g_dbgCVar;
-
 /// @addtogroup renderer
 /// @{
 
+inline BoolCVar g_dbgCVar("R", "Dbg", false, "Enable or not debug visualization");
+inline BoolCVar g_dbgPhysicsCVar("R", "DbgPhysics", false, "Enable or not physics debug visualization");
+
 /// Debugging stage
 class Dbg : public RendererObject
 {

+ 3 - 3
AnKi/Renderer/DepthDownscale.cpp

@@ -6,7 +6,7 @@
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 
 #if ANKI_COMPILER_GCC_COMPATIBLE
@@ -43,7 +43,7 @@ Error DepthDownscale::initInternal()
 
 	ANKI_R_LOGV("Initializing HiZ. Mip count %u, last mip size %ux%u", m_mipCount, lastMipSize.x(), lastMipSize.y());
 
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 
 	// Create RT descr
 	{
@@ -87,7 +87,7 @@ void DepthDownscale::populateRenderGraph(RenderingContext& ctx)
 
 	m_runCtx.m_rt = rgraph.newRenderTarget(m_rtDescr);
 
-	if(g_preferComputeCVar.get())
+	if(g_preferComputeCVar)
 	{
 		// Do it with compute
 

+ 0 - 152
AnKi/Renderer/DownscaleBlur.cpp

@@ -1,152 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Renderer/DownscaleBlur.h>
-#include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/LightShading.h>
-#include <AnKi/Renderer/Tonemapping.h>
-#include <AnKi/Core/CVarSet.h>
-#include <AnKi/Util/Tracer.h>
-
-namespace anki {
-
-Error DownscaleBlur::init()
-{
-	const Error err = initInternal();
-	if(err)
-	{
-		ANKI_R_LOGE("Failed to initialize downscale blur");
-	}
-
-	return err;
-}
-
-Error DownscaleBlur::initInternal()
-{
-	m_passCount =
-		computeMaxMipmapCount2d(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(), kDownscaleBurDownTo) - 1;
-
-	const UVec2 rez = getRenderer().getInternalResolution() / 2;
-	ANKI_R_LOGV("Initializing downscale pyramid. Resolution %ux%u, mip count %u", rez.x(), rez.y(), m_passCount);
-
-	const Bool preferCompute = g_preferComputeCVar.get();
-
-	// Create the miped texture
-	TextureInitInfo texinit = getRenderer().create2DRenderTargetDescription(rez.x(), rez.y(), getRenderer().getHdrFormat(), "DownscaleBlur");
-	texinit.m_usage = TextureUsageBit::kSrvPixel | TextureUsageBit::kSrvCompute;
-	if(preferCompute)
-	{
-		texinit.m_usage |= TextureUsageBit::kUavCompute;
-	}
-	else
-	{
-		texinit.m_usage |= TextureUsageBit::kRtvDsvWrite;
-	}
-	texinit.m_mipmapCount = U8(m_passCount);
-	m_rtTex = getRenderer().createAndClearRenderTarget(texinit, TextureUsageBit::kSrvCompute);
-
-	// Shader programs
-	ANKI_CHECK(loadShaderProgram("ShaderBinaries/DownscaleBlur.ankiprogbin", m_prog, m_grProg));
-
-	return Error::kNone;
-}
-
-void DownscaleBlur::importRenderTargets(RenderingContext& ctx)
-{
-	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
-	m_runCtx.m_rt = rgraph.importRenderTarget(m_rtTex.get(), TextureUsageBit::kSrvCompute);
-}
-
-void DownscaleBlur::populateRenderGraph(RenderingContext& ctx)
-{
-	ANKI_TRACE_SCOPED_EVENT(DownscaleBlur);
-	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
-
-	// Create passes
-	static constexpr Array<CString, 8> passNames = {"Down/Blur #0", "Down/Blur #1", "Down/Blur #2", "Down/Blur #3",
-													"Down/Blur #4", "Down/Blur #5", "Down/Blur #6", "Down/Blur #7"};
-	const RenderTargetHandle inRt = getRenderer().getLightShading().getRt();
-
-	for(U32 i = 0; i < m_passCount; ++i)
-	{
-		RenderPassBase* ppass;
-		if(g_preferComputeCVar.get())
-		{
-			ppass = &rgraph.newNonGraphicsRenderPass(passNames[i]);
-		}
-		else
-		{
-			GraphicsRenderPass& pass = rgraph.newGraphicsRenderPass(passNames[i]);
-
-			GraphicsRenderPassTargetDesc rtInf(m_runCtx.m_rt);
-			rtInf.m_subresource.m_mipmap = i;
-			pass.setRenderpassInfo({rtInf});
-
-			ppass = &pass;
-		}
-
-		const TextureUsageBit readUsage = (g_preferComputeCVar.get()) ? TextureUsageBit::kSrvCompute : TextureUsageBit::kSrvPixel;
-		const TextureUsageBit writeUsage = (g_preferComputeCVar.get()) ? TextureUsageBit::kUavCompute : TextureUsageBit::kRtvDsvWrite;
-
-		if(i > 0)
-		{
-			const TextureSubresourceDesc sampleSubresource = TextureSubresourceDesc::surface(i - 1, 0, 0);
-			const TextureSubresourceDesc renderSubresource = TextureSubresourceDesc::surface(i, 0, 0);
-
-			ppass->newTextureDependency(m_runCtx.m_rt, writeUsage, renderSubresource);
-			ppass->newTextureDependency(m_runCtx.m_rt, readUsage, sampleSubresource);
-		}
-		else
-		{
-			ppass->newTextureDependency(m_runCtx.m_rt, writeUsage, TextureSubresourceDesc::firstSurface());
-			ppass->newTextureDependency(inRt, readUsage);
-		}
-
-		ppass->setWork([this, i](RenderPassWorkContext& rgraphCtx) {
-			run(i, rgraphCtx);
-		});
-	}
-}
-
-void DownscaleBlur::run(U32 passIdx, RenderPassWorkContext& rgraphCtx)
-{
-	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-
-	cmdb.bindShaderProgram(m_grProg.get());
-
-	const U32 vpWidth = m_rtTex->getWidth() >> passIdx;
-	const U32 vpHeight = m_rtTex->getHeight() >> passIdx;
-
-	cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearClamp.get());
-
-	if(passIdx > 0)
-	{
-		rgraphCtx.bindSrv(0, 0, m_runCtx.m_rt, TextureSubresourceDesc::surface(passIdx - 1, 0, 0));
-	}
-	else
-	{
-		rgraphCtx.bindSrv(0, 0, getRenderer().getLightShading().getRt());
-	}
-
-	rgraphCtx.bindUav(0, 0, getRenderer().getTonemapping().getRt());
-
-	if(g_preferComputeCVar.get())
-	{
-		const Vec4 fbSize(F32(vpWidth), F32(vpHeight), 0.0f, 0.0f);
-		cmdb.setFastConstants(&fbSize, sizeof(fbSize));
-
-		rgraphCtx.bindUav(1, 0, m_runCtx.m_rt, TextureSubresourceDesc::surface(passIdx, 0, 0));
-
-		dispatchPPCompute(cmdb, 8, 8, vpWidth, vpHeight);
-	}
-	else
-	{
-		cmdb.setViewport(0, 0, vpWidth, vpHeight);
-
-		cmdb.draw(PrimitiveTopology::kTriangles, 3);
-	}
-}
-
-} // end namespace anki

+ 0 - 71
AnKi/Renderer/DownscaleBlur.h

@@ -1,71 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <AnKi/Renderer/RendererObject.h>
-
-namespace anki {
-
-/// @addtogroup renderer
-/// @{
-
-/// Downsample the IS and blur it at the same time.
-class DownscaleBlur : public RendererObject
-{
-public:
-	DownscaleBlur() = default;
-
-	~DownscaleBlur() = default;
-
-	Error init();
-
-	/// Import render targets
-	void importRenderTargets(RenderingContext& ctx);
-
-	/// Populate the rendergraph.
-	void populateRenderGraph(RenderingContext& ctx);
-
-	U32 getPassWidth(U32 pass) const
-	{
-		return m_rtTex->getWidth() >> min(pass, m_passCount - 1);
-	}
-
-	U32 getPassHeight(U32 pass) const
-	{
-		return m_rtTex->getHeight() >> min(pass, m_passCount - 1);
-	}
-
-	U32 getMipmapCount() const
-	{
-		return m_passCount;
-	}
-
-	RenderTargetHandle getRt() const
-	{
-		return m_runCtx.m_rt;
-	}
-
-private:
-	U32 m_passCount = 0; ///< It's also the mip count of the m_rtTex.
-
-	TexturePtr m_rtTex;
-
-	ShaderProgramResourcePtr m_prog;
-	ShaderProgramPtr m_grProg;
-
-	class
-	{
-	public:
-		RenderTargetHandle m_rt;
-	} m_runCtx;
-
-	Error initInternal();
-
-	void run(U32 passIdx, RenderPassWorkContext& rgraphCtx);
-};
-/// @}
-
-} // end namespace anki

+ 9 - 13
AnKi/Renderer/FinalComposite.cpp

@@ -5,24 +5,20 @@
 
 #include <AnKi/Renderer/FinalComposite.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Renderer/Bloom.h>
+#include <AnKi/Renderer/Bloom2.h>
 #include <AnKi/Renderer/Scale.h>
 #include <AnKi/Renderer/Tonemapping.h>
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/Dbg.h>
-#include <AnKi/Renderer/DownscaleBlur.h>
 #include <AnKi/Renderer/UiStage.h>
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 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,8 +29,8 @@ Error FinalComposite::initInternal()
 	for(MutatorValue dbg = 0; dbg < 2; ++dbg)
 	{
 		ANKI_CHECK(loadShaderProgram("ShaderBinaries/FinalComposite.ankiprogbin",
-									 {{"FILM_GRAIN", (g_filmGrainStrengthCVar.get() > 0.0) ? 1 : 0}, {"BLOOM_ENABLED", 1}, {"DBG_ENABLED", dbg}},
-									 m_prog, m_grProgs[dbg]));
+									 {{"FILM_GRAIN", (g_filmGrainStrengthCVar > 0.0) ? 1 : 0}, {"BLOOM_ENABLED", 1}, {"DBG_ENABLED", dbg}}, m_prog,
+									 m_grProgs[dbg]));
 	}
 
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/VisualizeRenderTarget.ankiprogbin", m_defaultVisualizeRenderTargetProg,
@@ -94,13 +90,13 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 
 	pass.newTextureDependency(outRt, TextureUsageBit::kRtvDsvWrite);
 
-	if(g_dbgCVar.get())
+	if(g_dbgCVar)
 	{
 		pass.newTextureDependency(getRenderer().getDbg().getRt(), TextureUsageBit::kSrvPixel);
 	}
 
 	pass.newTextureDependency(getRenderer().getScale().getTonemappedRt(), TextureUsageBit::kSrvPixel);
-	pass.newTextureDependency(getRenderer().getBloom().getRt(), TextureUsageBit::kSrvPixel);
+	pass.newTextureDependency(getRenderer().getBloom2().getBloomRt(), TextureUsageBit::kSrvPixel);
 	pass.newTextureDependency(getRenderer().getMotionVectors().getMotionVectorsRt(), TextureUsageBit::kSrvPixel);
 	pass.newTextureDependency(getRenderer().getGBuffer().getDepthRt(), TextureUsageBit::kSrvPixel);
 
@@ -122,7 +118,7 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 		ANKI_TRACE_SCOPED_EVENT(FinalComposite);
 
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-		const Bool dbgEnabled = g_dbgCVar.get();
+		const Bool dbgEnabled = g_dbgCVar;
 
 		Array<RenderTargetHandle, kMaxDebugRenderTargets> dbgRts;
 		ShaderProgramPtr optionalDebugProgram;
@@ -151,7 +147,7 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 
 			rgraphCtx.bindSrv(0, 0, getRenderer().getScale().getTonemappedRt());
 
-			rgraphCtx.bindSrv(1, 0, getRenderer().getBloom().getRt());
+			rgraphCtx.bindSrv(1, 0, getRenderer().getBloom2().getBloomRt());
 			cmdb.bindSrv(2, 0, TextureView(&m_lut->getTexture(), TextureSubresourceDesc::all()));
 			rgraphCtx.bindSrv(3, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
 			rgraphCtx.bindSrv(4, 0, getRenderer().getGBuffer().getDepthRt());
@@ -161,7 +157,7 @@ void FinalComposite::populateRenderGraph(RenderingContext& ctx)
 				rgraphCtx.bindSrv(5, 0, getRenderer().getDbg().getRt());
 			}
 
-			const UVec4 pc(g_motionBlurSamplesCVar.get(), floatBitsToUint(g_filmGrainStrengthCVar.get()), getRenderer().getFrameCount() & kMaxU32, 0);
+			const UVec4 pc(g_motionBlurSamplesCVar, floatBitsToUint(g_filmGrainStrengthCVar), getRenderer().getFrameCount() & kMaxU32, 0);
 			cmdb.setFastConstants(&pc, sizeof(pc));
 		}
 		else

+ 3 - 0
AnKi/Renderer/FinalComposite.h

@@ -13,6 +13,9 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U32> g_motionBlurSamplesCVar("R", "MotionBlurSamples", 32, 0, 2048, "Max motion blur samples");
+inline NumericCVar<F32> g_filmGrainStrengthCVar("R", "FilmGrainStrength", 16.0f, 0.0f, 250.0f, "Film grain strength");
+
 /// Post-processing stage.
 class FinalComposite : public RendererObject
 {

+ 2 - 2
AnKi/Renderer/ForwardShading.cpp

@@ -27,7 +27,7 @@ void ForwardShading::populateRenderGraph(RenderingContext& ctx)
 	m_runCtx = {};
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
 
-	const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+	const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 
 	FrustumGpuVisibilityInput visIn;
 	visIn.m_passesName = "FW shading";
@@ -36,7 +36,7 @@ void ForwardShading::populateRenderGraph(RenderingContext& ctx)
 	visIn.m_lodReferencePoint = ctx.m_matrices.m_cameraTransform.getTranslationPart().xyz();
 	visIn.m_lodDistances = lodDistances;
 	visIn.m_rgraph = &rgraph;
-	visIn.m_gatherAabbIndices = g_dbgCVar.get();
+	visIn.m_gatherAabbIndices = g_dbgCVar;
 	RenderTargetHandle hzb = getRenderer().getGBuffer().getHzbRt();
 	visIn.m_hzbRt = &hzb;
 	visIn.m_viewportSize = getRenderer().getInternalResolution();

+ 6 - 12
AnKi/Renderer/GBuffer.cpp

@@ -12,19 +12,13 @@
 #include <AnKi/Renderer/Utils/HzbGenerator.h>
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Core/App.h>
 #include <AnKi/Scene/Components/GlobalIlluminationProbeComponent.h>
 #include <AnKi/Scene/Components/ReflectionProbeComponent.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");
-static BoolCVar g_visualizeGiProbes(CVarSubsystem::kRenderer, "VisualizeGiProbes", false, "Visualize GI probes");
-static BoolCVar g_visualizeReflectionProbes(CVarSubsystem::kRenderer, "VisualizeReflProbes", false, "Visualize reflection probes");
-
 GBuffer::~GBuffer()
 {
 }
@@ -69,7 +63,7 @@ Error GBuffer::initInternal()
 		const TextureUsageBit usage = TextureUsageBit::kSrvCompute | TextureUsageBit::kUavCompute | TextureUsageBit::kSrvGeometry;
 
 		TextureInitInfo texinit =
-			getRenderer().create2DRenderTargetInitInfo(g_hzbWidthCVar.get(), g_hzbHeightCVar.get(), Format::kR32_Sfloat, usage, "GBuffer HZB");
+			getRenderer().create2DRenderTargetInitInfo(g_hzbWidthCVar, g_hzbHeightCVar, 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};
@@ -118,7 +112,7 @@ void GBuffer::populateRenderGraph(RenderingContext& ctx)
 	FrustumGpuVisibilityInput visIn;
 	{
 		const CommonMatrices& matrices = ctx.m_matrices;
-		const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+		const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 
 		visIn.m_passesName = "GBuffer";
 		visIn.m_technique = RenderingTechnique::kGBuffer;
@@ -127,7 +121,7 @@ void GBuffer::populateRenderGraph(RenderingContext& ctx)
 		visIn.m_lodDistances = lodDistances;
 		visIn.m_rgraph = &rgraph;
 		visIn.m_hzbRt = &m_runCtx.m_hzbRt;
-		visIn.m_gatherAabbIndices = g_dbgCVar.get();
+		visIn.m_gatherAabbIndices = g_dbgCVar;
 		visIn.m_viewportSize = getRenderer().getInternalResolution();
 		visIn.m_twoPhaseOcclusionCulling = getRenderer().getMeshletRenderingType() != MeshletRenderingType::kNone;
 
@@ -221,7 +215,7 @@ void GBuffer::populateRenderGraph(RenderingContext& ctx)
 				};
 
 				// Visualize GI probes
-				if(g_visualizeGiProbes.get() && GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementCount())
+				if(g_visualizeGiProbesCVar && GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getElementCount())
 				{
 					cmdb.bindShaderProgram(m_visualizeGiProbeGrProg.get());
 					cmdb.bindSrv(0, 0, GpuSceneArrays::GlobalIlluminationProbe::getSingleton().getBufferView());
@@ -243,7 +237,7 @@ void GBuffer::populateRenderGraph(RenderingContext& ctx)
 				}
 
 				// Visualize refl probes
-				if(g_visualizeReflectionProbes.get() && GpuSceneArrays::ReflectionProbe::getSingleton().getElementCount())
+				if(g_visualizeReflectionProbesCVar && GpuSceneArrays::ReflectionProbe::getSingleton().getElementCount())
 				{
 					cmdb.bindShaderProgram(m_visualizeReflProbeGrProg.get());
 					cmdb.bindSrv(0, 0, GpuSceneArrays::ReflectionProbe::getSingleton().getBufferView());

+ 6 - 0
AnKi/Renderer/GBuffer.h

@@ -13,6 +13,12 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U32> g_hzbWidthCVar("R", "HzbWidth", 512, 16, 4 * 1024, "HZB map width");
+inline NumericCVar<U32> g_hzbHeightCVar("R", "HzbHeight", 256, 16, 4 * 1024, "HZB map height");
+inline BoolCVar g_gbufferVrsCVar("R", "GBufferVrs", false, "Enable VRS in GBuffer");
+inline BoolCVar g_visualizeGiProbesCVar("R", "VisualizeGiProbes", false, "Visualize GI probes");
+inline BoolCVar g_visualizeReflectionProbesCVar("R", "VisualizeReflProbes", false, "Visualize reflection probes");
+
 /// G buffer stage. It populates the G buffer
 class GBuffer : public RendererObject
 {

+ 5 - 10
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -11,7 +11,7 @@
 #include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Scene/Components/GlobalIlluminationProbeComponent.h>
 #include <AnKi/Scene/Components/LightComponent.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Core/StatsSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Collision/Aabb.h>
@@ -20,11 +20,6 @@
 
 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");
-
 static StatCounter g_giProbeRenderCountStatVar(StatCategory::kRenderer, "GI probes rendered", StatFlag::kMainThreadUpdates);
 static StatCounter g_giProbeCellsRenderCountStatVar(StatCategory::kRenderer, "GI probes cells rendered", StatFlag::kMainThreadUpdates);
 
@@ -55,7 +50,7 @@ Error IndirectDiffuseProbes::init()
 
 Error IndirectDiffuseProbes::initInternal()
 {
-	m_tileSize = g_indirectDiffuseProbeTileResolutionCVar.get();
+	m_tileSize = g_indirectDiffuseProbeTileResolutionCVar;
 
 	ANKI_CHECK(initGBuffer());
 	ANKI_CHECK(initLightShading());
@@ -95,7 +90,7 @@ Error IndirectDiffuseProbes::initGBuffer()
 
 Error IndirectDiffuseProbes::initShadowMapping()
 {
-	const U32 resolution = g_indirectDiffuseProbeShadowMapResolutionCVar.get();
+	const U32 resolution = g_indirectDiffuseProbeShadowMapResolutionCVar;
 	ANKI_ASSERT(resolution > 8);
 
 	// RT descr
@@ -204,7 +199,7 @@ void IndirectDiffuseProbes::populateRenderGraph(RenderingContext& rctx)
 					Transform(cellCenter.xyz0(), Frustum::getOmnidirectionalFrustumRotations()[f], Vec4(1.0f, 1.0f, 1.0f, 0.0f)));
 				frustum.update();
 
-				Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+				Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 
 				FrustumGpuVisibilityInput visIn;
 				visIn.m_passesName = generateTempPassName("GI: GBuffer cell:%u face:%u", cellIdx, f);
@@ -282,7 +277,7 @@ void IndirectDiffuseProbes::populateRenderGraph(RenderingContext& rctx)
 
 				cascadeViewProjMat = cascadeProjMat * Mat4(cascadeViewMat, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
 
-				Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+				Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 
 				FrustumGpuVisibilityInput visIn;
 				visIn.m_passesName = generateTempPassName("GI: Shadows cell:%u face:%u", cellIdx, f);

+ 5 - 0
AnKi/Renderer/IndirectDiffuseProbes.h

@@ -14,6 +14,11 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U32> g_indirectDiffuseProbeTileResolutionCVar("R", "IndirectDiffuseProbeTileResolution", (ANKI_PLATFORM_MOBILE) ? 16 : 32, 8, 32,
+																 "GI tile resolution");
+inline NumericCVar<U32> g_indirectDiffuseProbeShadowMapResolutionCVar("R", "IndirectDiffuseProbeShadowMapResolution", 128, 4, 2048,
+																	  "GI shadowmap resolution");
+
 /// Ambient global illumination passes.
 ///
 /// It builds a volume clipmap with ambient GI information.

+ 2 - 6
AnKi/Renderer/LensFlare.cpp

@@ -6,7 +6,7 @@
 #include <AnKi/Renderer/LensFlare.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/Renderer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Core/GpuMemory/GpuVisibleTransientMemoryPool.h>
 #include <AnKi/Util/Functions.h>
 #include <AnKi/Scene/Components/LensFlareComponent.h>
@@ -14,10 +14,6 @@
 
 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();
@@ -33,7 +29,7 @@ Error LensFlare::initInternal()
 {
 	ANKI_R_LOGV("Initializing lens flare");
 
-	m_maxSpritesPerFlare = g_lensFlareMaxSpritesPerFlareCVar.get();
+	m_maxSpritesPerFlare = g_lensFlareMaxSpritesPerFlareCVar;
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/LensFlareSprite.ankiprogbin", m_realProg, m_realGrProg));
 
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/LensFlareUpdateIndirectInfo.ankiprogbin", m_updateIndirectBuffProg, m_updateIndirectBuffGrProg));

+ 3 - 0
AnKi/Renderer/LensFlare.h

@@ -14,6 +14,9 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U8> g_lensFlareMaxSpritesPerFlareCVar("R", "LensFlareMaxSpritesPerFlare", 8, 4, 255, "Max sprites per lens flare");
+inline NumericCVar<U8> g_lensFlareMaxFlaresCVar("R", "LensFlareMaxFlares", 16, 8, 255, "Max flare count");
+
 /// Lens flare rendering pass. Part of forward shading.
 class LensFlare : public RendererObject
 {

+ 3 - 3
AnKi/Renderer/LightShading.cpp

@@ -18,7 +18,7 @@
 #include <AnKi/Renderer/ClusterBinning.h>
 #include <AnKi/Renderer/Ssao.h>
 #include <AnKi/Renderer/Ssr.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Scene/Components/SkyboxComponent.h>
 #include <AnKi/Scene/Components/LightComponent.h>
@@ -95,7 +95,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 && g_vrsCVar.get();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar;
 	if(enableVrs)
 	{
 		// Just set some low value, the attachment will take over
@@ -248,7 +248,7 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 	ANKI_TRACE_SCOPED_EVENT(LightShading);
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
 
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar;
 
 	// Create RT
 	m_runCtx.m_rt = rgraph.newRenderTarget(m_lightShading.m_rtDescr);

+ 4 - 4
AnKi/Renderer/MotionVectors.cpp

@@ -6,7 +6,7 @@
 #include <AnKi/Renderer/MotionVectors.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/GBuffer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Window/Input.h>
 
@@ -47,7 +47,7 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 	RenderPassBase* ppass;
 	TextureUsageBit readUsage;
 	TextureUsageBit writeUsage;
-	if(g_preferComputeCVar.get())
+	if(g_preferComputeCVar)
 	{
 		NonGraphicsRenderPass& pass = rgraph.newNonGraphicsRenderPass("MotionVectors");
 
@@ -88,12 +88,12 @@ void MotionVectors::populateRenderGraph(RenderingContext& ctx)
 		pc->m_currentInvViewProjMat = ctx.m_matrices.m_invertedViewProjection;
 		pc->m_prevViewProjMat = ctx.m_prevMatrices.m_viewProjection;
 
-		if(g_preferComputeCVar.get())
+		if(g_preferComputeCVar)
 		{
 			rgraphCtx.bindUav(0, 0, m_runCtx.m_motionVectorsRtHandle);
 		}
 
-		if(g_preferComputeCVar.get())
+		if(g_preferComputeCVar)
 		{
 			dispatchPPCompute(cmdb, 8, 8, getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y());
 		}

+ 7 - 11
AnKi/Renderer/ProbeReflections.cpp

@@ -12,7 +12,7 @@
 #include <AnKi/Renderer/PrimaryNonRenderableVisibility.h>
 #include <AnKi/Renderer/Utils/MipmapGenerator.h>
 #include <AnKi/Renderer/Utils/Drawer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Core/StatsSet.h>
 #include <AnKi/Resource/MeshResource.h>
@@ -24,10 +24,6 @@
 
 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");
 static StatCounter g_probeReflectionCountStatVar(StatCategory::kRenderer, "Reflection probes rendered", StatFlag::kMainThreadUpdates);
 
 Error ProbeReflections::init()
@@ -66,7 +62,7 @@ Error ProbeReflections::initInternal()
 
 Error ProbeReflections::initGBuffer()
 {
-	m_gbuffer.m_tileSize = g_reflectionProbeResolutionCVar.get();
+	m_gbuffer.m_tileSize = g_reflectionProbeResolutionCVar;
 
 	// Create RT descriptions
 	{
@@ -96,7 +92,7 @@ Error ProbeReflections::initGBuffer()
 
 Error ProbeReflections::initLightShading()
 {
-	m_lightShading.m_tileSize = g_reflectionProbeResolutionCVar.get();
+	m_lightShading.m_tileSize = g_reflectionProbeResolutionCVar;
 	m_lightShading.m_mipCount = U8(computeMaxMipmapCount2d(m_lightShading.m_tileSize, m_lightShading.m_tileSize, 8));
 
 	// Init deferred
@@ -107,7 +103,7 @@ Error ProbeReflections::initLightShading()
 
 Error ProbeReflections::initIrradiance()
 {
-	m_irradiance.m_workgroupSize = g_probeReflectionIrradianceResolutionCVar.get();
+	m_irradiance.m_workgroupSize = g_probeReflectionIrradianceResolutionCVar;
 
 	// Create prog
 	{
@@ -137,7 +133,7 @@ Error ProbeReflections::initIrradianceToRefl()
 
 Error ProbeReflections::initShadowMapping()
 {
-	const U32 resolution = g_probeReflectionShadowMapResolutionCVar.get();
+	const U32 resolution = g_probeReflectionShadowMapResolutionCVar;
 	ANKI_ASSERT(resolution > 8);
 
 	// RT descr
@@ -204,7 +200,7 @@ void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
 				Transform(probeToRefresh->getWorldPosition().xyz0(), Frustum::getOmnidirectionalFrustumRotations()[f], Vec4(1.0f, 1.0f, 1.0f, 0.0f)));
 			frustum.update();
 
-			Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+			Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 
 			FrustumGpuVisibilityInput visIn;
 			visIn.m_passesName = generateTempPassName("Cube refl: GBuffer face:%u", f);
@@ -280,7 +276,7 @@ void ProbeReflections::populateRenderGraph(RenderingContext& rctx)
 
 			cascadeViewProjMat = cascadeProjMat * Mat4(cascadeViewMat, Vec4(0.0f, 0.0f, 0.0f, 1.0f));
 
-			Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+			Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 
 			FrustumGpuVisibilityInput visIn;
 			visIn.m_passesName = generateTempPassName("Cube refl: Shadows face:%u", f);

+ 5 - 0
AnKi/Renderer/ProbeReflections.h

@@ -14,6 +14,11 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U32> g_probeReflectionIrradianceResolutionCVar("R", "ProbeReflectionIrradianceResolution", 16, 4, 2048,
+																  "Reflection probe irradiance resolution");
+inline NumericCVar<U32> g_probeReflectionShadowMapResolutionCVar("R", "ProbeReflectionShadowMapResolution", 64, 4, 2048,
+																 "Reflection probe shadow resolution");
+
 /// Probe reflections.
 class ProbeReflections : public RendererObject
 {

+ 16 - 47
AnKi/Renderer/Renderer.cpp

@@ -5,7 +5,7 @@
 
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/HighRezTimer.h>
 #include <AnKi/Collision/Aabb.h>
 #include <AnKi/Collision/Plane.h>
@@ -15,6 +15,7 @@
 #include <AnKi/Scene/Components/CameraComponent.h>
 #include <AnKi/Scene/Components/LightComponent.h>
 #include <AnKi/Core/StatsSet.h>
+#include <AnKi/Core/App.h>
 
 #include <AnKi/Renderer/ProbeReflections.h>
 #include <AnKi/Renderer/GBuffer.h>
@@ -22,12 +23,11 @@
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/ShadowMapping.h>
 #include <AnKi/Renderer/FinalComposite.h>
-#include <AnKi/Renderer/Bloom.h>
+#include <AnKi/Renderer/Bloom2.h>
 #include <AnKi/Renderer/Tonemapping.h>
 #include <AnKi/Renderer/ForwardShading.h>
 #include <AnKi/Renderer/LensFlare.h>
 #include <AnKi/Renderer/Dbg.h>
-#include <AnKi/Renderer/DownscaleBlur.h>
 #include <AnKi/Renderer/VolumetricFog.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/TemporalAA.h>
@@ -53,39 +53,9 @@
 
 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_zSplitCountCVar(CVarSubsystem::kRenderer, "ZSplitCount", 64, 8, kMaxZsplitCount, "Clusterer number of Z splits");
-static NumericCVar<U8> g_textureAnisotropyCVar(CVarSubsystem::kRenderer, "TextureAnisotropy", (ANKI_PLATFORM_MOBILE) ? 1 : 16, 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");
-BoolCVar g_rayTracedShadowsCVar(CVarSubsystem::kRenderer, "RayTracedShadows", true,
-								"Enable or not ray traced shadows. Ignored if RT is not supported");
-NumericCVar<U8> g_shadowCascadeCountCVar(CVarSubsystem::kRenderer, "ShadowCascadeCount", (ANKI_PLATFORM_MOBILE) ? 3 : kMaxShadowCascades, 1,
-										 kMaxShadowCascades, "Max number of shadow cascades for directional lights");
-NumericCVar<F32> g_shadowCascade0DistanceCVar(CVarSubsystem::kRenderer, "ShadowCascade0Distance", 18.0, 1.0, kMaxF32,
-											  "The distance of the 1st cascade");
-NumericCVar<F32> g_shadowCascade1DistanceCVar(CVarSubsystem::kRenderer, "ShadowCascade1Distance", (ANKI_PLATFORM_MOBILE) ? 80.0f : 40.0, 1.0, kMaxF32,
-											  "The distance of the 2nd cascade");
-NumericCVar<F32> g_shadowCascade2DistanceCVar(CVarSubsystem::kRenderer, "ShadowCascade2Distance", (ANKI_PLATFORM_MOBILE) ? 150.0f : 80.0, 1.0,
-											  kMaxF32, "The distance of the 3rd cascade");
-NumericCVar<F32> g_shadowCascade3DistanceCVar(CVarSubsystem::kRenderer, "ShadowCascade3Distance", 200.0, 1.0, kMaxF32,
-											  "The distance of the 4th cascade");
-NumericCVar<F32> g_lod0MaxDistanceCVar(CVarSubsystem::kRenderer, "Lod0MaxDistance", 20.0f, 1.0f, kMaxF32,
-									   "Distance that will be used to calculate the LOD 0");
-NumericCVar<F32> g_lod1MaxDistanceCVar(CVarSubsystem::kRenderer, "Lod1MaxDistance", 40.0f, 2.0f, kMaxF32,
-									   "Distance that will be used to calculate the LOD 1");
-
 static StatCounter g_primitivesDrawnStatVar(StatCategory::kRenderer, "Primitives drawn", StatFlag::kMainThreadUpdates | StatFlag::kZeroEveryFrame);
 static StatCounter g_rendererCpuTimeStatVar(StatCategory::kTime, "Renderer",
 											StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
-StatCounter g_rendererGpuTimeStatVar(StatCategory::kTime, "GPU frame", StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
 
 /// Generate a Halton jitter in [-0.5, 0.5]
 static Vec2 generateJitter(U32 frame)
@@ -153,11 +123,11 @@ Error Renderer::initInternal(const RendererInitInfo& inf)
 	m_rgraph = GrManager::getSingleton().newRenderGraph();
 
 	// Set from the config
-	m_postProcessResolution = UVec2(Vec2(m_swapchainResolution) * g_renderScalingCVar.get());
+	m_postProcessResolution = UVec2(Vec2(m_swapchainResolution) * g_renderScalingCVar);
 	alignRoundDown(2, m_postProcessResolution.x());
 	alignRoundDown(2, m_postProcessResolution.y());
 
-	m_internalResolution = UVec2(Vec2(m_postProcessResolution) * g_internalRenderScalingCVar.get());
+	m_internalResolution = UVec2(Vec2(m_postProcessResolution) * g_internalRenderScalingCVar);
 	alignRoundDown(2, m_internalResolution.x());
 	alignRoundDown(2, m_internalResolution.y());
 
@@ -166,9 +136,9 @@ Error Renderer::initInternal(const RendererInitInfo& inf)
 
 	m_tileCounts.x() = (m_internalResolution.x() + kClusteredShadingTileSize - 1) / kClusteredShadingTileSize;
 	m_tileCounts.y() = (m_internalResolution.y() + kClusteredShadingTileSize - 1) / kClusteredShadingTileSize;
-	m_zSplitCount = g_zSplitCountCVar.get();
+	m_zSplitCount = g_zSplitCountCVar;
 
-	if(g_meshletRenderingCVar.get() && !GrManager::getSingleton().getDeviceCapabilities().m_meshShaders)
+	if(g_meshletRenderingCVar && !GrManager::getSingleton().getDeviceCapabilities().m_meshShaders)
 	{
 		m_meshletRenderingType = MeshletRenderingType::kSoftware;
 	}
@@ -232,14 +202,14 @@ Error Renderer::initInternal(const RendererInitInfo& inf)
 		sinit.m_addressing = SamplingAddressing::kRepeat;
 		m_samplers.m_trilinearRepeat = GrManager::getSingleton().newSampler(sinit);
 
-		if(g_textureAnisotropyCVar.get() <= 1u)
+		if(g_textureAnisotropyCVar <= 1u)
 		{
 			m_samplers.m_trilinearRepeatAniso = m_samplers.m_trilinearRepeat;
 		}
 		else
 		{
 			sinit.setName("TrilinearRepeatAniso");
-			sinit.m_anisotropyLevel = g_textureAnisotropyCVar.get();
+			sinit.m_anisotropyLevel = g_textureAnisotropyCVar;
 			m_samplers.m_trilinearRepeatAniso = GrManager::getSingleton().newSampler(sinit);
 		}
 
@@ -285,7 +255,7 @@ Error Renderer::initInternal(const RendererInitInfo& inf)
 Error Renderer::populateRenderGraph(RenderingContext& ctx)
 {
 	// Import RTs first
-	m_downscaleBlur->importRenderTargets(ctx);
+	m_bloom2->importRenderTargets(ctx);
 	m_tonemapping->importRenderTargets(ctx);
 	m_vrsSriGeneration->importRenderTargets(ctx);
 	m_gbuffer->importRenderTargets(ctx);
@@ -324,9 +294,8 @@ Error Renderer::populateRenderGraph(RenderingContext& ctx)
 	}
 	m_vrsSriGeneration->populateRenderGraph(ctx);
 	m_scale->populateRenderGraph(ctx);
-	m_downscaleBlur->populateRenderGraph(ctx);
+	m_bloom2->populateRenderGraph(ctx);
 	m_tonemapping->populateRenderGraph(ctx);
-	m_bloom->populateRenderGraph(ctx);
 	m_dbg->populateRenderGraph(ctx);
 
 	m_finalComposite->populateRenderGraph(ctx);
@@ -355,7 +324,7 @@ void Renderer::writeGlobalRendererConstants(RenderingContext& ctx, GlobalRendere
 	consts.m_zSplitCountOverFrustumLength = F32(m_zSplitCount) / (ctx.m_cameraFar - ctx.m_cameraNear);
 	consts.m_zSplitMagic.x() = (ctx.m_cameraNear - ctx.m_cameraFar) / (ctx.m_cameraNear * F32(m_zSplitCount));
 	consts.m_zSplitMagic.y() = ctx.m_cameraFar / (ctx.m_cameraNear * F32(m_zSplitCount));
-	consts.m_lightVolumeLastZSplit = min(g_volumetricLightingAccumulationFinalZSplitCVar.get() - 1, m_zSplitCount);
+	consts.m_lightVolumeLastZSplit = min(g_volumetricLightingAccumulationFinalZSplitCVar - 1, m_zSplitCount);
 
 	consts.m_reflectionProbesMipCount = F32(m_probeReflections->getReflectionTextureMipmapCount());
 
@@ -367,15 +336,15 @@ void Renderer::writeGlobalRendererConstants(RenderingContext& ctx, GlobalRendere
 	if(dirLight)
 	{
 		DirectionalLight& out = consts.m_directionalLight;
-		const U32 shadowCascadeCount = (dirLight->getShadowEnabled()) ? g_shadowCascadeCountCVar.get() : 0;
+		const U32 shadowCascadeCount = (dirLight->getShadowEnabled()) ? g_shadowCascadeCountCVar : 0;
 
 		out.m_diffuseColor = dirLight->getDiffuseColor().xyz();
 		out.m_power = dirLight->getLightPower();
 		out.m_shadowCascadeCount_31bit_active_1bit = shadowCascadeCount << 1u;
 		out.m_shadowCascadeCount_31bit_active_1bit |= 1;
 		out.m_direction = dirLight->getDirection();
-		out.m_shadowCascadeDistances = Vec4(g_shadowCascade0DistanceCVar.get(), g_shadowCascade1DistanceCVar.get(),
-											g_shadowCascade2DistanceCVar.get(), g_shadowCascade3DistanceCVar.get());
+		out.m_shadowCascadeDistances =
+			Vec4(g_shadowCascade0DistanceCVar, g_shadowCascade1DistanceCVar, g_shadowCascade2DistanceCVar, g_shadowCascade3DistanceCVar);
 
 		for(U cascade = 0; cascade < shadowCascadeCount; ++cascade)
 		{
@@ -630,7 +599,7 @@ void Renderer::setCurrentDebugRenderTarget(CString rtName)
 Format Renderer::getHdrFormat() const
 {
 	Format out;
-	if(!g_highQualityHdrCVar.get())
+	if(!g_highQualityHdrCVar)
 	{
 		out = Format::kB10G11R11_Ufloat_Pack32;
 	}

+ 26 - 15
AnKi/Renderer/Renderer.h

@@ -13,24 +13,35 @@
 
 namespace anki {
 
-// Forward
-extern BoolCVar g_vrsCVar;
-extern BoolCVar g_vrsLimitTo2x2CVar;
-extern BoolCVar g_preferComputeCVar;
-extern NumericCVar<F32> g_renderScalingCVar;
-extern BoolCVar g_rayTracedShadowsCVar;
-extern BoolCVar g_meshletRenderingCVar;
-extern NumericCVar<U8> g_shadowCascadeCountCVar;
-extern NumericCVar<F32> g_shadowCascade0DistanceCVar;
-extern NumericCVar<F32> g_shadowCascade1DistanceCVar;
-extern NumericCVar<F32> g_shadowCascade2DistanceCVar;
-extern NumericCVar<F32> g_shadowCascade3DistanceCVar;
-extern NumericCVar<F32> g_lod0MaxDistanceCVar;
-extern NumericCVar<F32> g_lod1MaxDistanceCVar;
-
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<F32> g_internalRenderScalingCVar("R", "InternalRenderScaling", 1.0f, 0.5f, 1.0f,
+													"A factor over the requested swapchain resolution. Applies to all passes up to TAA");
+inline NumericCVar<F32> g_renderScalingCVar("R", "RenderScaling", 1.0f, 0.5f, 8.0f,
+											"A factor over the requested swapchain resolution. Applies to post-processing and UI");
+inline NumericCVar<U32> g_zSplitCountCVar("R", "ZSplitCount", 64, 8, kMaxZsplitCount, "Clusterer number of Z splits");
+inline NumericCVar<U8> g_textureAnisotropyCVar("R", "TextureAnisotropy", (ANKI_PLATFORM_MOBILE) ? 1 : 16, 1, 16,
+											   "Texture anisotropy for the main passes");
+inline BoolCVar g_preferComputeCVar("R", "PreferCompute", !ANKI_PLATFORM_MOBILE, "Prefer compute shaders");
+inline BoolCVar g_highQualityHdrCVar("R", "HighQualityHdr", !ANKI_PLATFORM_MOBILE,
+									 "If true use R16G16B16 for HDR images. Alternatively use B10G11R11");
+inline BoolCVar g_vrsLimitTo2x2CVar("R", "VrsLimitTo2x2", false, "If true the max rate will be 2x2");
+inline BoolCVar g_rayTracedShadowsCVar("R", "RayTracedShadows", true, "Enable or not ray traced shadows. Ignored if RT is not supported");
+inline NumericCVar<U8> g_shadowCascadeCountCVar("R", "ShadowCascadeCount", (ANKI_PLATFORM_MOBILE) ? 3 : kMaxShadowCascades, 1, kMaxShadowCascades,
+												"Max number of shadow cascades for directional lights");
+inline NumericCVar<F32> g_shadowCascade0DistanceCVar("R", "ShadowCascade0Distance", 18.0, 1.0, kMaxF32, "The distance of the 1st cascade");
+inline NumericCVar<F32> g_shadowCascade1DistanceCVar("R", "ShadowCascade1Distance", (ANKI_PLATFORM_MOBILE) ? 80.0f : 40.0, 1.0, kMaxF32,
+													 "The distance of the 2nd cascade");
+inline NumericCVar<F32> g_shadowCascade2DistanceCVar("R", "ShadowCascade2Distance", (ANKI_PLATFORM_MOBILE) ? 150.0f : 80.0, 1.0, kMaxF32,
+													 "The distance of the 3rd cascade");
+inline NumericCVar<F32> g_shadowCascade3DistanceCVar("R", "ShadowCascade3Distance", 200.0, 1.0, kMaxF32, "The distance of the 4th cascade");
+inline NumericCVar<F32> g_lod0MaxDistanceCVar("R", "Lod0MaxDistance", 20.0f, 1.0f, kMaxF32, "Distance that will be used to calculate the LOD 0");
+inline NumericCVar<F32> g_lod1MaxDistanceCVar("R", "Lod1MaxDistance", 40.0f, 2.0f, kMaxF32, "Distance that will be used to calculate the LOD 1");
+
+inline StatCounter g_rendererGpuTimeStatVar(StatCategory::kTime, "GPU frame",
+											StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
+
 /// Renderer statistics.
 class RendererPrecreatedSamplers
 {

+ 1 - 1
AnKi/Renderer/RendererObject.cpp

@@ -54,7 +54,7 @@ Error RendererObject::loadShaderProgram(CString filename, std::initializer_list<
 
 		if(techniqueShaderTypes == (ShaderTypeBit::kCompute | ShaderTypeBit::kPixel | ShaderTypeBit::kVertex))
 		{
-			if(g_preferComputeCVar.get())
+			if(g_preferComputeCVar)
 			{
 				shaderTypes = ShaderTypeBit::kCompute;
 			}

+ 3 - 4
AnKi/Renderer/RendererObject.def.h

@@ -11,9 +11,8 @@ ANKI_RENDERER_OBJECT_DEF(ShadowMapping, shadowMapping, 1)
 ANKI_RENDERER_OBJECT_DEF(LightShading, lightShading, 1)
 ANKI_RENDERER_OBJECT_DEF(ForwardShading, forwardShading, 1)
 ANKI_RENDERER_OBJECT_DEF(LensFlare, lensFlare, 1)
-ANKI_RENDERER_OBJECT_DEF(DownscaleBlur, downscaleBlur, 1)
+ANKI_RENDERER_OBJECT_DEF(Bloom2, bloom2, 1)
 ANKI_RENDERER_OBJECT_DEF(Tonemapping, tonemapping, 1)
-ANKI_RENDERER_OBJECT_DEF(Bloom, bloom, 1)
 ANKI_RENDERER_OBJECT_DEF(FinalComposite, finalComposite, 1)
 ANKI_RENDERER_OBJECT_DEF(Dbg, dbg, 1)
 ANKI_RENDERER_OBJECT_DEF(ProbeReflections, probeReflections, 1)
@@ -24,9 +23,9 @@ ANKI_RENDERER_OBJECT_DEF(UiStage, uiStage, 1)
 ANKI_RENDERER_OBJECT_DEF(VolumetricLightingAccumulation, volumetricLightingAccumulation, 1)
 ANKI_RENDERER_OBJECT_DEF(IndirectDiffuseProbes, indirectDiffuseProbes, 1)
 ANKI_RENDERER_OBJECT_DEF(ShadowmapsResolve, shadowmapsResolve, 1)
-ANKI_RENDERER_OBJECT_DEF(RtShadows, rtShadows, GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rayTracedShadowsCVar.get())
+ANKI_RENDERER_OBJECT_DEF(RtShadows, rtShadows, GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rayTracedShadowsCVar)
 ANKI_RENDERER_OBJECT_DEF(AccelerationStructureBuilder, accelerationStructureBuilder,
-						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rayTracedShadowsCVar.get())
+						 GrManager::getSingleton().getDeviceCapabilities().m_rayTracingEnabled&& g_rayTracedShadowsCVar)
 ANKI_RENDERER_OBJECT_DEF(MotionVectors, motionVectors, 1)
 ANKI_RENDERER_OBJECT_DEF(Scale, scale, 1)
 ANKI_RENDERER_OBJECT_DEF(VrsSriGeneration, vrsSriGeneration, 1)

+ 5 - 10
AnKi/Renderer/RtShadows.cpp

@@ -12,7 +12,7 @@
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/ClusterBinning.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Shaders/Include/MaterialTypes.h>
 #include <AnKi/Shaders/Include/GpuSceneTypes.h>
 #include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
@@ -21,11 +21,6 @@
 
 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();
@@ -41,8 +36,8 @@ Error RtShadows::initInternal()
 {
 	ANKI_R_LOGV("Initializing RT shadows");
 
-	m_useSvgf = g_rtShadowsSvgfCVar.get();
-	m_atrousPassCount = g_rtShadowsSvgfAtrousPassCountCVar.get();
+	m_useSvgf = g_rtShadowsSvgfCVar;
+	m_atrousPassCount = g_rtShadowsSvgfAtrousPassCountCVar;
 
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_blueNoiseImage));
 
@@ -53,7 +48,7 @@ Error RtShadows::initInternal()
 	// Ray gen and miss
 	{
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_rayGenAndMissProg);
-		variantInitInfo.addMutation("RAYS_PER_PIXEL", g_rtShadowsRaysPerPixelCVar.get());
+		variantInitInfo.addMutation("RAYS_PER_PIXEL", g_rtShadowsRaysPerPixelCVar);
 		variantInitInfo.requestTechniqueAndTypes(ShaderTypeBit::kRayGen, "RtShadows");
 		const ShaderProgramResourceVariant* variant;
 		m_rayGenAndMissProg->getOrCreateVariant(variantInitInfo, variant);
@@ -61,7 +56,7 @@ Error RtShadows::initInternal()
 		m_rayGenShaderGroupIdx = variant->getShaderGroupHandleIndex();
 
 		ShaderProgramResourceVariantInitInfo variantInitInfo2(m_rayGenAndMissProg);
-		variantInitInfo2.addMutation("RAYS_PER_PIXEL", g_rtShadowsRaysPerPixelCVar.get());
+		variantInitInfo2.addMutation("RAYS_PER_PIXEL", g_rtShadowsRaysPerPixelCVar);
 		variantInitInfo2.requestTechniqueAndTypes(ShaderTypeBit::kMiss, "RtShadows");
 		m_rayGenAndMissProg->getOrCreateVariant(variantInitInfo2, variant);
 		m_missShaderGroupIdx = variant->getShaderGroupHandleIndex();

+ 4 - 0
AnKi/Renderer/RtShadows.h

@@ -15,6 +15,10 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline BoolCVar g_rtShadowsSvgfCVar("R", "RtShadowsSvgf", false, "Enable or not RT shadows SVGF");
+inline NumericCVar<U8> g_rtShadowsSvgfAtrousPassCountCVar("R", "RtShadowsSvgfAtrousPassCount", 3, 1, 20, "Number of atrous passes of SVGF");
+inline NumericCVar<U32> g_rtShadowsRaysPerPixelCVar("R", "RtShadowsRaysPerPixel", 1, 1, 8, "Number of shadow rays per pixel");
+
 /// Similar to ShadowmapsResolve but it's using ray tracing.
 class RtShadows : public RendererObject
 {

+ 9 - 14
AnKi/Renderer/Scale.cpp

@@ -6,7 +6,7 @@
 #include <AnKi/Renderer/Scale.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/TemporalAA.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/MotionVectors.h>
@@ -33,22 +33,17 @@
 
 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 = g_sharpnessCVar.get() > 0.0f;
+	const Bool needsSharpening = g_sharpnessCVar > 0.0f;
 	if(!needsScaling && !needsSharpening)
 	{
 		return Error::kNone;
 	}
 
-	const U32 dlssQuality = g_dlssQualityCVar.get();
-	const U32 fsrQuality = g_fsrQualityCVar.get();
+	const U32 dlssQuality = g_dlssQualityCVar;
+	const U32 fsrQuality = g_fsrQualityCVar;
 
 	if(needsScaling)
 	{
@@ -156,7 +151,7 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 	}
 
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 
 	// Step 1: Upscaling
 	if(m_upscalingMethod == UpscalingMethod::kGr)
@@ -292,7 +287,7 @@ void Scale::runFsrOrBilinearScaling(RenderPassWorkContext& rgraphCtx)
 {
 	ANKI_TRACE_SCOPED_EVENT(Scale);
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 	const RenderTargetHandle inRt = getRenderer().getTemporalAA().getTonemappedRt();
 	const RenderTargetHandle outRt = m_runCtx.m_upscaledTonemappedRt;
 
@@ -357,7 +352,7 @@ void Scale::runRcasSharpening(RenderPassWorkContext& rgraphCtx)
 {
 	ANKI_TRACE_SCOPED_EVENT(Scale);
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 	const RenderTargetHandle inRt = m_runCtx.m_tonemappedRt;
 	const RenderTargetHandle outRt = m_runCtx.m_sharpenedRt;
 
@@ -382,7 +377,7 @@ void Scale::runRcasSharpening(RenderPassWorkContext& rgraphCtx)
 		UVec2 m_padding;
 	} pc;
 
-	F32 sharpness = g_sharpnessCVar.get(); // [0, 1]
+	F32 sharpness = g_sharpnessCVar; // [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);
@@ -428,7 +423,7 @@ void Scale::runTonemapping(RenderPassWorkContext& rgraphCtx)
 {
 	ANKI_TRACE_SCOPED_EVENT(Scale);
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 	const RenderTargetHandle inRt = m_runCtx.m_upscaledHdrRt;
 	const RenderTargetHandle outRt = m_runCtx.m_tonemappedRt;
 

+ 4 - 0
AnKi/Renderer/Scale.h

@@ -12,6 +12,10 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U8> g_fsrQualityCVar("R", "FsrQuality", 1, 0, 2, "0: Use bilinear, 1: FSR low quality, 2: FSR high quality");
+inline NumericCVar<U8> g_dlssQualityCVar("R", "DlssQuality", 2, 0, 3, "0: Disabled, 1: Performance, 2: Balanced, 3: Quality");
+inline NumericCVar<F32> g_sharpnessCVar("R", "Sharpness", (ANKI_PLATFORM_MOBILE) ? 0.0f : 0.8f, 0.0f, 1.0f, "Sharpen the image. It's a factor");
+
 /// Upscales, sharpens and in some cases tonemaps.
 class Scale : public RendererObject
 {

+ 15 - 22
AnKi/Renderer/ShadowMapping.cpp

@@ -20,13 +20,6 @@
 
 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");
-BoolCVar g_shadowMappingPcfCVar(CVarSubsystem::kRenderer, "ShadowMappingPcf", (ANKI_PLATFORM_MOBILE) ? false : true, "Shadow PCF");
-BoolCVar g_shadowMappingPcssCVar(CVarSubsystem::kRenderer, "ShadowMappingPcss", (ANKI_PLATFORM_MOBILE) ? false : true, "Shadow PCSS");
-
 static StatCounter g_tilesAllocatedStatVar(StatCategory::kRenderer, "Shadow tiles (re)allocated", StatFlag::kMainThreadUpdates);
 
 class LightHash
@@ -81,8 +74,8 @@ Error ShadowMapping::initInternal()
 {
 	// Init RT
 	{
-		m_tileResolution = g_shadowMappingTileResolutionCVar.get();
-		m_tileCountBothAxis = g_shadowMappingTileCountPerRowOrColumnCVar.get();
+		m_tileResolution = g_shadowMappingTileResolutionCVar;
+		m_tileCountBothAxis = g_shadowMappingTileCountPerRowOrColumnCVar;
 
 		ANKI_R_LOGV("Initializing shadowmapping. Atlas resolution %ux%u", m_tileResolution * m_tileCountBothAxis,
 					m_tileResolution * m_tileCountBothAxis);
@@ -278,7 +271,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 
 	// Allocate tiles for the dir light first but don't build any passes
 	const LightComponent* dirLight = SceneGraph::getSingleton().getDirectionalLight();
-	if(dirLight && (!dirLight->getShadowEnabled() || !g_shadowCascadeCountCVar.get()))
+	if(dirLight && (!dirLight->getShadowEnabled() || !g_shadowCascadeCountCVar))
 	{
 		dirLight = nullptr; // Skip dir light
 	}
@@ -286,7 +279,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 	Array<UVec4, kMaxShadowCascades> dirLightAtlasViewports;
 	if(dirLight)
 	{
-		const U32 cascadeCount = g_shadowCascadeCountCVar.get();
+		const U32 cascadeCount = g_shadowCascadeCountCVar;
 
 		Array<U32, kMaxShadowCascades> hierarchies;
 		for(U32 cascade = 0; cascade < cascadeCount; ++cascade)
@@ -311,7 +304,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 
 		// Prepare data to allocate tiles and allocate
 		U32 hierarchy;
-		chooseDetail(cameraOrigin, *lightc, {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()}, hierarchy);
+		chooseDetail(cameraOrigin, *lightc, {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar}, hierarchy);
 		Array<U32, 6> hierarchies;
 		hierarchies.fill(hierarchy);
 
@@ -324,7 +317,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 
 			// Remove a few texels to avoid bilinear filtering bleeding
 			F32 texelsBorder;
-			if(g_shadowMappingPcfCVar.get() || g_shadowMappingPcssCVar.get())
+			if(g_shadowMappingPcfCVar || g_shadowMappingPcssCVar)
 			{
 				texelsBorder = 2.0f; // 2 texels
 			}
@@ -352,7 +345,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 			}
 
 			// Vis testing
-			const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+			const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 			DistanceGpuVisibilityInput visIn;
 			visIn.m_passesName = generateTempPassName("Shadows point light lightIdx:%u", lightIdx);
 			visIn.m_technique = RenderingTechnique::kDepth;
@@ -414,7 +407,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 
 		// Allocate tile
 		U32 hierarchy;
-		chooseDetail(cameraOrigin, *lightc, {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()}, hierarchy);
+		chooseDetail(cameraOrigin, *lightc, {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar}, hierarchy);
 		UVec4 atlasViewport;
 		const TileAllocatorResult2 result = allocateAtlasTiles(lightc->getUuid(), lightc->getArrayIndex(), 1, &hierarchy, &atlasViewport);
 
@@ -430,7 +423,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 			}
 
 			// Vis testing
-			const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+			const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 			FrustumGpuVisibilityInput visIn;
 			visIn.m_passesName = generateTempPassName("Shadows spot light lightIdx:%u", lightIdx);
 			visIn.m_technique = RenderingTechnique::kDepth;
@@ -467,15 +460,15 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 	// Process the directional light last
 	if(dirLight)
 	{
-		const U32 cascadeCount = g_shadowCascadeCountCVar.get();
+		const U32 cascadeCount = g_shadowCascadeCountCVar;
 
 		// Compute the view projection matrices
 		Array<F32, kMaxShadowCascades> cascadeDistances;
 		static_assert(kMaxShadowCascades == 4);
-		cascadeDistances[0] = g_shadowCascade0DistanceCVar.get();
-		cascadeDistances[1] = g_shadowCascade1DistanceCVar.get();
-		cascadeDistances[2] = g_shadowCascade2DistanceCVar.get();
-		cascadeDistances[3] = g_shadowCascade3DistanceCVar.get();
+		cascadeDistances[0] = g_shadowCascade0DistanceCVar;
+		cascadeDistances[1] = g_shadowCascade1DistanceCVar;
+		cascadeDistances[2] = g_shadowCascade2DistanceCVar;
+		cascadeDistances[3] = g_shadowCascade3DistanceCVar;
 
 		Array<Mat4, kMaxShadowCascades> cascadeViewProjMats;
 		Array<Mat3x4, kMaxShadowCascades> cascadeViewMats;
@@ -510,7 +503,7 @@ void ShadowMapping::processLights(RenderingContext& ctx)
 		for(U32 cascade = 0; cascade < cascadeCount; ++cascade)
 		{
 			// Vis testing
-			const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar.get(), g_lod1MaxDistanceCVar.get()};
+			const Array<F32, kMaxLodCount - 1> lodDistances = {g_lod0MaxDistanceCVar, g_lod1MaxDistanceCVar};
 			FrustumGpuVisibilityInput visIn;
 			visIn.m_passesName = generateTempPassName("Shadows: Dir light cascade lightIdx:%u cascade:%u", lightIdx, cascade);
 			visIn.m_technique = RenderingTechnique::kDepth;

+ 7 - 2
AnKi/Renderer/ShadowMapping.h

@@ -14,12 +14,17 @@ namespace anki {
 
 // Forward
 class GpuVisibilityOutput;
-extern BoolCVar g_shadowMappingPcfCVar;
-extern BoolCVar g_shadowMappingPcssCVar;
 
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U32> g_shadowMappingTileResolutionCVar("R", "ShadowMappingTileResolution", (ANKI_PLATFORM_MOBILE) ? 128 : 256, 16, 2048,
+														  "Shadowmapping tile resolution");
+inline NumericCVar<U32> g_shadowMappingTileCountPerRowOrColumnCVar("R", "ShadowMappingTileCountPerRowOrColumn", 32, 1, 256,
+																   "Shadowmapping atlas will have this number squared number of tiles");
+inline BoolCVar g_shadowMappingPcfCVar("R", "ShadowMappingPcf", (ANKI_PLATFORM_MOBILE) ? false : true, "Shadow PCF");
+inline BoolCVar g_shadowMappingPcssCVar("R", "ShadowMappingPcss", (ANKI_PLATFORM_MOBILE) ? false : true, "Shadow PCSS");
+
 /// Shadowmapping pass
 class ShadowMapping : public RendererObject
 {

+ 7 - 9
AnKi/Renderer/ShadowmapsResolve.cpp

@@ -10,13 +10,11 @@
 #include <AnKi/Renderer/DepthDownscale.h>
 #include <AnKi/Renderer/ClusterBinning.h>
 #include <AnKi/Renderer/RtShadows.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 
 namespace anki {
 
-static BoolCVar g_smResolveQuarterRezCVar(CVarSubsystem::kRenderer, "SmResolveQuarterRez", ANKI_PLATFORM_MOBILE, "Shadowmapping resolve quality");
-
 Error ShadowmapsResolve::init()
 {
 	const Error err = initInternal();
@@ -30,7 +28,7 @@ Error ShadowmapsResolve::init()
 
 Error ShadowmapsResolve::initInternal()
 {
-	m_quarterRez = g_smResolveQuarterRezCVar.get();
+	m_quarterRez = g_smResolveQuarterRezCVar;
 	const U32 width = getRenderer().getInternalResolution().x() / (m_quarterRez + 1);
 	const U32 height = getRenderer().getInternalResolution().y() / (m_quarterRez + 1);
 
@@ -59,7 +57,7 @@ void ShadowmapsResolve::populateRenderGraph(RenderingContext& ctx)
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
 	m_runCtx.m_rt = rgraph.newRenderTarget(m_rtDescr);
 
-	if(g_preferComputeCVar.get())
+	if(g_preferComputeCVar)
 	{
 		NonGraphicsRenderPass& rpass = rgraph.newNonGraphicsRenderPass("ResolveShadows");
 
@@ -113,11 +111,11 @@ void ShadowmapsResolve::run(RenderPassWorkContext& rgraphCtx, RenderingContext&
 	CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
 	U32 quality;
-	if(g_shadowMappingPcssCVar.get())
+	if(g_shadowMappingPcssCVar)
 	{
 		quality = 2;
 	}
-	else if(g_shadowMappingPcfCVar.get())
+	else if(g_shadowMappingPcfCVar)
 	{
 		quality = 1;
 	}
@@ -152,13 +150,13 @@ void ShadowmapsResolve::run(RenderPassWorkContext& rgraphCtx, RenderingContext&
 		rgraphCtx.bindSrv(6, 0, getRenderer().getRtShadows().getRt());
 	}
 
-	if(g_preferComputeCVar.get() || g_shadowMappingPcfCVar.get() || g_shadowMappingPcssCVar.get())
+	if(g_preferComputeCVar || g_shadowMappingPcfCVar || g_shadowMappingPcssCVar)
 	{
 		const Vec4 consts(F32(m_rtDescr.m_width), F32(m_rtDescr.m_height), 0.0f, 0.0f);
 		cmdb.setFastConstants(&consts, sizeof(consts));
 	}
 
-	if(g_preferComputeCVar.get())
+	if(g_preferComputeCVar)
 	{
 		rgraphCtx.bindUav(0, 0, m_runCtx.m_rt);
 		dispatchPPCompute(cmdb, 8, 8, m_rtDescr.m_width, m_rtDescr.m_height);

+ 2 - 0
AnKi/Renderer/ShadowmapsResolve.h

@@ -14,6 +14,8 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline BoolCVar g_smResolveQuarterRezCVar("R", "SmResolveQuarterRez", ANKI_PLATFORM_MOBILE, "Shadowmapping resolve quality");
+
 /// Resolves shadowmaps into a single texture.
 class ShadowmapsResolve : public RendererObject
 {

+ 17 - 24
AnKi/Renderer/Ssao.cpp

@@ -12,13 +12,6 @@
 
 namespace anki {
 
-static NumericCVar<U32> g_ssaoSampleCountCVar(CVarSubsystem::kRenderer, "SsaoSampleCount", 4, 1, 1024, "SSAO sample count");
-static NumericCVar<F32> g_ssaoRadiusCVar(CVarSubsystem::kRenderer, "SsaoRadius", 2.0f, 0.1f, 100.0f, "SSAO radius in meters");
-static BoolCVar g_ssaoQuarterRez(CVarSubsystem::kRenderer, "SsaoQuarterResolution", ANKI_PLATFORM_MOBILE, "Render SSAO in quarter rez");
-static NumericCVar<F32> g_ssaoPower(CVarSubsystem::kRenderer, "SsaoPower", 1.5f, 0.1f, 100.0f, "SSAO power");
-static NumericCVar<U8> g_ssaoSpatialQuality(CVarSubsystem::kRenderer, "SsaoSpatialQuality", (ANKI_PLATFORM_MOBILE) ? 0 : 1, 0, 1,
-											"SSAO spatial denoise quality");
-
 Error Ssao::init()
 {
 	const Error err = initInternal();
@@ -31,11 +24,11 @@ Error Ssao::init()
 
 Error Ssao::initInternal()
 {
-	const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2 : getRenderer().getInternalResolution();
+	const UVec2 rez = (g_ssaoQuarterRezCVar) ? getRenderer().getInternalResolution() / 2 : getRenderer().getInternalResolution();
 
 	ANKI_R_LOGV("Initializing SSAO. Resolution %ux%u", rez.x(), rez.y());
 
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 
 	{
 		TextureUsageBit usage = TextureUsageBit::kAllSrv;
@@ -53,10 +46,10 @@ Error Ssao::initInternal()
 	m_bentNormalsAndSsaoRtDescr.bake();
 
 	ANKI_CHECK(
-		loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", {{"SPATIAL_DENOISE_QUALITY", g_ssaoSpatialQuality.get()}}, m_prog, m_grProg, "Ssao"));
-	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", {{"SPATIAL_DENOISE_QUALITY", g_ssaoSpatialQuality.get()}}, m_prog,
+		loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", {{"SPATIAL_DENOISE_QUALITY", g_ssaoSpatialQualityCVar}}, m_prog, m_grProg, "Ssao"));
+	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", {{"SPATIAL_DENOISE_QUALITY", g_ssaoSpatialQualityCVar}}, m_prog,
 								 m_spatialDenoiseGrProg, "SsaoSpatialDenoise"));
-	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", {{"SPATIAL_DENOISE_QUALITY", g_ssaoSpatialQuality.get()}}, m_prog,
+	ANKI_CHECK(loadShaderProgram("ShaderBinaries/Ssao.ankiprogbin", {{"SPATIAL_DENOISE_QUALITY", g_ssaoSpatialQualityCVar}}, m_prog,
 								 m_tempralDenoiseGrProg, "SsaoTemporalDenoise"));
 
 	ANKI_CHECK(ResourceManager::getSingleton().loadResource("EngineAssets/BlueNoise_Rgba8_64x64.png", m_noiseImage));
@@ -68,7 +61,7 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 {
 	ANKI_TRACE_SCOPED_EVENT(Ssao);
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 
 	const U32 readRtIdx = getRenderer().getFrameCount() & 1;
 	const U32 writeRtIdx = !readRtIdx;
@@ -121,7 +114,7 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 		}
 
 		ppass->newTextureDependency(getRenderer().getGBuffer().getColorRt(2), readUsage);
-		ppass->newTextureDependency((g_ssaoQuarterRez.get()) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt(),
+		ppass->newTextureDependency((g_ssaoQuarterRezCVar) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt(),
 									readUsage);
 		ppass->newTextureDependency(finalRt, writeUsage);
 
@@ -131,17 +124,17 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 			cmdb.bindShaderProgram(m_grProg.get());
 
 			rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getColorRt(2));
-			rgraphCtx.bindSrv(1, 0, (g_ssaoQuarterRez.get()) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt());
+			rgraphCtx.bindSrv(1, 0, (g_ssaoQuarterRezCVar) ? getRenderer().getDepthDownscale().getRt() : getRenderer().getGBuffer().getDepthRt());
 
 			cmdb.bindSrv(2, 0, TextureView(&m_noiseImage->getTexture(), TextureSubresourceDesc::all()));
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_trilinearRepeat.get());
 			cmdb.bindSampler(1, 0, getRenderer().getSamplers().m_trilinearClamp.get());
 
-			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
+			const UVec2 rez = (g_ssaoQuarterRezCVar) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 
 			SsaoConstants consts;
-			consts.m_radius = g_ssaoRadiusCVar.get();
-			consts.m_sampleCount = g_ssaoSampleCountCVar.get();
+			consts.m_radius = g_ssaoRadiusCVar;
+			consts.m_sampleCount = g_ssaoSampleCountCVar;
 			consts.m_viewportSizef = Vec2(rez);
 			consts.m_unprojectionParameters = ctx.m_matrices.m_unprojectionParameters;
 			consts.m_projectionMat00 = ctx.m_matrices.m_projection(0, 0);
@@ -149,11 +142,11 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 			consts.m_projectionMat22 = ctx.m_matrices.m_projection(2, 2);
 			consts.m_projectionMat23 = ctx.m_matrices.m_projection(2, 3);
 			consts.m_frameCount = getRenderer().getFrameCount() % kMaxU32;
-			consts.m_ssaoPower = g_ssaoPower.get();
+			consts.m_ssaoPower = g_ssaoPowerCVar;
 			consts.m_viewMat = ctx.m_matrices.m_view;
 			cmdb.setFastConstants(&consts, sizeof(consts));
 
-			if(g_preferComputeCVar.get())
+			if(g_preferComputeCVar)
 			{
 				rgraphCtx.bindUav(0, 0, finalRt);
 
@@ -197,14 +190,14 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindSrv(0, 0, finalRt);
 			rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getDepthRt());
 
-			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
+			const UVec2 rez = (g_ssaoQuarterRezCVar) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 
 			SsaoSpatialDenoiseConstants consts;
 			computeLinearizeDepthOptimal(ctx.m_cameraNear, ctx.m_cameraFar, consts.m_linearizeDepthParams.x(), consts.m_linearizeDepthParams.y());
 			consts.m_viewToWorldMat = ctx.m_matrices.m_cameraTransform;
 			cmdb.setFastConstants(&consts, sizeof(consts));
 
-			if(g_preferComputeCVar.get())
+			if(g_preferComputeCVar)
 			{
 				rgraphCtx.bindUav(0, 0, bentNormalsAndSsaoTempRt);
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());
@@ -248,9 +241,9 @@ void Ssao::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindSrv(1, 0, historyRt);
 			rgraphCtx.bindSrv(2, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
 
-			const UVec2 rez = (g_ssaoQuarterRez.get()) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
+			const UVec2 rez = (g_ssaoQuarterRezCVar) ? getRenderer().getInternalResolution() / 2u : getRenderer().getInternalResolution();
 
-			if(g_preferComputeCVar.get())
+			if(g_preferComputeCVar)
 			{
 				rgraphCtx.bindUav(0, 0, finalRt);
 				dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());

+ 6 - 0
AnKi/Renderer/Ssao.h

@@ -14,6 +14,12 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U32> g_ssaoSampleCountCVar("R", "SsaoSampleCount", 4, 1, 1024, "SSAO sample count");
+inline NumericCVar<F32> g_ssaoRadiusCVar("R", "SsaoRadius", 2.0f, 0.1f, 100.0f, "SSAO radius in meters");
+inline BoolCVar g_ssaoQuarterRezCVar("R", "SsaoQuarterResolution", ANKI_PLATFORM_MOBILE, "Render SSAO in quarter rez");
+inline NumericCVar<F32> g_ssaoPowerCVar("R", "SsaoPower", 1.5f, 0.1f, 100.0f, "SSAO power");
+inline NumericCVar<U8> g_ssaoSpatialQualityCVar("R", "SsaoSpatialQuality", (ANKI_PLATFORM_MOBILE) ? 0 : 1, 0, 1, "SSAO spatial denoise quality");
+
 /// Screen space ambient occlusion.
 class Ssao : public RendererObject
 {

+ 11 - 17
AnKi/Renderer/Ssr.cpp

@@ -6,7 +6,7 @@
 #include <AnKi/Renderer/Ssr.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Util/Tracer.h>
-#include <AnKi/Renderer/DownscaleBlur.h>
+#include <AnKi/Renderer/Bloom2.h>
 #include <AnKi/Renderer/GBuffer.h>
 #include <AnKi/Renderer/DepthDownscale.h>
 
@@ -29,12 +29,6 @@
 
 namespace anki {
 
-static NumericCVar<U32> g_ssrStepIncrementCVar(CVarSubsystem::kRenderer, "SsrStepIncrement", 32, 1, 256, "The number of steps for each loop");
-static NumericCVar<U32> g_ssrMaxIterationsCVar(CVarSubsystem::kRenderer, "SsrMaxIterations", 64, 1, 256, "Max SSR raymarching loop iterations");
-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");
-static BoolCVar g_ssrQuarterResolution(CVarSubsystem::kRenderer, "SsrQuarterResolution", ANKI_PLATFORM_MOBILE);
-
 Error Ssr::init()
 {
 	const Error err = initInternal();
@@ -47,12 +41,12 @@ Error Ssr::init()
 
 Error Ssr::initInternal()
 {
-	const UVec2 rez = (g_ssrQuarterResolution.get()) ? getRenderer().getInternalResolution() / 2 : getRenderer().getInternalResolution();
+	const UVec2 rez = (g_ssrQuarterResolutionCVar) ? getRenderer().getInternalResolution() / 2 : getRenderer().getInternalResolution();
 
 	ANKI_R_LOGV("Initializing SSR. Resolution %ux%u", rez.x(), rez.y());
 
 	TextureUsageBit mipTexUsage = TextureUsageBit::kAllSrv;
-	if(g_preferComputeCVar.get())
+	if(g_preferComputeCVar)
 	{
 		mipTexUsage |= TextureUsageBit::kUavCompute;
 	}
@@ -74,7 +68,7 @@ void Ssr::populateRenderGraph(RenderingContext& ctx)
 	ANKI_TRACE_SCOPED_EVENT(Ssr);
 
 	RenderGraphBuilder& rgraph = ctx.m_renderGraphDescr;
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 
 	m_runCtx.m_ssrRt = rgraph.newRenderTarget(m_ssrRtDescr);
 
@@ -102,7 +96,7 @@ void Ssr::populateRenderGraph(RenderingContext& ctx)
 		writeUsage = TextureUsageBit::kRtvDsvWrite;
 	}
 
-	ppass->newTextureDependency(getRenderer().getDownscaleBlur().getRt(), readUsage);
+	ppass->newTextureDependency(getRenderer().getBloom2().getPyramidRt(), readUsage);
 	ppass->newTextureDependency(getRenderer().getGBuffer().getColorRt(1), readUsage);
 	ppass->newTextureDependency(getRenderer().getGBuffer().getColorRt(2), readUsage);
 	ppass->newTextureDependency(getRenderer().getDepthDownscale().getRt(), readUsage);
@@ -111,16 +105,16 @@ void Ssr::populateRenderGraph(RenderingContext& ctx)
 	ppass->setWork([this, &ctx](RenderPassWorkContext& rgraphCtx) {
 		CommandBuffer& cmdb = *rgraphCtx.m_commandBuffer;
 
-		const UVec2 rez = getRenderer().getInternalResolution() / ((g_ssrQuarterResolution.get()) ? 2 : 1);
+		const UVec2 rez = getRenderer().getInternalResolution() / ((g_ssrQuarterResolutionCVar) ? 2 : 1);
 
 		cmdb.bindShaderProgram(m_ssrGrProg.get());
 
 		SsrConstants consts = {};
 		consts.m_viewportSizef = Vec2(rez);
 		consts.m_frameCount = getRenderer().getFrameCount() % kMaxU32;
-		consts.m_maxIterations = g_ssrMaxIterationsCVar.get();
-		consts.m_roughnessCutoff = g_ssrRoughnessCutoffCVar.get();
-		consts.m_stepIncrement = g_ssrStepIncrementCVar.get();
+		consts.m_maxIterations = g_ssrMaxIterationsCVar;
+		consts.m_roughnessCutoff = g_ssrRoughnessCutoffCVar;
+		consts.m_stepIncrement = g_ssrStepIncrementCVar;
 		consts.m_projMat00_11_22_23 = Vec4(ctx.m_matrices.m_projection(0, 0), ctx.m_matrices.m_projection(1, 1), ctx.m_matrices.m_projection(2, 2),
 										   ctx.m_matrices.m_projection(2, 3));
 		consts.m_unprojectionParameters = ctx.m_matrices.m_unprojectionParameters;
@@ -132,9 +126,9 @@ void Ssr::populateRenderGraph(RenderingContext& ctx)
 		rgraphCtx.bindSrv(0, 0, getRenderer().getGBuffer().getColorRt(1));
 		rgraphCtx.bindSrv(1, 0, getRenderer().getGBuffer().getColorRt(2));
 		rgraphCtx.bindSrv(2, 0, getRenderer().getDepthDownscale().getRt());
-		rgraphCtx.bindSrv(3, 0, getRenderer().getDownscaleBlur().getRt());
+		rgraphCtx.bindSrv(3, 0, getRenderer().getBloom2().getPyramidRt());
 
-		if(g_preferComputeCVar.get())
+		if(g_preferComputeCVar)
 		{
 			rgraphCtx.bindUav(0, 0, m_runCtx.m_ssrRt);
 			dispatchPPCompute(cmdb, 8, 8, rez.x(), rez.y());

+ 6 - 0
AnKi/Renderer/Ssr.h

@@ -14,6 +14,12 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<U32> g_ssrStepIncrementCVar("R", "SsrStepIncrement", 32, 1, 256, "The number of steps for each loop");
+inline NumericCVar<U32> g_ssrMaxIterationsCVar("R", "SsrMaxIterations", 64, 1, 256, "Max SSR raymarching loop iterations");
+inline NumericCVar<F32> g_ssrRoughnessCutoffCVar("R", "SsrRoughnessCutoff", (ANKI_PLATFORM_MOBILE) ? 0.7f : 1.0f, 0.0f, 1.0f,
+												 "Materials with roughness higher that this value will fallback to probe reflections");
+inline BoolCVar g_ssrQuarterResolutionCVar("R", "SsrQuarterResolution", ANKI_PLATFORM_MOBILE);
+
 /// Screen space reflections.
 class Ssr : public RendererObject
 {

+ 4 - 4
AnKi/Renderer/TemporalAA.cpp

@@ -9,7 +9,7 @@
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/Tonemapping.h>
 #include <AnKi/Renderer/MotionVectors.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 
 namespace anki {
@@ -34,7 +34,7 @@ Error TemporalAA::initInternal()
 	for(U32 i = 0; i < 2; ++i)
 	{
 		TextureUsageBit usage = TextureUsageBit::kSrvPixel | TextureUsageBit::kSrvCompute;
-		usage |= (g_preferComputeCVar.get()) ? TextureUsageBit::kUavCompute : TextureUsageBit::kRtvDsvWrite;
+		usage |= (g_preferComputeCVar) ? TextureUsageBit::kUavCompute : TextureUsageBit::kRtvDsvWrite;
 
 		TextureInitInfo texinit =
 			getRenderer().create2DRenderTargetInitInfo(getRenderer().getInternalResolution().x(), getRenderer().getInternalResolution().y(),
@@ -59,7 +59,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 
 	const U32 historyRtIdx = (getRenderer().getFrameCount() + 1) & 1;
 	const U32 renderRtIdx = !historyRtIdx;
-	const Bool preferCompute = g_preferComputeCVar.get();
+	const Bool preferCompute = g_preferComputeCVar;
 
 	// Import RTs
 	if(m_rtTexturesImportedOnce) [[likely]]
@@ -119,7 +119,7 @@ void TemporalAA::populateRenderGraph(RenderingContext& ctx)
 		rgraphCtx.bindSrv(2, 0, getRenderer().getMotionVectors().getMotionVectorsRt());
 		rgraphCtx.bindUav(0, 0, getRenderer().getTonemapping().getRt());
 
-		if(g_preferComputeCVar.get())
+		if(g_preferComputeCVar)
 		{
 			rgraphCtx.bindUav(1, 0, m_runCtx.m_renderRt);
 			rgraphCtx.bindUav(2, 0, m_runCtx.m_tonemappedRt);

+ 6 - 7
AnKi/Renderer/Tonemapping.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 
 #include <AnKi/Renderer/Tonemapping.h>
-#include <AnKi/Renderer/DownscaleBlur.h>
+#include <AnKi/Renderer/Bloom2.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Util/Tracer.h>
 
@@ -23,11 +23,10 @@ Error Tonemapping::init()
 
 Error Tonemapping::initInternal()
 {
-	m_inputTexMip = getRenderer().getDownscaleBlur().getMipmapCount() - 2;
-	const U32 width = getRenderer().getDownscaleBlur().getPassWidth(m_inputTexMip);
-	const U32 height = getRenderer().getDownscaleBlur().getPassHeight(m_inputTexMip);
+	m_inputTexMip = (getRenderer().getBloom2().getPyramidTextureMipmapCount() > 2) ? getRenderer().getBloom2().getPyramidTextureMipmapCount() - 2 : 0;
+	const UVec2 size = getRenderer().getBloom2().getPyramidTextureSize() >> m_inputTexMip;
 
-	ANKI_R_LOGV("Initializing tonemapping. Resolution %ux%u", width, height);
+	ANKI_R_LOGV("Initializing tonemapping. Resolution %ux%u", size.x(), size.y());
 
 	// Create program
 	ANKI_CHECK(loadShaderProgram("ShaderBinaries/TonemappingAverageLuminance.ankiprogbin", m_prog, m_grProg));
@@ -63,12 +62,12 @@ void Tonemapping::populateRenderGraph(RenderingContext& ctx)
 
 		cmdb.bindShaderProgram(m_grProg.get());
 		rgraphCtx.bindUav(0, 0, m_runCtx.m_exposureLuminanceHandle);
-		rgraphCtx.bindSrv(0, 0, getRenderer().getDownscaleBlur().getRt(), TextureSubresourceDesc::surface(m_inputTexMip, 0, 0));
+		rgraphCtx.bindSrv(0, 0, getRenderer().getBloom2().getPyramidRt(), TextureSubresourceDesc::surface(m_inputTexMip, 0, 0));
 
 		cmdb.dispatchCompute(1, 1, 1);
 	});
 
-	pass.newTextureDependency(getRenderer().getDownscaleBlur().getRt(), TextureUsageBit::kSrvCompute,
+	pass.newTextureDependency(getRenderer().getBloom2().getPyramidRt(), TextureUsageBit::kSrvCompute,
 							  TextureSubresourceDesc::surface(m_inputTexMip, 0, 0));
 }
 

+ 3 - 2
AnKi/Renderer/Utils/GpuVisibility.cpp

@@ -14,7 +14,8 @@
 #include <AnKi/Shaders/Include/GpuVisibilityTypes.h>
 #include <AnKi/Core/GpuMemory/UnifiedGeometryBuffer.h>
 #include <AnKi/Core/StatsSet.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
+#include <AnKi/Core/App.h>
 
 namespace anki {
 
@@ -45,7 +46,7 @@ static GpuVisLimits computeLimits(RenderingTechnique t)
 	const RenderStateBucketContainer& buckets = RenderStateBucketContainer::getSingleton();
 
 	const U32 meshletUserCount = buckets.getBucketsActiveUserCountWithMeshletSupport(t);
-	ANKI_ASSERT(meshletUserCount == 0 || (g_meshletRenderingCVar.get() || GrManager::getSingleton().getDeviceCapabilities().m_meshShaders));
+	ANKI_ASSERT(meshletUserCount == 0 || (g_meshletRenderingCVar || GrManager::getSingleton().getDeviceCapabilities().m_meshShaders));
 	out.m_totalLegacyRenderables = buckets.getBucketsActiveUserCountWithNoMeshletSupport(t);
 	out.m_maxVisibleLegacyRenderables = min(out.m_totalLegacyRenderables, kMaxVisibleObjects);
 

+ 4 - 4
AnKi/Renderer/VolumetricFog.cpp

@@ -9,7 +9,7 @@
 #include <AnKi/Renderer/ShadowMapping.h>
 #include <AnKi/Renderer/LightShading.h>
 #include <AnKi/Renderer/VolumetricLightingAccumulation.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Scene/Components/SkyboxComponent.h>
 #include <AnKi/Util/Tracer.h>
 
@@ -18,9 +18,9 @@ namespace anki {
 Error VolumetricFog::init()
 {
 	// Misc
-	const F32 qualityXY = g_volumetricLightingAccumulationQualityXYCVar.get();
-	const F32 qualityZ = g_volumetricLightingAccumulationQualityZCVar.get();
-	m_finalZSplit = min(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar.get());
+	const F32 qualityXY = g_volumetricLightingAccumulationQualityXYCVar;
+	const F32 qualityZ = g_volumetricLightingAccumulationQualityZCVar;
+	m_finalZSplit = min<U32>(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar);
 
 	m_volumeSize[0] = U32(F32(getRenderer().getTileCounts().x()) * qualityXY);
 	m_volumeSize[1] = U32(F32(getRenderer().getTileCounts().y()) * qualityXY);

+ 5 - 12
AnKi/Renderer/VolumetricLightingAccumulation.cpp

@@ -9,25 +9,18 @@
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/ClusterBinning.h>
 #include <AnKi/Resource/ImageResource.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Scene/Components/SkyboxComponent.h>
 #include <AnKi/Util/Tracer.h>
 
 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 = g_volumetricLightingAccumulationQualityXYCVar.get();
-	const F32 qualityZ = g_volumetricLightingAccumulationQualityZCVar.get();
-	const U32 finalZSplit = min(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar.get());
+	const F32 qualityXY = g_volumetricLightingAccumulationQualityXYCVar;
+	const F32 qualityZ = g_volumetricLightingAccumulationQualityZCVar;
+	const U32 finalZSplit = min<U32>(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar);
 
 	m_volumeSize[0] = U32(F32(getRenderer().getTileCounts().x()) * qualityXY);
 	m_volumeSize[1] = U32(F32(getRenderer().getTileCounts().y()) * qualityXY);
@@ -139,7 +132,7 @@ void VolumetricLightingAccumulation::populateRenderGraph(RenderingContext& ctx)
 		}
 		consts.m_volumeSize = UVec3(m_volumeSize);
 
-		const U32 finalZSplit = min(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar.get());
+		const U32 finalZSplit = min<U32>(getRenderer().getZSplitCount() - 1, g_volumetricLightingAccumulationFinalZSplitCVar);
 		consts.m_maxZSplitsToProcessf = F32(finalZSplit + 1);
 
 		cmdb.setFastConstants(&consts, sizeof(consts));

+ 7 - 5
AnKi/Renderer/VolumetricLightingAccumulation.h

@@ -9,14 +9,16 @@
 
 namespace anki {
 
-// Forward
-extern NumericCVar<F32> g_volumetricLightingAccumulationQualityXYCVar;
-extern NumericCVar<F32> g_volumetricLightingAccumulationQualityZCVar;
-extern NumericCVar<U32> g_volumetricLightingAccumulationFinalZSplitCVar;
-
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<F32> g_volumetricLightingAccumulationQualityXYCVar("R", "VolumetricLightingAccumulationQualityXY", 4.0f, 1.0f, 16.0f,
+																	  "Quality of XY dimensions of volumetric lights");
+inline NumericCVar<F32> g_volumetricLightingAccumulationQualityZCVar("R", "VolumetricLightingAccumulationQualityZ", 4.0f, 1.0f, 16.0f,
+																	 "Quality of Z dimension of volumetric lights");
+inline NumericCVar<U32> g_volumetricLightingAccumulationFinalZSplitCVar("R", "VolumetricLightingAccumulationFinalZSplit", 26, 1, 256,
+																		"Final cluster split that will recieve volumetric lights");
+
 /// Volumetric lighting. It accumulates lighting in a volume texture.
 class VolumetricLightingAccumulation : public RendererObject
 {

+ 5 - 8
AnKi/Renderer/VrsSriGeneration.cpp

@@ -6,14 +6,11 @@
 #include <AnKi/Renderer/VrsSriGeneration.h>
 #include <AnKi/Renderer/Renderer.h>
 #include <AnKi/Renderer/LightShading.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 
 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();
@@ -66,7 +63,7 @@ Error VrsSriGeneration::initInternal()
 		variantInit.addMutation("SHARED_MEMORY", 1);
 	}
 
-	variantInit.addMutation("LIMIT_RATE_TO_2X2", g_vrsLimitTo2x2CVar.get());
+	variantInit.addMutation("LIMIT_RATE_TO_2X2", g_vrsLimitTo2x2CVar);
 
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(variantInit, variant);
@@ -96,7 +93,7 @@ void VrsSriGeneration::getDebugRenderTarget(CString rtName, Array<RenderTargetHa
 
 void VrsSriGeneration::importRenderTargets(RenderingContext& ctx)
 {
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar;
 	if(!enableVrs)
 	{
 		return;
@@ -117,7 +114,7 @@ void VrsSriGeneration::importRenderTargets(RenderingContext& ctx)
 
 void VrsSriGeneration::populateRenderGraph(RenderingContext& ctx)
 {
-	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar.get();
+	const Bool enableVrs = GrManager::getSingleton().getDeviceCapabilities().m_vrs && g_vrsCVar;
 	if(!enableVrs)
 	{
 		return;
@@ -143,7 +140,7 @@ void VrsSriGeneration::populateRenderGraph(RenderingContext& ctx)
 			rgraphCtx.bindSrv(0, 0, getRenderer().getLightShading().getRt());
 			cmdb.bindSampler(0, 0, getRenderer().getSamplers().m_nearestNearestClamp.get());
 			rgraphCtx.bindUav(0, 0, m_runCtx.m_rt);
-			const Vec4 pc(1.0f / Vec2(getRenderer().getInternalResolution()), g_vrsThresholdCVar.get(), 0.0f);
+			const Vec4 pc(1.0f / Vec2(getRenderer().getInternalResolution()), g_vrsThresholdCVar, 0.0f);
 			cmdb.setFastConstants(&pc, sizeof(pc));
 
 			const U32 fakeWorkgroupSizeXorY = m_sriTexelDimension;

+ 2 - 0
AnKi/Renderer/VrsSriGeneration.h

@@ -12,6 +12,8 @@ namespace anki {
 /// @addtogroup renderer
 /// @{
 
+inline NumericCVar<F32> g_vrsThresholdCVar("R", "VrsThreshold", 0.1f, 0.0f, 1.0f, "Threshold under which a lower shading rate will be applied");
+
 /// Computes the shading rate image to be used by a number of passes.
 class VrsSriGeneration : public RendererObject
 {

+ 2 - 4
AnKi/Resource/ImageResource.cpp

@@ -7,13 +7,11 @@
 #include <AnKi/Resource/ImageLoader.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Resource/AsyncLoader.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Filesystem.h>
 
 namespace anki {
 
-static NumericCVar<U32> g_maxImageSizeCVar(CVarSubsystem::kResource, "MaxImageSize", 1024u * 1024u, 4u, kMaxU32, "Max image size to load");
-
 class ImageResource::LoadingContext
 {
 public:
@@ -68,7 +66,7 @@ Error ImageResource::load(const ResourceFilename& filename, Bool async)
 	ResourceFilePtr file;
 	ANKI_CHECK(openFile(filename, file));
 
-	ANKI_CHECK(loader.load(file, filename, g_maxImageSizeCVar.get()));
+	ANKI_CHECK(loader.load(file, filename, g_maxImageSizeCVar));
 
 	// Various sizes
 	init.m_width = loader.getWidth();

+ 2 - 0
AnKi/Resource/ImageResource.h

@@ -13,6 +13,8 @@ namespace anki {
 /// @addtogroup resource
 /// @{
 
+inline NumericCVar<U32> g_maxImageSizeCVar("Rsrc", "MaxImageSize", 1024u * 1024u, 4u, kMaxU32, "Max image size to load");
+
 /// Image resource class. It loads or creates an image and then loads it in the GPU. It supports compressed and uncompressed TGAs, PNGs, JPEG and
 /// AnKi's image format.
 class ImageResource : public ResourceObject

+ 1 - 1
AnKi/Resource/MaterialResource.cpp

@@ -522,7 +522,7 @@ const MaterialVariant& MaterialResource::getOrCreateVariant(const RenderingKey&
 	}
 
 	const Bool meshShadersSupported = GrManager::getSingleton().getDeviceCapabilities().m_meshShaders;
-	ANKI_ASSERT(!(key.getMeshletRendering() && (!meshShadersSupported && !g_meshletRenderingCVar.get()))
+	ANKI_ASSERT(!(key.getMeshletRendering() && (!meshShadersSupported && !g_meshletRenderingCVar))
 				&& "Can't be asking for meshlet rendering if mesh shaders or SW meshlet rendering are not supported/enabled");
 	if(key.getMeshletRendering() && !(m_shaderTechniques & (ShaderTechniqueBit::kMeshSaders | ShaderTechniqueBit::kSwMeshletRendering)))
 	{

+ 2 - 4
AnKi/Resource/MeshResource.cpp

@@ -9,12 +9,10 @@
 #include <AnKi/Resource/AsyncLoader.h>
 #include <AnKi/Util/Functions.h>
 #include <AnKi/Util/Filesystem.h>
+#include <AnKi/Core/App.h>
 
 namespace anki {
 
-// Forward
-extern BoolCVar g_meshletRenderingCVar;
-
 class MeshResource::LoadContext
 {
 public:
@@ -145,7 +143,7 @@ Error MeshResource::load(const ResourceFilename& filename, Bool async)
 		}
 
 		// Meshlet
-		if(GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_meshletRenderingCVar.get())
+		if(GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_meshletRenderingCVar)
 		{
 			const PtrSize meshletIndicesSize = header.m_meshletPrimitiveCounts[l] * sizeof(U8Vec4);
 			lod.m_meshletIndices = UnifiedGeometryBuffer::getSingleton().allocate(meshletIndicesSize, sizeof(U8Vec4));

+ 2 - 4
AnKi/Resource/ModelResource.cpp

@@ -8,12 +8,10 @@
 #include <AnKi/Resource/MeshResource.h>
 #include <AnKi/Util/Xml.h>
 #include <AnKi/Util/Logger.h>
+#include <AnKi/Core/App.h>
 
 namespace anki {
 
-// Forward
-extern BoolCVar g_meshletRenderingCVar;
-
 void ModelPatch::getGeometryInfo(U32 lod, ModelPatchGeometryInfo& inf) const
 {
 	lod = min<U32>(lod, m_meshLodCount - 1);
@@ -118,7 +116,7 @@ Error ModelPatch::init([[maybe_unused]] ModelResource* model, CString meshFName,
 			}
 		}
 
-		if(GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_meshletRenderingCVar.get())
+		if(GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_meshletRenderingCVar)
 		{
 			U32 dummy;
 			m_mesh->getMeshletBufferInfo(l, lod.m_meshletBoundingVolumesUgbOffset, lod.m_meshletGometryDescriptorsUgbOffset, dummy);

+ 3 - 3
AnKi/Resource/ResourceFilesystem.cpp

@@ -5,7 +5,7 @@
 
 #include <AnKi/Resource/ResourceFilesystem.h>
 #include <AnKi/Util/Filesystem.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <ZLib/contrib/minizip/unzip.h>
 #if ANKI_OS_ANDROID
@@ -14,7 +14,7 @@
 
 namespace anki {
 
-StringCVar g_dataPathsCVar(CVarSubsystem::kResource, "DataPaths", ".",
+StringCVar g_dataPathsCVar("Rsrc", "DataPaths", ".",
 						   "The engine loads assets only in from these paths. Separate them with : (it's smart enough to identify drive letters in "
 						   "Windows). After a path you can add an optional | and what follows it is a number of words to include or exclude paths. "
 						   "eg. my_path|include_this,include_that,+exclude_this");
@@ -236,7 +236,7 @@ ResourceFilesystem::~ResourceFilesystem()
 Error ResourceFilesystem::init()
 {
 	ResourceStringList paths;
-	paths.splitString(g_dataPathsCVar.get(), ':');
+	paths.splitString(g_dataPathsCVar, ':');
 
 	// Workaround the fact that : is used in drives in Windows
 #if ANKI_OS_WINDOWS

+ 1 - 1
AnKi/Resource/ResourceFilesystem.h

@@ -10,7 +10,7 @@
 #include <AnKi/Util/StringList.h>
 #include <AnKi/Util/File.h>
 #include <AnKi/Util/Ptr.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 namespace anki {
 

+ 2 - 5
AnKi/Resource/ResourceManager.cpp

@@ -8,7 +8,7 @@
 #include <AnKi/Resource/ShaderProgramResourceSystem.h>
 #include <AnKi/Resource/AnimationResource.h>
 #include <AnKi/Util/Logger.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 #include <AnKi/Resource/MaterialResource.h>
 #include <AnKi/Resource/MeshResource.h>
@@ -25,9 +25,6 @@
 
 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()
 {
 }
@@ -57,7 +54,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(g_transferScratchMemorySizeCVar.get()));
+	ANKI_CHECK(m_transferGpuAlloc->init(g_transferScratchMemorySizeCVar));
 
 	// Init the programs
 	m_shaderProgramSystem = newInstance<ShaderProgramResourceSystem>(ResourceMemoryPool::getSingleton());

+ 3 - 0
AnKi/Resource/ResourceManager.h

@@ -25,6 +25,9 @@ class ShaderProgramResourceSystem;
 /// @addtogroup resource
 /// @{
 
+inline NumericCVar<PtrSize> g_transferScratchMemorySizeCVar("Rsrc", "TransferScratchMemorySize", 256_MB, 1_MB, 4_GB,
+															"Memory that is used fot texture and buffer uploads");
+
 /// Manage resources of a certain type
 template<typename Type>
 class TypeResourceManager

+ 1 - 1
AnKi/Resource/ShaderProgramResource.cpp

@@ -10,7 +10,7 @@
 #include <AnKi/Gr/GrManager.h>
 #include <AnKi/Util/Filesystem.h>
 #include <AnKi/Util/Functions.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 namespace anki {
 

+ 1 - 1
AnKi/Resource/ShaderProgramResourceSystem.cpp

@@ -12,7 +12,7 @@
 #include <AnKi/Util/Filesystem.h>
 #include <AnKi/Util/System.h>
 #include <AnKi/Util/BitSet.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 
 namespace anki {
 

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

@@ -7,7 +7,6 @@
 
 #include <AnKi/Scene/Components/SceneComponent.h>
 #include <AnKi/Scene/Frustum.h>
-#include <AnKi/Core/CVarSet.h>
 
 namespace anki {
 

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

@@ -7,7 +7,7 @@
 #include <AnKi/Scene/Components/MoveComponent.h>
 #include <AnKi/Scene/SceneNode.h>
 #include <AnKi/Scene/SceneGraph.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Gr/Texture.h>
 #include <AnKi/Gr/CommandBuffer.h>
@@ -139,13 +139,13 @@ F32 GlobalIlluminationProbeComponent::getRenderRadius() const
 {
 	F32 effectiveDistance = max(m_halfSize.x(), m_halfSize.y());
 	effectiveDistance = max(effectiveDistance, m_halfSize.z());
-	effectiveDistance = max(effectiveDistance, g_probeEffectiveDistanceCVar.get());
+	effectiveDistance = max<F32>(effectiveDistance, g_probeEffectiveDistanceCVar);
 	return effectiveDistance;
 }
 
 F32 GlobalIlluminationProbeComponent::getShadowsRenderRadius() const
 {
-	return min(getRenderRadius(), g_probeShadowEffectiveDistanceCVar.get());
+	return min<F32>(getRenderRadius(), g_probeShadowEffectiveDistanceCVar);
 }
 
 } // end namespace anki

+ 1 - 1
AnKi/Scene/Components/ModelComponent.cpp

@@ -278,7 +278,7 @@ Error ModelComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
 				key.setRenderingTechnique(t);
 				key.setSkinned(hasSkin);
 				key.setVelocity(moved);
-				key.setMeshletRendering(GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_meshletRenderingCVar.get());
+				key.setMeshletRendering(GrManager::getSingleton().getDeviceCapabilities().m_meshShaders || g_meshletRenderingCVar);
 
 				const MaterialVariant& mvariant = m_model->getModelPatches()[i].getMaterial()->getOrCreateVariant(key);
 

+ 4 - 7
AnKi/Scene/Components/ReflectionProbeComponent.cpp

@@ -7,14 +7,11 @@
 #include <AnKi/Scene/Components/MoveComponent.h>
 #include <AnKi/Scene/SceneGraph.h>
 #include <AnKi/Scene/SceneNode.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Gr/Texture.h>
 
 namespace anki {
 
-NumericCVar<U32> g_reflectionProbeResolutionCVar(CVarSubsystem::kScene, "ReflectionProbeResolution", 128, 8, 2048,
-												 "The resolution of the reflection probe's reflection");
-
 ReflectionProbeComponent::ReflectionProbeComponent(SceneNode* node)
 	: SceneComponent(node, kClassType)
 {
@@ -24,7 +21,7 @@ ReflectionProbeComponent::ReflectionProbeComponent(SceneNode* node)
 	TextureInitInfo texInit("ReflectionProbe");
 	texInit.m_format =
 		(GrManager::getSingleton().getDeviceCapabilities().m_unalignedBbpTextureFormats) ? Format::kR16G16B16_Sfloat : Format::kR16G16B16A16_Sfloat;
-	texInit.m_width = g_reflectionProbeResolutionCVar.get();
+	texInit.m_width = g_reflectionProbeResolutionCVar;
 	texInit.m_height = texInit.m_width;
 	texInit.m_mipmapCount = U8(computeMaxMipmapCount2d(texInit.m_width, texInit.m_height, 8));
 	texInit.m_type = TextureType::kCube;
@@ -78,13 +75,13 @@ F32 ReflectionProbeComponent::getRenderRadius() const
 {
 	F32 effectiveDistance = max(m_halfSize.x(), m_halfSize.y());
 	effectiveDistance = max(effectiveDistance, m_halfSize.z());
-	effectiveDistance = max(effectiveDistance, g_probeEffectiveDistanceCVar.get());
+	effectiveDistance = max<F32>(effectiveDistance, g_probeEffectiveDistanceCVar);
 	return effectiveDistance;
 }
 
 F32 ReflectionProbeComponent::getShadowsRenderRadius() const
 {
-	return min(getRenderRadius(), g_probeShadowEffectiveDistanceCVar.get());
+	return min<F32>(getRenderRadius(), g_probeShadowEffectiveDistanceCVar);
 }
 
 } // end namespace anki

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

@@ -12,11 +12,12 @@
 
 namespace anki {
 
-extern NumericCVar<U32> g_reflectionProbeResolutionCVar;
-
 /// @addtogroup scene
 /// @{
 
+inline NumericCVar<U32> g_reflectionProbeResolutionCVar("Scene", "ReflectionProbeResolution", 128, 8, 2048,
+														"The resolution of the reflection probe's reflection");
+
 /// Reflection probe component.
 class ReflectionProbeComponent : public SceneComponent
 {

+ 1 - 1
AnKi/Scene/DeveloperConsoleUiNode.cpp

@@ -156,7 +156,7 @@ void DeveloperConsoleUiNode::draw(CanvasPtr& canvas)
 		const Error err = m_scriptEnv.evalString(&m_inputText[0]);
 		if(!err)
 		{
-			ANKI_CORE_LOGI("Script ran without errors");
+			ANKI_SCENE_LOGI("Script ran without errors");
 		}
 		m_inputText[0] = '\0';
 	}

+ 4 - 31
AnKi/Scene/SceneGraph.cpp

@@ -7,7 +7,7 @@
 #include <AnKi/Scene/RenderStateBucket.h>
 #include <AnKi/Physics/PhysicsWorld.h>
 #include <AnKi/Resource/ResourceManager.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
 #include <AnKi/Core/StatsSet.h>
 #include <AnKi/Util/Tracer.h>
 #include <AnKi/Util/HighRezTimer.h>
@@ -41,33 +41,6 @@ static StatCounter g_sceneUpdateTimeStatVar(StatCategory::kTime, "All scene upda
 static StatCounter g_scenePhysicsTimeStatVar(StatCategory::kTime, "Physics",
 											 StatFlag::kMilisecond | StatFlag::kShowAverage | StatFlag::kMainThreadUpdates);
 
-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");
-
-// Gpu scene arrays
-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");
-
 constexpr U32 kUpdateNodeBatchSize = 10;
 
 class SceneGraph::UpdateSceneNodesCtx
@@ -111,17 +84,17 @@ Error SceneGraph::init(AllocAlignedCallback allocCallback, void* allocCallbackDa
 	camc->setPerspective(0.1f, 1000.0f, toRad(60.0f), (1080.0f / 1920.0f) * toRad(60.0f));
 	m_mainCam = m_defaultMainCam;
 
-#define ANKI_CAT_TYPE(arrayName, gpuSceneType, id, cvarName) GpuSceneArrays::arrayName::allocateSingleton(cvarName.get());
+#define ANKI_CAT_TYPE(arrayName, gpuSceneType, id, cvarName) GpuSceneArrays::arrayName::allocateSingleton(U32(cvarName));
 #include <AnKi/Scene/GpuSceneArrays.def.h>
 
 	RenderStateBucketContainer::allocateSingleton();
 
 	// Construct a few common nodex
-	if(g_displayStatsCVar.get() > 0)
+	if(g_displayStatsCVar > 0)
 	{
 		StatsUiNode* statsNode;
 		ANKI_CHECK(newSceneNode("_StatsUi", statsNode));
-		statsNode->setFpsOnly(g_displayStatsCVar.get() == 1);
+		statsNode->setFpsOnly(g_displayStatsCVar == 1);
 	}
 
 	DeveloperConsoleUiNode* consoleNode;

+ 26 - 6
AnKi/Scene/SceneGraph.h

@@ -12,18 +12,38 @@
 #include <AnKi/Util/BlockArray.h>
 #include <AnKi/Scene/Events/EventManager.h>
 #include <AnKi/Resource/Common.h>
-#include <AnKi/Core/CVarSet.h>
+#include <AnKi/Util/CVarSet.h>
+#include <AnKi/Core/Common.h>
 
 namespace anki {
 
-// Forward
-class RenderQueue;
-extern NumericCVar<F32> g_probeEffectiveDistanceCVar;
-extern NumericCVar<F32> g_probeShadowEffectiveDistanceCVar;
-
 /// @addtogroup scene
 /// @{
 
+inline NumericCVar<F32> g_probeEffectiveDistanceCVar("Scene", "ProbeEffectiveDistance", 256.0f, 1.0f, kMaxF32, "How far various probes can render");
+inline NumericCVar<F32> g_probeShadowEffectiveDistanceCVar("Scene", "ProbeShadowEffectiveDistance", 32.0f, 1.0f, kMaxF32,
+														   "How far to render shadows for the various probes");
+
+// Gpu scene arrays
+inline NumericCVar<U32> g_minGpuSceneTransformsCVar("Scene", "MinGpuSceneTransforms", 2 * 10 * 1024, 8, 100 * 1024,
+													"The min number of transforms stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneMeshesCVar("Scene", "MinGpuSceneMeshes", 8 * 1024, 8, 100 * 1024,
+												"The min number of meshes stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneParticleEmittersCVar("Scene", "MinGpuSceneParticleEmitters", 1 * 1024, 8, 100 * 1024,
+														  "The min number of particle emitters stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneLightsCVar("Scene", "MinGpuSceneLights", 2 * 1024, 8, 100 * 1024,
+												"The min number of lights stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneReflectionProbesCVar("Scene", "MinGpuSceneReflectionProbes", 128, 8, 100 * 1024,
+														  "The min number of reflection probes stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneGlobalIlluminationProbesCVar("Scene", "MinGpuSceneGlobalIlluminationProbes", 128, 8, 100 * 1024,
+																  "The min number of GI probes stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneDecalsCVar("Scene", "MinGpuSceneDecals", 2 * 1024, 8, 100 * 1024,
+												"The min number of decals stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneFogDensityVolumesCVar("Scene", "MinGpuSceneFogDensityVolumes", 512, 8, 100 * 1024,
+														   "The min number fog density volumes stored in the GPU scene");
+inline NumericCVar<U32> g_minGpuSceneRenderablesCVar("Scene", "MinGpuSceneRenderables", 10 * 1024, 8, 100 * 1024,
+													 "The min number of renderables stored in the GPU scene");
+
 class SceneComponentArrays
 {
 public:

+ 1 - 0
AnKi/Scene/StatsUiNode.cpp

@@ -9,6 +9,7 @@
 #include <AnKi/Core/App.h>
 #include <AnKi/Ui/UiManager.h>
 #include <AnKi/Ui/Font.h>
+#include <AnKi/Renderer/Renderer.h>
 
 namespace anki {
 

+ 0 - 71
AnKi/Shaders/Bloom.ankiprog

@@ -1,71 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Shaders/QuadVert.hlsl>
-#if ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER
-#	include <AnKi/Shaders/TonemappingFunctions.hlsl>
-#	include <AnKi/Shaders/Functions.hlsl>
-
-SamplerState g_linearAnyClampSampler : register(s0);
-Texture2D<RVec4> g_inTex : register(t0);
-
-#	define TONEMAPPING_REGISTER u0
-#	include <AnKi/Shaders/TonemappingResources.hlsl>
-
-struct Consts
-{
-	RF32 m_threshold;
-	F32 m_scale;
-	F32 m_padding0;
-	F32 m_padding1;
-};
-ANKI_FAST_CONSTANTS(Consts, g_consts)
-
-#	if ANKI_COMPUTE_SHADER
-#		define THREADGROUP_SIZE_X 8
-#		define THREADGROUP_SIZE_Y 8
-RWTexture2D<RVec4> g_storageTex : register(u1);
-#	endif
-
-#	if ANKI_COMPUTE_SHADER
-[numthreads(THREADGROUP_SIZE_X, THREADGROUP_SIZE_Y, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
-#	else
-RVec3 main(VertOut input) : SV_TARGET0
-#	endif
-{
-#	if ANKI_COMPUTE_SHADER
-	Vec2 imgSize;
-	g_storageTex.GetDimensions(imgSize.x, imgSize.y);
-
-	const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / imgSize;
-#	else
-	const Vec2 uv = input.m_uv;
-#	endif
-
-	const RF32 weight = 1.0 / 5.0;
-	RVec3 color = g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb * weight;
-	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)).rgb * weight;
-	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)).rgb * weight;
-	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)).rgb * weight;
-	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)).rgb * weight;
-
-	color = tonemap(color, readExposureAndAverageLuminance().y, g_consts.m_threshold) * g_consts.m_scale;
-
-#	if ANKI_COMPUTE_SHADER
-	g_storageTex[svDispatchThreadId] = RVec4(color, 0.0);
-#	else
-	return color;
-#	endif
-}
-#endif // ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER
-
-#pragma anki technique_start vert
-#pragma anki technique_end vert
-
-#pragma anki technique_start pixel
-#pragma anki technique_end pixel
-
-#pragma anki technique_start comp
-#pragma anki technique_end comp

+ 250 - 0
AnKi/Shaders/Bloom2.ankiprog

@@ -0,0 +1,250 @@
+// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Shaders/QuadVert.hlsl>
+
+// ===========================================================================
+// Downscale                                                                 =
+// ===========================================================================
+#if(ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Downscale
+#	include <AnKi/Shaders/Functions.hlsl>
+
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<RVec3> g_tex : register(t0);
+
+struct Constants
+{
+	Vec2 m_fbSize;
+	UVec2 m_padding;
+};
+ANKI_FAST_CONSTANTS(Constants, g_consts)
+
+#	if ANKI_COMPUTE_SHADER
+RWTexture2D<RVec4> g_storageTex : register(u1);
+#	endif
+
+#	if ANKI_COMPUTE_SHADER
+[numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
+{
+	const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / g_consts.m_fbSize;
+#	else
+RVec3 main(VertOut input) : SV_TARGET0
+{
+	const Vec2 uv = input.m_uv;
+#	endif
+
+	RVec3 output;
+	const RF32 weight = 1.0 / 5.0;
+	output = g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0) * weight;
+	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)) * weight;
+	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)) * weight;
+	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)) * weight;
+	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)) * weight;
+
+#	if ANKI_COMPUTE_SHADER
+	g_storageTex[svDispatchThreadId] = RVec4(output, 1.0);
+#	else
+	return output;
+#	endif
+}
+#endif // (ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Downscale
+
+// ===========================================================================
+// Exposure                                                                  =
+// ===========================================================================
+#if(ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Exposure
+#	include <AnKi/Shaders/TonemappingFunctions.hlsl>
+#	include <AnKi/Shaders/Functions.hlsl>
+
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<RVec4> g_inTex : register(t0);
+
+#	define TONEMAPPING_REGISTER u0
+#	include <AnKi/Shaders/TonemappingResources.hlsl>
+
+struct Consts
+{
+	RF32 m_threshold;
+	F32 m_scale;
+	F32 m_padding0;
+	F32 m_padding1;
+};
+ANKI_FAST_CONSTANTS(Consts, g_consts)
+
+#	if ANKI_COMPUTE_SHADER
+RWTexture2D<RVec4> g_storageTex : register(u1);
+#	endif
+
+#	if ANKI_COMPUTE_SHADER
+[numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
+#	else
+RVec3 main(VertOut input) : SV_TARGET0
+#	endif
+{
+#	if ANKI_COMPUTE_SHADER
+	Vec2 imgSize;
+	g_storageTex.GetDimensions(imgSize.x, imgSize.y);
+
+	const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / imgSize;
+#	else
+	const Vec2 uv = input.m_uv;
+#	endif
+
+	const RF32 weight = 1.0 / 5.0;
+	RVec3 color = g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb * weight;
+	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)).rgb * weight;
+	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)).rgb * weight;
+	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)).rgb * weight;
+	color += g_inTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)).rgb * weight;
+
+	color = tonemap(color, readExposureAndAverageLuminance().y, g_consts.m_threshold) * g_consts.m_scale;
+
+#	if ANKI_COMPUTE_SHADER
+	g_storageTex[svDispatchThreadId] = RVec4(color, 0.0);
+#	else
+	return color;
+#	endif
+}
+#endif // (ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER) && ANKI_TECHNIQUE_Exposure
+
+// ===========================================================================
+// Upscale                                                                   =
+// ===========================================================================
+#if(ANKI_PIXEL_SHADER || ANKI_COMPUTE_SHADER) && ANKI_TECHNIQUE_Upscale
+#	include <AnKi/Shaders/Functions.hlsl>
+
+// Constants
+#	define ENABLE_CHROMATIC_DISTORTION 1
+#	define ENABLE_HALO 1
+constexpr U32 kMaxGhosts = 4u;
+constexpr F32 kGhostDispersal = 0.7;
+constexpr F32 kHaloWidth = 0.4;
+constexpr F32 kChromaticDistortion = 3.0;
+constexpr F32 kHaloOpacity = 0.5;
+
+SamplerState g_linearAnyClampSampler : register(s0);
+Texture2D<RVec4> g_inputTex : register(t0);
+Texture2D<RVec3> g_lensDirtTex : register(t1);
+
+#	if ANKI_COMPUTE_SHADER
+RWTexture2D<RVec4> g_storageTex : register(u0);
+#	endif
+
+RVec3 textureDistorted(Texture2D<RVec4> tex, SamplerState sampl, Vec2 uv,
+					   Vec2 direction, // direction of distortion
+					   Vec3 distortion) // per-channel distortion factor
+{
+#	if ENABLE_CHROMATIC_DISTORTION
+	return RVec3(tex.SampleLevel(sampl, uv + direction * distortion.r, 0.0).r, tex.SampleLevel(sampl, uv + direction * distortion.g, 0.0).g,
+				 tex.SampleLevel(sampl, uv + direction * distortion.b, 0.0).b);
+#	else
+	return tex.SampleLevel(uv, 0.0).rgb;
+#	endif
+}
+
+RVec3 ssLensFlare(Vec2 uv)
+{
+	Vec2 textureSize;
+	g_inputTex.GetDimensions(textureSize.x, textureSize.y);
+
+	const Vec2 texelSize = 1.0 / textureSize;
+	const Vec3 distortion = Vec3(-texelSize.x * kChromaticDistortion, 0.0, texelSize.x * kChromaticDistortion);
+	const F32 lensOfHalf = length(Vec2(0.5, 0.5));
+
+	const Vec2 flipUv = Vec2(1.0, 1.0) - uv;
+
+	const Vec2 ghostVec = (Vec2(0.5, 0.5) - flipUv) * kGhostDispersal;
+
+	const Vec2 direction = normalize(ghostVec);
+	RVec3 result = Vec3(0.0, 0.0, 0.0);
+
+	// Sample ghosts
+	[unroll] for(U32 i = 0u; i < kMaxGhosts; ++i)
+	{
+		const Vec2 offset = frac(flipUv + ghostVec * F32(i));
+
+		RF32 weight = length(Vec2(0.5, 0.5) - offset) / lensOfHalf;
+		weight = pow(1.0 - weight, 10.0);
+
+		result += textureDistorted(g_inputTex, g_linearAnyClampSampler, offset, direction, distortion) * weight;
+	}
+
+	// Sample halo
+#	if ENABLE_HALO
+	const Vec2 haloVec = normalize(ghostVec) * kHaloWidth;
+	RF32 weight = length(Vec2(0.5, 0.5) - frac(flipUv + haloVec)) / lensOfHalf;
+	weight = pow(1.0 - weight, 20.0);
+	result += textureDistorted(g_inputTex, g_linearAnyClampSampler, flipUv + haloVec, direction, distortion) * (weight * kHaloOpacity);
+#	endif
+
+	// Lens dirt
+	result *= g_lensDirtTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb;
+
+	return result;
+}
+
+RVec3 upscale(Vec2 uv)
+{
+	const RF32 weight = 1.0 / 5.0;
+	RVec3 result = g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)).rgb * weight;
+	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)).rgb * weight;
+
+	return result;
+}
+
+#	if ANKI_COMPUTE_SHADER
+[numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
+#	else
+RVec3 main(VertOut input) : SV_TARGET0
+#	endif
+{
+#	if ANKI_COMPUTE_SHADER
+	Vec2 storageTexSize;
+	g_storageTex.GetDimensions(storageTexSize.x, storageTexSize.y);
+
+	const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / storageTexSize;
+#	else
+	const Vec2 uv = input.m_uv;
+#	endif
+
+	const RVec3 outColor = ssLensFlare(uv) + upscale(uv);
+
+#	if ANKI_COMPUTE_SHADER
+	g_storageTex[svDispatchThreadId] = RVec4(outColor, 0.0);
+#	else
+	return outColor;
+#	endif
+}
+#endif // (ANKI_PIXEL_SHADER || ANKI_COMPUTE_SHADER) && ANKI_TECHNIQUE_Upscale
+
+#pragma anki technique_start vert Downscale
+#pragma anki technique_end vert Downscale
+
+#pragma anki technique_start pixel Downscale
+#pragma anki technique_end pixel Downscale
+
+#pragma anki technique_start comp Downscale
+#pragma anki technique_end comp Downscale
+
+#pragma anki technique_start vert Exposure
+#pragma anki technique_end vert Exposure
+
+#pragma anki technique_start pixel Exposure
+#pragma anki technique_end pixel Exposure
+
+#pragma anki technique_start comp Exposure
+#pragma anki technique_end comp Exposure
+
+#pragma anki technique_start vert Upscale
+#pragma anki technique_end vert Upscale
+
+#pragma anki technique_start pixel Upscale
+#pragma anki technique_end pixel Upscale
+
+#pragma anki technique_start comp Upscale
+#pragma anki technique_end comp Upscale

+ 0 - 125
AnKi/Shaders/BloomUpscale.ankiprog

@@ -1,125 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Shaders/QuadVert.hlsl>
-#if ANKI_PIXEL_SHADER || ANKI_COMPUTE_SHADER
-#	include <AnKi/Shaders/Functions.hlsl>
-
-// Constants
-#	define ENABLE_CHROMATIC_DISTORTION 1
-#	define ENABLE_HALO 1
-constexpr U32 kMaxGhosts = 4u;
-constexpr F32 kGhostDispersal = 0.7;
-constexpr F32 kHaloWidth = 0.4;
-constexpr F32 kChromaticDistortion = 3.0;
-constexpr F32 kHaloOpacity = 0.5;
-
-SamplerState g_linearAnyClampSampler : register(s0);
-Texture2D<RVec4> g_inputTex : register(t0);
-Texture2D<RVec3> g_lensDirtTex : register(t1);
-
-#	if ANKI_COMPUTE_SHADER
-#		define THREADGROUP_SIZE_XY 8
-RWTexture2D<RVec4> g_storageTex : register(u0);
-#	endif
-
-RVec3 textureDistorted(Texture2D<RVec4> tex, SamplerState sampl, Vec2 uv,
-					   Vec2 direction, // direction of distortion
-					   Vec3 distortion) // per-channel distortion factor
-{
-#	if ENABLE_CHROMATIC_DISTORTION
-	return RVec3(tex.SampleLevel(sampl, uv + direction * distortion.r, 0.0).r, tex.SampleLevel(sampl, uv + direction * distortion.g, 0.0).g,
-				 tex.SampleLevel(sampl, uv + direction * distortion.b, 0.0).b);
-#	else
-	return tex.SampleLevel(uv, 0.0).rgb;
-#	endif
-}
-
-RVec3 ssLensFlare(Vec2 uv)
-{
-	Vec2 textureSize;
-	g_inputTex.GetDimensions(textureSize.x, textureSize.y);
-
-	const Vec2 texelSize = 1.0 / textureSize;
-	const Vec3 distortion = Vec3(-texelSize.x * kChromaticDistortion, 0.0, texelSize.x * kChromaticDistortion);
-	const F32 lensOfHalf = length(Vec2(0.5, 0.5));
-
-	const Vec2 flipUv = Vec2(1.0, 1.0) - uv;
-
-	const Vec2 ghostVec = (Vec2(0.5, 0.5) - flipUv) * kGhostDispersal;
-
-	const Vec2 direction = normalize(ghostVec);
-	RVec3 result = Vec3(0.0, 0.0, 0.0);
-
-	// Sample ghosts
-	[unroll] for(U32 i = 0u; i < kMaxGhosts; ++i)
-	{
-		const Vec2 offset = frac(flipUv + ghostVec * F32(i));
-
-		RF32 weight = length(Vec2(0.5, 0.5) - offset) / lensOfHalf;
-		weight = pow(1.0 - weight, 10.0);
-
-		result += textureDistorted(g_inputTex, g_linearAnyClampSampler, offset, direction, distortion) * weight;
-	}
-
-	// Sample halo
-#	if ENABLE_HALO
-	const Vec2 haloVec = normalize(ghostVec) * kHaloWidth;
-	RF32 weight = length(Vec2(0.5, 0.5) - frac(flipUv + haloVec)) / lensOfHalf;
-	weight = pow(1.0 - weight, 20.0);
-	result += textureDistorted(g_inputTex, g_linearAnyClampSampler, flipUv + haloVec, direction, distortion) * (weight * kHaloOpacity);
-#	endif
-
-	// Lens dirt
-	result *= g_lensDirtTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb;
-
-	return result;
-}
-
-RVec3 upscale(Vec2 uv)
-{
-	const RF32 weight = 1.0 / 5.0;
-	RVec3 result = g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0).rgb * weight;
-	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)).rgb * weight;
-	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)).rgb * weight;
-	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)).rgb * weight;
-	result += g_inputTex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)).rgb * weight;
-
-	return result;
-}
-
-#	if ANKI_COMPUTE_SHADER
-[numthreads(THREADGROUP_SIZE_XY, THREADGROUP_SIZE_XY, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
-#	else
-RVec3 main(VertOut input) : SV_TARGET0
-#	endif
-{
-#	if ANKI_COMPUTE_SHADER
-	Vec2 storageTexSize;
-	g_storageTex.GetDimensions(storageTexSize.x, storageTexSize.y);
-
-	const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / storageTexSize;
-#	else
-	const Vec2 uv = input.m_uv;
-#	endif
-
-	const RVec3 outColor = ssLensFlare(uv) + upscale(uv);
-
-#	if ANKI_COMPUTE_SHADER
-	g_storageTex[svDispatchThreadId] = RVec4(outColor, 0.0);
-#	else
-	return outColor;
-#	endif
-}
-#endif // ANKI_PIXEL_SHADER || ANKI_COMPUTE_SHADER
-
-#pragma anki technique_start vert
-#pragma anki technique_end vert
-
-#pragma anki technique_start pixel
-#pragma anki technique_end pixel
-
-#pragma anki technique_start comp
-#pragma anki technique_end comp

+ 0 - 63
AnKi/Shaders/DownscaleBlur.ankiprog

@@ -1,63 +0,0 @@
-// Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <AnKi/Shaders/QuadVert.hlsl>
-#if ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER
-#	include <AnKi/Shaders/TonemappingFunctions.hlsl>
-#	include <AnKi/Shaders/Functions.hlsl>
-
-SamplerState g_linearAnyClampSampler : register(s0);
-Texture2D<RVec3> g_tex : register(t0);
-
-#	define TONEMAPPING_REGISTER u0
-#	include <AnKi/Shaders/TonemappingResources.hlsl>
-
-struct Constants
-{
-	Vec2 m_fbSize;
-	UVec2 m_padding;
-};
-ANKI_FAST_CONSTANTS(Constants, g_consts)
-
-#	if ANKI_COMPUTE_SHADER
-RWTexture2D<RVec4> g_storageTex : register(u1);
-#	endif
-
-#	if ANKI_COMPUTE_SHADER
-[numthreads(8, 8, 1)] void main(UVec2 svDispatchThreadId : SV_DISPATCHTHREADID)
-#	else
-RVec3 main(VertOut input) : SV_TARGET0
-#	endif
-{
-#	if ANKI_COMPUTE_SHADER
-	const Vec2 uv = (Vec2(svDispatchThreadId) + 0.5) / g_consts.m_fbSize;
-#	else
-	const Vec2 uv = input.m_uv;
-#	endif
-
-	RVec3 output;
-	const RF32 weight = 1.0 / 5.0;
-	output = g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0) * weight;
-	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, +1)) * weight;
-	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, -1)) * weight;
-	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(+1, -1)) * weight;
-	output += g_tex.SampleLevel(g_linearAnyClampSampler, uv, 0.0, IVec2(-1, +1)) * weight;
-
-#	if ANKI_COMPUTE_SHADER
-	g_storageTex[svDispatchThreadId] = RVec4(output, 1.0);
-#	else
-	return output;
-#	endif
-}
-#endif // ANKI_COMPUTE_SHADER || ANKI_PIXEL_SHADER
-
-#pragma anki technique_start vert
-#pragma anki technique_end vert
-
-#pragma anki technique_start pixel
-#pragma anki technique_end pixel
-
-#pragma anki technique_start comp
-#pragma anki technique_end comp

Some files were not shown because too many files changed in this diff