Browse Source

Revamp the config system

Panagiotis Christopoulos Charitos 6 years ago
parent
commit
0f7d34b3b9
45 changed files with 754 additions and 685 deletions
  1. 1 2
      CMakeLists.txt
  2. 4 4
      samples/common/Framework.cpp
  3. 1 1
      sandbox/Main.cpp
  4. 1 1
      src/anki/Core.h
  5. 13 6
      src/anki/core/App.cpp
  6. 1 1
      src/anki/core/CMakeLists.txt
  7. 0 108
      src/anki/core/Config.cpp
  8. 0 25
      src/anki/core/Config.h
  9. 427 0
      src/anki/core/ConfigSet.cpp
  10. 117 0
      src/anki/core/ConfigSet.h
  11. 10 5
      src/anki/core/StagingGpuMemoryManager.cpp
  12. 2 2
      src/anki/gr/gl/GlState.cpp
  13. 1 1
      src/anki/gr/gl/GrManagerImpl.cpp
  14. 1 1
      src/anki/gr/gl/GrManagerImplSdl.cpp
  15. 15 8
      src/anki/gr/vulkan/GrManagerImpl.cpp
  16. 2 2
      src/anki/gr/vulkan/PipelineCache.cpp
  17. 0 2
      src/anki/misc/CMakeLists.txt
  18. 0 18
      src/anki/misc/Common.h
  19. 0 306
      src/anki/misc/ConfigSet.cpp
  20. 0 96
      src/anki/misc/ConfigSet.h
  21. 6 3
      src/anki/renderer/Bloom.cpp
  22. 5 3
      src/anki/renderer/ClusterBin.cpp
  23. 4 2
      src/anki/renderer/Dbg.cpp
  24. 4 2
      src/anki/renderer/FinalComposite.cpp
  25. 1 1
      src/anki/renderer/GBuffer.cpp
  26. 4 4
      src/anki/renderer/GBufferPost.cpp
  27. 12 7
      src/anki/renderer/GlobalIllumination.cpp
  28. 6 3
      src/anki/renderer/LensFlare.cpp
  29. 1 1
      src/anki/renderer/LightShading.cpp
  30. 4 2
      src/anki/renderer/MainRenderer.cpp
  31. 12 7
      src/anki/renderer/ProbeReflections.cpp
  32. 14 7
      src/anki/renderer/Renderer.cpp
  33. 21 10
      src/anki/renderer/ShadowMapping.cpp
  34. 1 1
      src/anki/renderer/Ssao.cpp
  35. 6 3
      src/anki/renderer/Ssr.cpp
  36. 4 4
      src/anki/renderer/VolumetricFog.cpp
  37. 8 4
      src/anki/renderer/VolumetricLightingAccumulation.cpp
  38. 3 3
      src/anki/resource/ResourceFilesystem.cpp
  39. 10 4
      src/anki/resource/ResourceManager.cpp
  40. 11 4
      src/anki/scene/SceneGraph.cpp
  41. 5 5
      tests/framework/Framework.cpp
  42. 4 4
      tests/framework/Framework.h
  43. 5 5
      tests/gr/Gr.cpp
  44. 2 2
      tests/resource/ResourceManager.cpp
  45. 5 5
      tests/ui/Ui.cpp

+ 1 - 2
CMakeLists.txt

@@ -413,8 +413,7 @@ set(THIRD_PARTY_LIBS ${THIRD_PARTY_LIBS} BulletSoftBody BulletDynamics BulletCol
 	ankiimgui)
 	ankiimgui)
 
 
 # Add anki sub libraries
 # Add anki sub libraries
-set(ANKI_SUB_DIRS importer core script renderer scene ui input physics resource misc gr collision math util
-	shader_compiler)
+set(ANKI_SUB_DIRS importer core script renderer scene ui input physics resource gr collision math util shader_compiler)
 foreach(TMP ${ANKI_SUB_DIRS})
 foreach(TMP ${ANKI_SUB_DIRS})
 	add_subdirectory(src/anki/${TMP})
 	add_subdirectory(src/anki/${TMP})
 endforeach()
 endforeach()

+ 4 - 4
samples/common/Framework.cpp

@@ -19,10 +19,10 @@ Error SampleApp::init(int argc, char** argv, CString sampleName)
 	}
 	}
 
 
 	// Init the super class
 	// Init the super class
-	Config config;
-	config.set("window.fullscreen", true);
-	config.set("rsrc.dataPaths", ".:../..");
-	config.set("window.debugContext", 0);
+	ConfigSet config = DefaultConfigSet::get();
+	config.set("window_fullscreen", true);
+	config.set("rsrc_dataPaths", ".:../..");
+	config.set("gr_debugContext", 0);
 	ANKI_CHECK(config.setFromCommandLineArguments(argc, argv));
 	ANKI_CHECK(config.setFromCommandLineArguments(argc, argv));
 	ANKI_CHECK(App::init(config, allocAligned, nullptr));
 	ANKI_CHECK(App::init(config, allocAligned, nullptr));
 
 

+ 1 - 1
sandbox/Main.cpp

@@ -33,7 +33,7 @@ Error MyApp::init(int argc, char* argv[])
 	}
 	}
 
 
 	// Config
 	// Config
-	Config config;
+	ConfigSet config = DefaultConfigSet::get();
 	ANKI_CHECK(config.loadFromFile(argv[1]));
 	ANKI_CHECK(config.loadFromFile(argv[1]));
 	ANKI_CHECK(config.setFromCommandLineArguments(argc, argv));
 	ANKI_CHECK(config.setFromCommandLineArguments(argc, argv));
 	// ANKI_CHECK(config.saveToFile(argv[1]));
 	// ANKI_CHECK(config.saveToFile(argv[1]));

+ 1 - 1
src/anki/Core.h

@@ -6,6 +6,6 @@
 #pragma once
 #pragma once
 
 
 #include <anki/core/App.h>
 #include <anki/core/App.h>
-#include <anki/core/Config.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/core/NativeWindow.h>
 #include <anki/core/NativeWindow.h>
 #include <anki/core/CoreTracer.h>
 #include <anki/core/CoreTracer.h>

+ 13 - 6
src/anki/core/App.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/core/App.h>
 #include <anki/core/App.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Logger.h>
 #include <anki/util/File.h>
 #include <anki/util/File.h>
 #include <anki/util/Filesystem.h>
 #include <anki/util/Filesystem.h>
@@ -34,6 +34,13 @@
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(width, 1280, 16, 16 * 1024, "Width")
+ANKI_REGISTER_CONFIG_OPTION(height, 768, 16, 16 * 1024, "Height")
+ANKI_REGISTER_CONFIG_OPTION(core_mainThreadCount, max(2u, getCpuCoresCount() / 2u), 2u, 1024u)
+ANKI_REGISTER_CONFIG_OPTION(core_displayStats, 0, 0, 1)
+ANKI_REGISTER_CONFIG_OPTION(core_clearCaches, 0, 0, 1)
+ANKI_REGISTER_CONFIG_OPTION(window_fullscreen, 0, 0, 1)
+
 #if ANKI_OS_ANDROID
 #if ANKI_OS_ANDROID
 /// The one and only android hack
 /// The one and only android hack
 android_app* gAndroidApp = nullptr;
 android_app* gAndroidApp = nullptr;
@@ -307,7 +314,7 @@ Error App::init(const ConfigSet& config, AllocAlignedCallback allocCb, void* all
 Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb, void* allocCbUserData)
 Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb, void* allocCbUserData)
 {
 {
 	ConfigSet config = config_;
 	ConfigSet config = config_;
-	m_displayStats = config.getNumberU32("core.displayStats");
+	m_displayStats = config.getNumberU32("core_displayStats");
 
 
 	initMemoryCallbacks(allocCb, allocCbUserData);
 	initMemoryCallbacks(allocCb, allocCbUserData);
 	m_heapAlloc = HeapAllocator<U8>(m_allocCb, m_allocCbData);
 	m_heapAlloc = HeapAllocator<U8>(m_allocCb, m_allocCbData);
@@ -356,7 +363,7 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 	}
 	}
 #endif
 #endif
 
 
-	ANKI_CORE_LOGI("Number of main threads: %u", U(config.getNumberU32("core.mainThreadCount")));
+	ANKI_CORE_LOGI("Number of main threads: %u", U(config.getNumberU32("core_mainThreadCount")));
 
 
 	//
 	//
 	// Core tracer
 	// Core tracer
@@ -374,7 +381,7 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 	nwinit.m_height = config.getNumberU32("height");
 	nwinit.m_height = config.getNumberU32("height");
 	nwinit.m_depthBits = 0;
 	nwinit.m_depthBits = 0;
 	nwinit.m_stencilBits = 0;
 	nwinit.m_stencilBits = 0;
-	nwinit.m_fullscreenDesktopRez = config.getBool("window.fullscreen");
+	nwinit.m_fullscreenDesktopRez = config.getBool("window_fullscreen");
 	m_window = m_heapAlloc.newInstance<NativeWindow>();
 	m_window = m_heapAlloc.newInstance<NativeWindow>();
 
 
 	ANKI_CHECK(m_window->init(nwinit, m_heapAlloc));
 	ANKI_CHECK(m_window->init(nwinit, m_heapAlloc));
@@ -388,7 +395,7 @@ Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb,
 	//
 	//
 	// ThreadPool
 	// ThreadPool
 	//
 	//
-	m_threadHive = m_heapAlloc.newInstance<ThreadHive>(config.getNumberU32("core.mainThreadCount"), m_heapAlloc, true);
+	m_threadHive = m_heapAlloc.newInstance<ThreadHive>(config.getNumberU32("core_mainThreadCount"), m_heapAlloc, true);
 
 
 	//
 	//
 	// Graphics API
 	// Graphics API
@@ -508,7 +515,7 @@ Error App::initDirs(const ConfigSet& cfg)
 	m_cacheDir.sprintf(m_heapAlloc, "%s/cache", &m_settingsDir[0]);
 	m_cacheDir.sprintf(m_heapAlloc, "%s/cache", &m_settingsDir[0]);
 
 
 	const Bool cacheDirExists = directoryExists(m_cacheDir.toCString());
 	const Bool cacheDirExists = directoryExists(m_cacheDir.toCString());
-	if(cfg.getBool("core.clearCaches") && cacheDirExists)
+	if(cfg.getBool("core_clearCaches") && cacheDirExists)
 	{
 	{
 		ANKI_CORE_LOGI("Will delete the cache dir and start fresh: %s", &m_cacheDir[0]);
 		ANKI_CORE_LOGI("Will delete the cache dir and start fresh: %s", &m_cacheDir[0]);
 		ANKI_CHECK(removeDirectory(m_cacheDir.toCString(), m_heapAlloc));
 		ANKI_CHECK(removeDirectory(m_cacheDir.toCString(), m_heapAlloc));

+ 1 - 1
src/anki/core/CMakeLists.txt

@@ -1,4 +1,4 @@
-set(SOURCES App.cpp Config.cpp StagingGpuMemoryManager.cpp DeveloperConsole.cpp CoreTracer.cpp)
+set(SOURCES App.cpp ConfigSet.cpp StagingGpuMemoryManager.cpp DeveloperConsole.cpp CoreTracer.cpp)
 
 
 if(SDL)
 if(SDL)
 	set(SOURCES ${SOURCES} NativeWindowSdl.cpp)
 	set(SOURCES ${SOURCES} NativeWindowSdl.cpp)

+ 0 - 108
src/anki/core/Config.cpp

@@ -1,108 +0,0 @@
-// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/core/Config.h>
-#include <anki/util/System.h>
-#include <anki/Math.h>
-#include <shaders/glsl_cpp_common/ClusteredShading.h>
-
-namespace anki
-{
-
-Config::Config()
-{
-	// Renderer
-	newOption("r.renderingQuality", 1.0, "Rendering quality factor");
-	newOption("r.lodDistance0", 20.0, "Distance that will be used to calculate the LOD 0");
-	newOption("r.lodDistance1", 40.0, "Distance that will be used to calculate the LOD 1");
-	newOption("r.clusterSizeX", 32);
-	newOption("r.clusterSizeY", 26);
-	newOption("r.clusterSizeZ", 32);
-	newOption("r.avgObjectsPerCluster", 16);
-	newOption("r.textureAnisotropy", 8);
-
-	newOption("r.volumetricLightingAccumulation.clusterFractionXY", 4);
-	newOption("r.volumetricLightingAccumulation.clusterFractionZ", 4);
-	newOption("r.volumetricLightingAccumulation.finalClusterInZ", 26);
-
-	newOption("r.shadowMapping.enabled", true);
-	newOption("r.shadowMapping.tileResolution", 128);
-	newOption("r.shadowMapping.tileCountPerRowOrColumn", 16);
-	newOption("r.shadowMapping.scratchTileCountX", 4 * (MAX_SHADOW_CASCADES + 2));
-	newOption("r.shadowMapping.scratchTileCountY", 4);
-	newOption("r.shadowMapping.lightLodDistance0", 10.0);
-	newOption("r.shadowMapping.lightLodDistance1", 20.0);
-
-	newOption("r.lensFlare.maxSpritesPerFlare", 8);
-	newOption("r.lensFlare.maxFlares", 16);
-
-	newOption("r.bloom.threshold", 2.5);
-	newOption("r.bloom.scale", 2.5);
-
-	newOption("r.indirect.reflectionResolution", 128);
-	newOption("r.indirect.irradianceResolution", 16);
-	newOption("r.indirect.maxSimultaneousProbeCount", 32);
-	newOption("r.indirect.shadowMapResolution", 64);
-
-	newOption("r.gi.tileResolution", 32);
-	newOption("r.gi.shadowMapResolution", 128);
-	newOption("r.gi.maxCachedProbes", 16);
-	newOption("r.gi.maxVisibleProbes", 8);
-	newOption("r.gi.firstClipmapLevelCellSize", 1.0);
-	newOption("r.gi.secondClipmapLevelCellSize", 8.0);
-	newOption("r.gi.firstClipmapMaxDistance", 20.0);
-
-	newOption("r.motionBlur.maxSamples", 32);
-
-	newOption("r.ssr.maxSteps", 64);
-	newOption("r.ssr.historyBlendFactor", 0.3);
-
-	newOption("r.dbg.enabled", false);
-
-	newOption("r.final.motionBlurSamples", 32);
-
-	// Scene
-	newOption("scene.earlyZDistance", 10.0, "Objects with distance lower than that will be used in early Z");
-	newOption("scene.reflectionProbeEffectiveDistance", 256.0, "How far reflection probes can look");
-	newOption("scene.reflectionProbeShadowEffectiveDistance", 32.0, "How far to render shadows for reflection probes");
-
-	// Globals
-	newOption("width", 1280);
-	newOption("height", 768);
-
-	// Resource
-	newOption("rsrc.maxTextureSize", 1024 * 1024);
-	newOption("rsrc.dumpShaderSources", false);
-	newOption("rsrc.dataPaths", ".", "The engine loads assets only in from these paths. Separate them with :");
-	newOption("rsrc.transferScratchMemorySize", 256_MB);
-
-	// Window
-	newOption("window.fullscreen", false);
-	newOption("window.debugContext", false);
-	newOption("window.vsync", false);
-	newOption("window.debugMarkers", false);
-
-	// GR
-	newOption("gr.diskShaderCacheMaxSize", 10_MB);
-	newOption("gr.vkminor", 1);
-	newOption("gr.vkmajor", 1);
-	newOption("gr.glmajor", 4);
-	newOption("gr.glminor", 5);
-
-	// Core
-	newOption("core.uniformPerFrameMemorySize", 16_MB);
-	newOption("core.storagePerFrameMemorySize", 16_MB);
-	newOption("core.vertexPerFrameMemorySize", 10_MB);
-	newOption("core.textureBufferPerFrameMemorySize", 1_MB);
-	newOption("core.mainThreadCount", max(2u, getCpuCoresCount() / 2u));
-	newOption("core.displayStats", false);
-	newOption("core.clearCaches", false);
-}
-
-Config::~Config()
-{
-}
-
-} // end namespace anki

+ 0 - 25
src/anki/core/Config.h

@@ -1,25 +0,0 @@
-// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/misc/ConfigSet.h>
-
-namespace anki
-{
-
-/// @addtogroup core
-/// @{
-
-/// Global configuration set
-class Config : public ConfigSet
-{
-public:
-	Config();
-	~Config();
-};
-/// @}
-
-} // end namespace anki

+ 427 - 0
src/anki/core/ConfigSet.cpp

@@ -0,0 +1,427 @@
+// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/core/ConfigSet.h>
+#include <anki/util/Xml.h>
+#include <anki/util/Logger.h>
+#include <anki/util/File.h>
+
+namespace anki
+{
+
+class ConfigSet::Option : public NonCopyable
+{
+public:
+	enum Type
+	{
+		NONE,
+		FLOAT,
+		UNSIGNED,
+		STRING
+	};
+
+	String m_name;
+	String m_helpMsg;
+
+	String m_str;
+	F64 m_float = 0.0;
+	F64 m_minFloat = 0.0;
+	F64 m_maxFloat = 0.0;
+	U64 m_unsigned = 0;
+	U64 m_minUnsigned = 0;
+	U64 m_maxUnsigned = 0;
+
+	Type m_type = NONE;
+
+	Option() = default;
+
+	Option(Option&& b)
+		: m_name(std::move(b.m_name))
+		, m_helpMsg(std::move(b.m_helpMsg))
+		, m_str(std::move(b.m_str))
+		, m_float(b.m_float)
+		, m_minFloat(b.m_minFloat)
+		, m_maxFloat(b.m_maxFloat)
+		, m_unsigned(b.m_unsigned)
+		, m_minUnsigned(b.m_minUnsigned)
+		, m_maxUnsigned(b.m_maxUnsigned)
+		, m_type(b.m_type)
+	{
+	}
+
+	~Option() = default;
+
+	Option& operator=(Option&& b) = delete;
+};
+
+ConfigSet::ConfigSet()
+{
+	m_alloc = HeapAllocator<U8>(allocAligned, nullptr);
+}
+
+ConfigSet::~ConfigSet()
+{
+	for(Option& o : m_options)
+	{
+		o.m_name.destroy(m_alloc);
+		o.m_str.destroy(m_alloc);
+		o.m_helpMsg.destroy(m_alloc);
+	}
+
+	m_options.destroy(m_alloc);
+}
+
+ConfigSet& ConfigSet::operator=(const ConfigSet& b)
+{
+	m_alloc = b.m_alloc; // Not a copy but we are fine
+
+	for(const Option& o : b.m_options)
+	{
+		Option newO;
+		newO.m_name.create(m_alloc, o.m_name.toCString());
+		if(o.m_type == Option::STRING)
+		{
+			newO.m_str.create(m_alloc, o.m_str.toCString());
+		}
+		newO.m_float = o.m_float;
+		newO.m_minFloat = o.m_minFloat;
+		newO.m_maxFloat = o.m_maxFloat;
+		newO.m_unsigned = o.m_unsigned;
+		newO.m_minUnsigned = o.m_minUnsigned;
+		newO.m_maxUnsigned = o.m_maxUnsigned;
+		newO.m_type = o.m_type;
+
+		m_options.emplaceBack(m_alloc, std::move(newO));
+	}
+
+	return *this;
+}
+
+ConfigSet::Option* ConfigSet::tryFind(CString optionName)
+{
+	for(List<Option>::Iterator it = m_options.getBegin(); it != m_options.getEnd(); ++it)
+	{
+		if((*it).m_name == optionName)
+		{
+			return &(*it);
+		}
+	}
+
+	return nullptr;
+}
+
+const ConfigSet::Option* ConfigSet::tryFind(CString optionName) const
+{
+	for(List<Option>::ConstIterator it = m_options.getBegin(); it != m_options.getEnd(); ++it)
+	{
+		if((*it).m_name == optionName)
+		{
+			return &(*it);
+		}
+	}
+
+	return nullptr;
+}
+
+void ConfigSet::newOption(CString optionName, CString value, CString helpMsg)
+{
+	ANKI_ASSERT(!tryFind(optionName));
+
+	Option o;
+	o.m_name.create(m_alloc, optionName);
+	o.m_str.create(m_alloc, value);
+	o.m_type = Option::STRING;
+	if(!helpMsg.isEmpty())
+	{
+		o.m_helpMsg.create(m_alloc, helpMsg);
+	}
+
+	m_options.emplaceBack(m_alloc, std::move(o));
+}
+
+void ConfigSet::newOptionInternal(CString optionName, F64 value, F64 minValue, F64 maxValue, CString helpMsg)
+{
+	ANKI_ASSERT(!tryFind(optionName));
+	ANKI_ASSERT(value >= minValue && value <= maxValue && minValue <= maxValue);
+
+	Option o;
+	o.m_name.create(m_alloc, optionName);
+	o.m_float = value;
+	o.m_minFloat = minValue;
+	o.m_maxFloat = maxValue;
+	o.m_type = Option::FLOAT;
+	if(!helpMsg.isEmpty())
+	{
+		o.m_helpMsg.create(m_alloc, helpMsg);
+	}
+
+	m_options.emplaceBack(m_alloc, std::move(o));
+}
+
+void ConfigSet::newOptionInternal(CString optionName, U64 value, U64 minValue, U64 maxValue, CString helpMsg)
+{
+	ANKI_ASSERT(!tryFind(optionName));
+	ANKI_ASSERT(value >= minValue && value <= maxValue && minValue <= maxValue);
+
+	Option o;
+	o.m_name.create(m_alloc, optionName);
+	o.m_unsigned = value;
+	o.m_minUnsigned = minValue;
+	o.m_maxUnsigned = maxValue;
+	o.m_type = Option::UNSIGNED;
+	if(!helpMsg.isEmpty())
+	{
+		o.m_helpMsg.create(m_alloc, helpMsg);
+	}
+
+	m_options.emplaceBack(m_alloc, std::move(o));
+}
+
+void ConfigSet::set(CString optionName, CString value)
+{
+	Option* o = tryFind(optionName);
+	ANKI_ASSERT(o);
+	ANKI_ASSERT(o->m_type == Option::STRING);
+	o->m_str.destroy(m_alloc);
+	o->m_str.create(m_alloc, value);
+}
+
+void ConfigSet::setInternal(CString optionName, F64 value)
+{
+	Option* o = tryFind(optionName);
+	ANKI_ASSERT(o);
+	ANKI_ASSERT(o->m_type == Option::FLOAT);
+	ANKI_ASSERT(value >= o->m_minFloat);
+	ANKI_ASSERT(value <= o->m_maxFloat);
+	o->m_float = value;
+}
+
+void ConfigSet::setInternal(CString optionName, U64 value)
+{
+	Option* o = tryFind(optionName);
+	ANKI_ASSERT(o);
+	ANKI_ASSERT(o->m_type == Option::UNSIGNED);
+	ANKI_ASSERT(value >= o->m_minUnsigned);
+	ANKI_ASSERT(value <= o->m_maxUnsigned);
+	o->m_unsigned = value;
+}
+
+F64 ConfigSet::getNumberF64(CString optionName) const
+{
+	const Option* option = tryFind(optionName);
+	ANKI_ASSERT(option);
+	ANKI_ASSERT(option->m_type == Option::FLOAT);
+	return option->m_float;
+}
+
+F32 ConfigSet::getNumberF32(CString optionName) const
+{
+	return F32(getNumberF64(optionName));
+}
+
+U64 ConfigSet::getNumberU64(CString optionName) const
+{
+	const Option* option = tryFind(optionName);
+	ANKI_ASSERT(option);
+	ANKI_ASSERT(option->m_type == Option::UNSIGNED);
+	return option->m_unsigned;
+}
+
+U32 ConfigSet::getNumberU32(CString optionName) const
+{
+	const U64 out = getNumberU64(optionName);
+	if(out > MAX_U32)
+	{
+		ANKI_CORE_LOGW("Option is out of U32 range: %s", optionName.cstr());
+	}
+	return U32(out);
+}
+
+U16 ConfigSet::getNumberU16(CString optionName) const
+{
+	const U64 out = getNumberU64(optionName);
+	if(out > MAX_U16)
+	{
+		ANKI_CORE_LOGW("Option is out of U16 range: %s", optionName.cstr());
+	}
+	return U16(out);
+}
+
+U8 ConfigSet::getNumberU8(CString optionName) const
+{
+	const U64 out = getNumberU64(optionName);
+	if(out > MAX_U8)
+	{
+		ANKI_CORE_LOGW("Option is out of U8 range: %s", optionName.cstr());
+	}
+	return U8(out);
+}
+
+Bool ConfigSet::getBool(CString optionName) const
+{
+	const U64 val = getNumberU64(optionName);
+	if((val & ~U64(1)) != 0)
+	{
+		ANKI_CORE_LOGW("Expecting 0 or 1 for the config option \"%s\". Will mask out extra bits", optionName.cstr());
+	}
+	return val & 1;
+}
+
+CString ConfigSet::getString(CString optionName) const
+{
+	const Option* o = tryFind(optionName);
+	ANKI_ASSERT(o);
+	ANKI_ASSERT(o->m_type == Option::STRING);
+	return o->m_str.toCString();
+}
+
+Error ConfigSet::loadFromFile(CString filename)
+{
+	ANKI_CORE_LOGI("Loading config file %s", filename.cstr());
+	XmlDocument xml;
+	ANKI_CHECK(xml.loadFile(filename, m_alloc));
+
+	XmlElement rootel;
+	ANKI_CHECK(xml.getChildElement("config", rootel));
+
+	for(Option& option : m_options)
+	{
+		XmlElement el;
+		ANKI_CHECK(rootel.getChildElementOptional(option.m_name.toCString(), el));
+
+		if(el)
+		{
+			if(option.m_type == Option::FLOAT)
+			{
+				ANKI_CHECK(el.getNumber(option.m_float));
+			}
+			else if(option.m_type == Option::UNSIGNED)
+			{
+				ANKI_CHECK(el.getNumber(option.m_unsigned));
+			}
+			else
+			{
+				ANKI_ASSERT(option.m_type == Option::STRING);
+				CString txt;
+				ANKI_CHECK(el.getText(txt));
+				option.m_str.destroy(m_alloc);
+				option.m_str.create(m_alloc, txt);
+			}
+		}
+		else
+		{
+			if(option.m_type == Option::FLOAT)
+			{
+				ANKI_CORE_LOGW(
+					"Missing option for \"%s\". Will use the default value: %f", &option.m_name[0], option.m_float);
+			}
+			else if(option.m_type == Option::UNSIGNED)
+			{
+				ANKI_CORE_LOGW("Missing option for \"%s\". Will use the default value: %" PRIu64,
+					&option.m_name[0],
+					option.m_unsigned);
+			}
+			else
+			{
+				ANKI_ASSERT(option.m_type == Option::STRING);
+				ANKI_CORE_LOGW("Missing option for \"%s\". Will use the default value: %s",
+					option.m_name.cstr(),
+					option.m_str.cstr());
+			}
+		}
+	}
+
+	return Error::NONE;
+}
+
+Error ConfigSet::saveToFile(CString filename) const
+{
+	ANKI_CORE_LOGI("Saving config file %s", &filename[0]);
+
+	File file;
+	ANKI_CHECK(file.open(filename, FileOpenFlag::WRITE));
+
+	ANKI_CHECK(file.writeText("%s\n<config>\n", XmlDocument::XML_HEADER.cstr()));
+
+	for(const Option& option : m_options)
+	{
+		if(!option.m_helpMsg.isEmpty())
+		{
+			ANKI_CHECK(file.writeText("\t<!-- %s -->\n", option.m_helpMsg.cstr()));
+		}
+
+		if(option.m_type == Option::FLOAT)
+		{
+			ANKI_CHECK(file.writeText("\t<%s>%f</%s>\n", option.m_name.cstr(), option.m_float, option.m_name.cstr()));
+		}
+		else if(option.m_type == Option::UNSIGNED)
+		{
+			ANKI_CHECK(file.writeText(
+				"\t<%s>%" PRIu64 "</%s>\n", option.m_name.cstr(), option.m_unsigned, option.m_name.cstr()));
+		}
+		else
+		{
+			ANKI_ASSERT(option.m_type == Option::STRING);
+			ANKI_CHECK(file.writeText(
+				"\t<%s><![CDATA[%s]]></%s>\n", option.m_name.cstr(), option.m_str.cstr(), option.m_name.cstr()));
+		}
+	}
+
+	ANKI_CHECK(file.writeText("</config>\n"));
+	return Error::NONE;
+}
+
+Error ConfigSet::setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[])
+{
+	for(U i = 0; i < cmdLineArgsCount; ++i)
+	{
+		const char* arg = cmdLineArgs[i];
+		ANKI_ASSERT(arg);
+		if(CString(arg) == "-cfg")
+		{
+			if(i + 2 >= cmdLineArgsCount)
+			{
+				ANKI_CORE_LOGE("Wrong number of arguments after -cfg");
+				return Error::USER_DATA;
+			}
+
+			// Get the option
+			++i;
+			arg = cmdLineArgs[i];
+			ANKI_ASSERT(arg);
+			Option* option = tryFind(arg);
+			if(option == nullptr)
+			{
+				ANKI_CORE_LOGE("Option name following -cfg not found: %s", arg);
+				return Error::USER_DATA;
+			}
+
+			// Set the value
+			++i;
+			arg = cmdLineArgs[i];
+			ANKI_ASSERT(arg);
+			if(option->m_type == Option::STRING)
+			{
+				option->m_str.destroy(m_alloc);
+				option->m_str.create(m_alloc, arg);
+			}
+			else if(option->m_type == Option::FLOAT)
+			{
+				CString val(arg);
+				ANKI_CHECK(val.toNumber(option->m_float));
+			}
+			else
+			{
+				ANKI_ASSERT(option->m_type == Option::UNSIGNED);
+				CString val(arg);
+				ANKI_CHECK(val.toNumber(option->m_unsigned));
+			}
+		}
+	}
+
+	return Error::NONE;
+}
+
+} // end namespace anki

+ 117 - 0
src/anki/core/ConfigSet.h

@@ -0,0 +1,117 @@
+// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma once
+
+#include <anki/core/Common.h>
+#include <anki/util/List.h>
+#include <anki/util/String.h>
+
+namespace anki
+{
+
+/// @addtogroup core
+/// @{
+
+/// A storage of configuration variables.
+class ConfigSet
+{
+public:
+	ConfigSet();
+
+	/// Copy.
+	ConfigSet(const ConfigSet& b)
+	{
+		operator=(b);
+	}
+
+	~ConfigSet();
+
+	/// Copy.
+	ConfigSet& operator=(const ConfigSet& b);
+
+	/// @name Set the value of an option.
+	/// @{
+	void set(CString optionName, CString value);
+
+	template<typename T, ANKI_ENABLE(std::is_integral<T>::value)>
+	void set(CString optionName, T value)
+	{
+		setInternal(optionName, U64(value));
+	}
+
+	template<typename T, ANKI_ENABLE(std::is_floating_point<T>::value)>
+	void set(CString optionName, T value)
+	{
+		setInternal(optionName, F64(value));
+	}
+	/// @}
+
+	/// @name Find an option and return its value.
+	/// @{
+	F64 getNumberF64(CString optionName) const;
+	F32 getNumberF32(CString optionName) const;
+	U64 getNumberU64(CString optionName) const;
+	U32 getNumberU32(CString optionName) const;
+	U16 getNumberU16(CString optionName) const;
+	U8 getNumberU8(CString optionName) const;
+	Bool getBool(CString optionName) const;
+	CString getString(CString optionName) const;
+	/// @}
+
+	/// @name Create new options.
+	/// @{
+	void newOption(CString optionName, CString value, CString helpMsg);
+
+	template<typename T, ANKI_ENABLE(std::is_integral<T>::value)>
+	void newOption(CString optionName, T value, T minValue, T maxValue, CString helpMsg = "")
+	{
+		newOptionInternal(optionName, U64(value), U64(minValue), U64(maxValue), helpMsg);
+	}
+
+	template<typename T, ANKI_ENABLE(std::is_floating_point<T>::value)>
+	void newOption(CString optionName, T value, T minValue, T maxValue, CString helpMsg = "")
+	{
+		newOptionInternal(optionName, F64(value), F64(minValue), F64(maxValue), helpMsg);
+	}
+	/// @}
+
+	ANKI_USE_RESULT Error loadFromFile(CString filename);
+
+	ANKI_USE_RESULT Error saveToFile(CString filename) const;
+
+	ANKI_USE_RESULT Error setFromCommandLineArguments(U32 cmdLineArgsCount, char* cmdLineArgs[]);
+
+private:
+	class Option;
+
+	HeapAllocator<U8> m_alloc;
+	List<Option> m_options;
+
+	Option* tryFind(CString name);
+	const Option* tryFind(CString name) const;
+
+	void setInternal(CString optionName, F64 value);
+	void setInternal(CString optionName, U64 value);
+
+	void newOptionInternal(CString optionName, U64 value, U64 minValue, U64 maxValue, CString helpMsg);
+	void newOptionInternal(CString optionName, F64 value, F64 minValue, F64 maxValue, CString helpMsg);
+};
+
+/// The default config set. Copy that to your own to override.
+using DefaultConfigSet = Singleton<ConfigSet>;
+
+/// This macro registers a config option. Have it on .cpp files.
+#define ANKI_REGISTER_CONFIG_OPTION(name, ...) \
+	struct ANKI_CONCATENATE(ConfigSet, name) \
+	{ \
+		ANKI_CONCATENATE(ConfigSet, name)() \
+		{ \
+			DefaultConfigSet::get().newOption(#name, __VA_ARGS__); \
+		} \
+	} ANKI_CONCATENATE(g_ConfigSet, name);
+/// @}
+
+} // end namespace anki

+ 10 - 5
src/anki/core/StagingGpuMemoryManager.cpp

@@ -4,13 +4,18 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/core/StagingGpuMemoryManager.h>
 #include <anki/core/StagingGpuMemoryManager.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/gr/GrManager.h>
 #include <anki/gr/GrManager.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(core_uniformPerFrameMemorySize, 16_MB, 1_MB, 1_GB)
+ANKI_REGISTER_CONFIG_OPTION(core_storagePerFrameMemorySize, 16_MB, 1_MB, 1_GB)
+ANKI_REGISTER_CONFIG_OPTION(core_vertexPerFrameMemorySize, 10_MB, 1_MB, 1_GB)
+ANKI_REGISTER_CONFIG_OPTION(core_textureBufferPerFrameMemorySize, 1_MB, 1_MB, 1_GB)
+
 StagingGpuMemoryManager::~StagingGpuMemoryManager()
 StagingGpuMemoryManager::~StagingGpuMemoryManager()
 {
 {
 	m_gr->finish();
 	m_gr->finish();
@@ -26,10 +31,10 @@ Error StagingGpuMemoryManager::init(GrManager* gr, const ConfigSet& cfg)
 {
 {
 	m_gr = gr;
 	m_gr = gr;
 
 
-	m_perFrameBuffers[StagingGpuMemoryType::UNIFORM].m_size = cfg.getNumberU32("core.uniformPerFrameMemorySize");
-	m_perFrameBuffers[StagingGpuMemoryType::STORAGE].m_size = cfg.getNumberU32("core.storagePerFrameMemorySize");
-	m_perFrameBuffers[StagingGpuMemoryType::VERTEX].m_size = cfg.getNumberU32("core.vertexPerFrameMemorySize");
-	m_perFrameBuffers[StagingGpuMemoryType::TEXTURE].m_size = cfg.getNumberU32("core.textureBufferPerFrameMemorySize");
+	m_perFrameBuffers[StagingGpuMemoryType::UNIFORM].m_size = cfg.getNumberU32("core_uniformPerFrameMemorySize");
+	m_perFrameBuffers[StagingGpuMemoryType::STORAGE].m_size = cfg.getNumberU32("core_storagePerFrameMemorySize");
+	m_perFrameBuffers[StagingGpuMemoryType::VERTEX].m_size = cfg.getNumberU32("core_vertexPerFrameMemorySize");
+	m_perFrameBuffers[StagingGpuMemoryType::TEXTURE].m_size = cfg.getNumberU32("core_textureBufferPerFrameMemorySize");
 
 
 	initBuffer(StagingGpuMemoryType::UNIFORM,
 	initBuffer(StagingGpuMemoryType::UNIFORM,
 		gr->getDeviceCapabilities().m_uniformBufferBindOffsetAlignment,
 		gr->getDeviceCapabilities().m_uniformBufferBindOffsetAlignment,

+ 2 - 2
src/anki/gr/gl/GlState.cpp

@@ -8,7 +8,7 @@
 #include <anki/gr/GrManager.h>
 #include <anki/gr/GrManager.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Logger.h>
 #include <anki/core/Trace.h>
 #include <anki/core/Trace.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <algorithm>
 #include <algorithm>
 #include <cstring>
 #include <cstring>
 
 
@@ -83,7 +83,7 @@ __stdcall
 
 
 void GlState::initMainThread(const ConfigSet& config)
 void GlState::initMainThread(const ConfigSet& config)
 {
 {
-	m_registerMessages = config.getNumber("window.debugContext");
+	m_registerMessages = config.getNumber("gr_debugContext");
 }
 }
 
 
 void GlState::initRenderThread()
 void GlState::initRenderThread()

+ 1 - 1
src/anki/gr/gl/GrManagerImpl.cpp

@@ -42,7 +42,7 @@ Error GrManagerImpl::init(GrManagerInitInfo& init, GrAllocator<U8> alloc)
 	m_alloc = alloc;
 	m_alloc = alloc;
 	m_cacheDir.create(m_alloc, init.m_cacheDirectory);
 	m_cacheDir.create(m_alloc, init.m_cacheDirectory);
 
 
-	m_debugMarkers = init.m_config->getNumber("window.debugMarkers");
+	m_debugMarkers = init.m_config->getNumber("gr_debugMarkers");
 
 
 	// Init the backend of the backend
 	// Init the backend of the backend
 	ANKI_CHECK(createBackend(init));
 	ANKI_CHECK(createBackend(init));

+ 1 - 1
src/anki/gr/gl/GrManagerImplSdl.cpp

@@ -39,7 +39,7 @@ public:
 			U(init.m_config->getNumber("gr.glmajor")),
 			U(init.m_config->getNumber("gr.glmajor")),
 			U(init.m_config->getNumber("gr.glminor")));
 			U(init.m_config->getNumber("gr.glminor")));
 
 
-		if(init.m_config->getNumber("window.debugContext"))
+		if(init.m_config->getNumber("gr_debugContext"))
 		{
 		{
 			if(SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG))
 			if(SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_DEBUG_FLAG))
 			{
 			{

+ 15 - 8
src/anki/gr/vulkan/GrManagerImpl.cpp

@@ -10,12 +10,19 @@
 #include <anki/gr/Fence.h>
 #include <anki/gr/Fence.h>
 #include <anki/gr/vulkan/FenceImpl.h>
 #include <anki/gr/vulkan/FenceImpl.h>
 #include <anki/util/Functions.h>
 #include <anki/util/Functions.h>
-#include <anki/core/Config.h>
+#include <anki/core/ConfigSet.h>
 #include <glslang/Public/ShaderLang.h>
 #include <glslang/Public/ShaderLang.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(gr_debugContext, 0, 0, 1)
+ANKI_REGISTER_CONFIG_OPTION(gr_vsync, 0, 0, 1)
+ANKI_REGISTER_CONFIG_OPTION(gr_debugMarkers, 0, 0, 1)
+ANKI_REGISTER_CONFIG_OPTION(gr_diskShaderCacheMaxSize, 128_MB, 1_MB, 1_GB)
+ANKI_REGISTER_CONFIG_OPTION(gr_vkminor, 1, 1, 1)
+ANKI_REGISTER_CONFIG_OPTION(gr_vkmajor, 1, 1, 1)
+
 GrManagerImpl::~GrManagerImpl()
 GrManagerImpl::~GrManagerImpl()
 {
 {
 	// FIRST THING: wait for the GPU
 	// FIRST THING: wait for the GPU
@@ -109,7 +116,7 @@ Error GrManagerImpl::initInternal(const GrManagerInitInfo& init)
 	ANKI_CHECK(initDevice(init));
 	ANKI_CHECK(initDevice(init));
 	vkGetDeviceQueue(m_device, m_queueIdx, 0, &m_queue);
 	vkGetDeviceQueue(m_device, m_queueIdx, 0, &m_queue);
 
 
-	m_swapchainFactory.init(this, init.m_config->getBool("window.vsync"));
+	m_swapchainFactory.init(this, init.m_config->getBool("gr_vsync"));
 
 
 	m_crntSwapchain = m_swapchainFactory.newInstance();
 	m_crntSwapchain = m_swapchainFactory.newInstance();
 
 
@@ -221,8 +228,8 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 
 
 	// Create the instance
 	// Create the instance
 	//
 	//
-	const U8 vulkanMinor = init.m_config->getNumberU8("gr.vkminor");
-	const U8 vulkanMajor = init.m_config->getNumberU8("gr.vkmajor");
+	const U8 vulkanMinor = init.m_config->getNumberU8("gr_vkminor");
+	const U8 vulkanMajor = init.m_config->getNumberU8("gr_vkmajor");
 
 
 	VkApplicationInfo app = {};
 	VkApplicationInfo app = {};
 	app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
 	app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
@@ -239,7 +246,7 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 	// Layers
 	// Layers
 	static Array<const char*, 1> LAYERS = {{"VK_LAYER_KHRONOS_validation"}};
 	static Array<const char*, 1> LAYERS = {{"VK_LAYER_KHRONOS_validation"}};
 	Array<const char*, LAYERS.getSize()> layersToEnable; // Keep it alive in the stack
 	Array<const char*, LAYERS.getSize()> layersToEnable; // Keep it alive in the stack
-	if(init.m_config->getBool("window.debugContext"))
+	if(init.m_config->getBool("gr_debugContext"))
 	{
 	{
 		uint32_t count;
 		uint32_t count;
 		vkEnumerateInstanceLayerProperties(&count, nullptr);
 		vkEnumerateInstanceLayerProperties(&count, nullptr);
@@ -421,7 +428,7 @@ Error GrManagerImpl::initInstance(const GrManagerInitInfo& init)
 
 
 	vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_devFeatures);
 	vkGetPhysicalDeviceFeatures(m_physicalDevice, &m_devFeatures);
 	m_devFeatures.robustBufferAccess =
 	m_devFeatures.robustBufferAccess =
-		(init.m_config->getBool("window.debugContext") && m_devFeatures.robustBufferAccess) ? true : false;
+		(init.m_config->getBool("gr_debugContext") && m_devFeatures.robustBufferAccess) ? true : false;
 	ANKI_VK_LOGI("Robust buffer access is %s", (m_devFeatures.robustBufferAccess) ? "enabled" : "disabled");
 	ANKI_VK_LOGI("Robust buffer access is %s", (m_devFeatures.robustBufferAccess) ? "enabled" : "disabled");
 
 
 	// Set limits
 	// Set limits
@@ -522,7 +529,7 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 				extensionsToEnable[extensionsToEnableCount++] = VK_KHR_MAINTENANCE1_EXTENSION_NAME;
 				extensionsToEnable[extensionsToEnableCount++] = VK_KHR_MAINTENANCE1_EXTENSION_NAME;
 			}
 			}
 			else if(CString(extensionInfos[extCount].extensionName) == VK_EXT_DEBUG_MARKER_EXTENSION_NAME
 			else if(CString(extensionInfos[extCount].extensionName) == VK_EXT_DEBUG_MARKER_EXTENSION_NAME
-					&& init.m_config->getBool("window.debugMarkers"))
+					&& init.m_config->getBool("gr_debugMarkers"))
 			{
 			{
 				m_extensions |= VulkanExtensions::EXT_DEBUG_MARKER;
 				m_extensions |= VulkanExtensions::EXT_DEBUG_MARKER;
 				extensionsToEnable[extensionsToEnableCount++] = VK_EXT_DEBUG_MARKER_EXTENSION_NAME;
 				extensionsToEnable[extensionsToEnableCount++] = VK_EXT_DEBUG_MARKER_EXTENSION_NAME;
@@ -538,7 +545,7 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 				extensionsToEnable[extensionsToEnableCount++] = VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME;
 				extensionsToEnable[extensionsToEnableCount++] = VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME;
 			}
 			}
 			else if(CString(extensionInfos[extCount].extensionName) == VK_AMD_SHADER_INFO_EXTENSION_NAME
 			else if(CString(extensionInfos[extCount].extensionName) == VK_AMD_SHADER_INFO_EXTENSION_NAME
-					&& init.m_config->getBool("core.displayStats"))
+					&& init.m_config->getBool("core_displayStats"))
 			{
 			{
 				m_extensions |= VulkanExtensions::AMD_SHADER_INFO;
 				m_extensions |= VulkanExtensions::AMD_SHADER_INFO;
 				extensionsToEnable[extensionsToEnableCount++] = VK_AMD_SHADER_INFO_EXTENSION_NAME;
 				extensionsToEnable[extensionsToEnableCount++] = VK_AMD_SHADER_INFO_EXTENSION_NAME;

+ 2 - 2
src/anki/gr/vulkan/PipelineCache.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <anki/gr/vulkan/PipelineCache.h>
 #include <anki/gr/vulkan/PipelineCache.h>
-#include <anki/core/Config.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/Filesystem.h>
 #include <anki/util/Filesystem.h>
 #include <anki/util/File.h>
 #include <anki/util/File.h>
 
 
@@ -15,7 +15,7 @@ Error PipelineCache::init(
 	VkDevice dev, VkPhysicalDevice pdev, CString cacheDir, const ConfigSet& cfg, GrAllocator<U8> alloc)
 	VkDevice dev, VkPhysicalDevice pdev, CString cacheDir, const ConfigSet& cfg, GrAllocator<U8> alloc)
 {
 {
 	ANKI_ASSERT(cacheDir && dev && pdev);
 	ANKI_ASSERT(cacheDir && dev && pdev);
-	m_dumpSize = cfg.getNumberU32("gr.diskShaderCacheMaxSize");
+	m_dumpSize = cfg.getNumberU32("gr_diskShaderCacheMaxSize");
 	m_dumpFilename.sprintf(alloc, "%s/vk_pipeline_cache", &cacheDir[0]);
 	m_dumpFilename.sprintf(alloc, "%s/vk_pipeline_cache", &cacheDir[0]);
 
 
 	// Try read the pipeline cache file.
 	// Try read the pipeline cache file.

+ 0 - 2
src/anki/misc/CMakeLists.txt

@@ -1,2 +0,0 @@
-file(GLOB SOURCES *.cpp)
-addAnkiSourceFiles(${SOURCES})

+ 0 - 18
src/anki/misc/Common.h

@@ -1,18 +0,0 @@
-// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/Config.h>
-
-namespace anki
-{
-
-#define ANKI_MISC_LOGI(...) ANKI_LOG("MISC", NORMAL, __VA_ARGS__)
-#define ANKI_MISC_LOGE(...) ANKI_LOG("MISC", ERROR, __VA_ARGS__)
-#define ANKI_MISC_LOGW(...) ANKI_LOG("MISC", WARNING, __VA_ARGS__)
-#define ANKI_MISC_LOGF(...) ANKI_LOG("MISC", FATAL, __VA_ARGS__)
-
-} // end namespace anki

+ 0 - 306
src/anki/misc/ConfigSet.cpp

@@ -1,306 +0,0 @@
-// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#include <anki/misc/ConfigSet.h>
-#include <anki/util/Xml.h>
-#include <anki/util/Logger.h>
-#include <anki/util/File.h>
-
-namespace anki
-{
-
-ConfigSet::ConfigSet()
-{
-	m_alloc = HeapAllocator<U8>(allocAligned, nullptr);
-}
-
-ConfigSet::~ConfigSet()
-{
-	for(Option& o : m_options)
-	{
-		o.m_name.destroy(m_alloc);
-		o.m_strVal.destroy(m_alloc);
-		o.m_helpMsg.destroy(m_alloc);
-	}
-
-	m_options.destroy(m_alloc);
-}
-
-ConfigSet& ConfigSet::operator=(const ConfigSet& b)
-{
-	m_alloc = b.m_alloc; // Not a copy but we are fine
-
-	for(const Option& o : b.m_options)
-	{
-		Option newO;
-		newO.m_name.create(m_alloc, o.m_name.toCString());
-		if(o.m_type == 0)
-		{
-			newO.m_strVal.create(m_alloc, o.m_strVal.toCString());
-		}
-		newO.m_fVal = o.m_fVal;
-		newO.m_type = o.m_type;
-
-		m_options.emplaceBack(m_alloc, std::move(newO));
-	}
-
-	return *this;
-}
-
-ConfigSet::Option* ConfigSet::tryFind(const CString& name)
-{
-	List<Option>::Iterator it = m_options.getBegin();
-	for(; it != m_options.getEnd(); ++it)
-	{
-		if((*it).m_name == name)
-		{
-			return &(*it);
-		}
-	}
-
-	return nullptr;
-}
-
-const ConfigSet::Option* ConfigSet::tryFind(const CString& name) const
-{
-	List<Option>::ConstIterator it = m_options.getBegin();
-	for(; it != m_options.getEnd(); ++it)
-	{
-		if((*it).m_name == name)
-		{
-			return &(*it);
-		}
-	}
-
-	return nullptr;
-}
-
-void ConfigSet::newOption(const CString& name, const CString& value, const CString& helpMsg)
-{
-	ANKI_ASSERT(!tryFind(name));
-
-	Option o;
-	o.m_name.create(m_alloc, name);
-	o.m_strVal.create(m_alloc, value);
-	o.m_type = 0;
-	if(!helpMsg.isEmpty())
-	{
-		o.m_helpMsg.create(m_alloc, helpMsg);
-	}
-
-	m_options.emplaceBack(m_alloc, std::move(o));
-}
-
-void ConfigSet::newOption(const CString& name, F64 value, const CString& helpMsg)
-{
-	ANKI_ASSERT(!tryFind(name));
-
-	Option o;
-	o.m_name.create(m_alloc, name);
-	o.m_fVal = value;
-	o.m_type = 1;
-	if(!helpMsg.isEmpty())
-	{
-		o.m_helpMsg.create(m_alloc, helpMsg);
-	}
-
-	m_options.emplaceBack(m_alloc, std::move(o));
-}
-
-void ConfigSet::set(const CString& name, F64 value)
-{
-	Option* o = tryFind(name);
-	ANKI_ASSERT(o);
-	ANKI_ASSERT(o->m_type == 1);
-	o->m_fVal = value;
-}
-
-void ConfigSet::set(const CString& name, const CString& value)
-{
-	Option* o = tryFind(name);
-	ANKI_ASSERT(o);
-	ANKI_ASSERT(o->m_type == 0);
-	o->m_strVal.destroy(m_alloc);
-	o->m_strVal.create(m_alloc, value);
-}
-
-F64 ConfigSet::getNumberF64(const CString& name) const
-{
-	const Option* option = tryFind(name);
-	ANKI_ASSERT(option);
-	ANKI_ASSERT(option->m_type == 1);
-	return option->m_fVal;
-}
-
-F32 ConfigSet::getNumberF32(const CString& name) const
-{
-	return F32(getNumberF64(name));
-}
-
-U32 ConfigSet::getNumberU32(const CString& name) const
-{
-	return U32(getNumberF64(name));
-}
-
-U16 ConfigSet::getNumberU16(const CString& name) const
-{
-	return U16(getNumberU32(name));
-}
-
-U8 ConfigSet::getNumberU8(const CString& name) const
-{
-	return U8(getNumberU32(name));
-}
-
-Bool ConfigSet::getBool(const CString& name) const
-{
-	const U32 val = getNumberU32(name);
-	if((val & ~U32(1)) != 0)
-	{
-		ANKI_MISC_LOGW("Expecting 0 or 1 for the config option \"%s\". Will mask out extra bits", name.cstr());
-	}
-	return val & 1;
-}
-
-CString ConfigSet::getString(const CString& name) const
-{
-	const Option* o = tryFind(name);
-	ANKI_ASSERT(o);
-	ANKI_ASSERT(o->m_type == 0);
-	return o->m_strVal.toCString();
-}
-
-Error ConfigSet::loadFromFile(CString filename)
-{
-	ANKI_MISC_LOGI("Loading config file %s", &filename[0]);
-	XmlDocument xml;
-	ANKI_CHECK(xml.loadFile(filename, m_alloc));
-
-	XmlElement rootel;
-	ANKI_CHECK(xml.getChildElement("config", rootel));
-
-	for(Option& option : m_options)
-	{
-		XmlElement el;
-		ANKI_CHECK(rootel.getChildElementOptional(option.m_name.toCString(), el));
-
-		if(el)
-		{
-			if(option.m_type == 1)
-			{
-				ANKI_CHECK(el.getNumber(option.m_fVal));
-			}
-			else
-			{
-				CString txt;
-				ANKI_CHECK(el.getText(txt));
-				option.m_strVal.destroy(m_alloc);
-				option.m_strVal.create(m_alloc, txt);
-			}
-		}
-		else
-		{
-			if(option.m_type == 0)
-			{
-				ANKI_MISC_LOGW("Missing option for \"%s\". Will use the default value: %s",
-					&option.m_name[0],
-					&option.m_strVal[0]);
-			}
-			else
-			{
-				ANKI_MISC_LOGW(
-					"Missing option for \"%s\". Will use the default value: %f", &option.m_name[0], option.m_fVal);
-			}
-		}
-	}
-
-	return Error::NONE;
-}
-
-Error ConfigSet::saveToFile(CString filename) const
-{
-	ANKI_MISC_LOGI("Saving config file %s", &filename[0]);
-
-	File file;
-	ANKI_CHECK(file.open(filename, FileOpenFlag::WRITE));
-
-	ANKI_CHECK(file.writeText("%s\n<config>\n", &XmlDocument::XML_HEADER[0]));
-
-	for(const Option& option : m_options)
-	{
-		if(!option.m_helpMsg.isEmpty())
-		{
-			ANKI_CHECK(file.writeText("\t<!-- %s -->\n", &option.m_helpMsg[0]));
-		}
-
-		if(option.m_type == 1)
-		{
-			// Some of the options are integers so try not to make them appear as floats in the file
-			if(option.m_fVal == round(option.m_fVal) && option.m_fVal >= 0.0)
-			{
-				ANKI_CHECK(file.writeText("\t<%s>%u</%s>\n", &option.m_name[0], U(option.m_fVal), &option.m_name[0]));
-			}
-			else
-			{
-				ANKI_CHECK(file.writeText("\t<%s>%f</%s>\n", &option.m_name[0], option.m_fVal, &option.m_name[0]));
-			}
-		}
-		else
-		{
-			ANKI_CHECK(file.writeText(
-				"\t<%s><![CDATA[%s]]></%s>\n", &option.m_name[0], &option.m_strVal[0], &option.m_name[0]));
-		}
-	}
-
-	ANKI_CHECK(file.writeText("</config>\n"));
-	return Error::NONE;
-}
-
-Error ConfigSet::setFromCommandLineArguments(U cmdLineArgsCount, char* cmdLineArgs[])
-{
-	for(U i = 0; i < cmdLineArgsCount; ++i)
-	{
-		const char* arg = cmdLineArgs[i];
-		ANKI_ASSERT(arg);
-		if(CString(arg) == "-cfg")
-		{
-			if(i + 2 >= cmdLineArgsCount)
-			{
-				ANKI_MISC_LOGE("Wrong number of arguments after -cfg");
-				return Error::USER_DATA;
-			}
-
-			// Get the option
-			++i;
-			arg = cmdLineArgs[i];
-			ANKI_ASSERT(arg);
-			Option* option = tryFind(arg);
-			if(option == nullptr)
-			{
-				ANKI_MISC_LOGE("Option name following -cfg not found: %s", arg);
-				return Error::USER_DATA;
-			}
-
-			// Set the value
-			++i;
-			arg = cmdLineArgs[i];
-			ANKI_ASSERT(arg);
-			if(option->m_type == 0)
-			{
-				option->m_strVal.destroy(m_alloc);
-				option->m_strVal.create(m_alloc, arg);
-			}
-			else
-			{
-				CString val(arg);
-				ANKI_CHECK(val.toNumber(option->m_fVal));
-			}
-		}
-	}
-
-	return Error::NONE;
-}
-
-} // end namespace anki

+ 0 - 96
src/anki/misc/ConfigSet.h

@@ -1,96 +0,0 @@
-// Copyright (C) 2009-2019, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-#pragma once
-
-#include <anki/misc/Common.h>
-#include <anki/util/List.h>
-#include <anki/util/String.h>
-
-namespace anki
-{
-
-/// @addtogroup misc
-/// @{
-
-/// A storage of configuration variables.
-class ConfigSet
-{
-public:
-	ConfigSet();
-
-	/// Copy.
-	ConfigSet(const ConfigSet& b)
-	{
-		operator=(b);
-	}
-
-	~ConfigSet();
-
-	/// Copy.
-	ConfigSet& operator=(const ConfigSet& b);
-
-	/// @name Set an option
-	/// @{
-	void set(const CString& name, const CString& value);
-	void set(const CString& name, F64 value);
-	/// @}
-
-	/// @name Find an option and return its value.
-	/// @{
-	F64 getNumberF64(const CString& name) const;
-	F32 getNumberF32(const CString& name) const;
-	U32 getNumberU32(const CString& name) const;
-	U16 getNumberU16(const CString& name) const;
-	U8 getNumberU8(const CString& name) const;
-	Bool getBool(const CString& name) const;
-	CString getString(const CString& name) const;
-	/// @}
-
-	ANKI_USE_RESULT Error loadFromFile(CString filename);
-
-	ANKI_USE_RESULT Error saveToFile(CString filename) const;
-
-	ANKI_USE_RESULT Error setFromCommandLineArguments(U cmdLineArgsCount, char* cmdLineArgs[]);
-
-protected:
-	void newOption(const CString& name, const CString& value, const CString& helpMsg = "");
-	void newOption(const CString& name, F64 value, const CString& helpMsg = "");
-
-private:
-	class Option : public NonCopyable
-	{
-	public:
-		String m_name;
-		String m_strVal;
-		String m_helpMsg;
-		F64 m_fVal = 0.0f;
-		U8 m_type = 0; ///< 0: string, 1: float
-
-		Option() = default;
-
-		Option(Option&& b)
-			: m_name(std::move(b.m_name))
-			, m_strVal(std::move(b.m_strVal))
-			, m_helpMsg(std::move(b.m_helpMsg))
-			, m_fVal(b.m_fVal)
-			, m_type(b.m_type)
-		{
-		}
-
-		~Option() = default;
-
-		Option& operator=(Option&& b) = delete;
-	};
-
-	HeapAllocator<U8> m_alloc;
-	List<Option> m_options;
-
-	Option* tryFind(const CString& name);
-	const Option* tryFind(const CString& name) const;
-};
-/// @}
-
-} // end namespace anki

+ 6 - 3
src/anki/renderer/Bloom.cpp

@@ -8,11 +8,14 @@
 #include <anki/renderer/FinalComposite.h>
 #include <anki/renderer/FinalComposite.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Tonemapping.h>
 #include <anki/renderer/Tonemapping.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_bloomThreshold, 2.5, 0.0, 256.0)
+ANKI_REGISTER_CONFIG_OPTION(r_bloomScale, 2.5, 0.0, 256.0)
+
 Bloom::Bloom(Renderer* r)
 Bloom::Bloom(Renderer* r)
 	: RendererObject(r)
 	: RendererObject(r)
 {
 {
@@ -27,8 +30,8 @@ Error Bloom::initExposure(const ConfigSet& config)
 	m_exposure.m_width = m_r->getDownscaleBlur().getPassWidth(MAX_U32) * 2;
 	m_exposure.m_width = m_r->getDownscaleBlur().getPassWidth(MAX_U32) * 2;
 	m_exposure.m_height = m_r->getDownscaleBlur().getPassHeight(MAX_U32) * 2;
 	m_exposure.m_height = m_r->getDownscaleBlur().getPassHeight(MAX_U32) * 2;
 
 
-	m_exposure.m_threshold = config.getNumberF32("r.bloom.threshold");
-	m_exposure.m_scale = config.getNumberF32("r.bloom.scale");
+	m_exposure.m_threshold = config.getNumberF32("r_bloomThreshold");
+	m_exposure.m_scale = config.getNumberF32("r_bloomScale");
 
 
 	// Create RT info
 	// Create RT info
 	m_exposure.m_rtDescr =
 	m_exposure.m_rtDescr =

+ 5 - 3
src/anki/renderer/ClusterBin.cpp

@@ -8,11 +8,13 @@
 #include <anki/Collision.h>
 #include <anki/Collision.h>
 #include <anki/util/ThreadHive.h>
 #include <anki/util/ThreadHive.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
-#include <anki/core/Config.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_avgObjectsPerCluster, 16, 16, 256)
+
 /// Get a view space point.
 /// Get a view space point.
 static Vec4 unproject(const F32 zVspace, const Vec2& ndc, const Vec4& unprojParams)
 static Vec4 unproject(const F32 zVspace, const Vec2& ndc, const Vec4& unprojParams)
 {
 {
@@ -114,7 +116,7 @@ void ClusterBin::init(
 
 
 	m_totalClusterCount = clusterCountX * clusterCountY * clusterCountZ;
 	m_totalClusterCount = clusterCountX * clusterCountY * clusterCountZ;
 
 
-	m_avgObjectsPerCluster = cfg.getNumberU32("r.avgObjectsPerCluster");
+	m_avgObjectsPerCluster = cfg.getNumberU32("r_avgObjectsPerCluster");
 
 
 	// The actual indices per cluster are
 	// The actual indices per cluster are
 	// - the object indices per cluster
 	// - the object indices per cluster
@@ -339,7 +341,7 @@ void ClusterBin::binTile(U32 tileIdx, BinCtx& ctx, TileCtx& tileCtx)
 	ClusterBin::TileCtx::ClusterMetaInfo& inf = tileCtx.m_clusterInfos[clusterZ]; \
 	ClusterBin::TileCtx::ClusterMetaInfo& inf = tileCtx.m_clusterInfos[clusterZ]; \
 	if(ANKI_UNLIKELY(U32(inf.m_offset) + 1 >= m_avgObjectsPerCluster)) \
 	if(ANKI_UNLIKELY(U32(inf.m_offset) + 1 >= m_avgObjectsPerCluster)) \
 	{ \
 	{ \
-		ANKI_R_LOGW("Out of cluster indices. Increase r.avgObjectsPerCluster"); \
+		ANKI_R_LOGW("Out of cluster indices. Increase r_avgObjectsPerCluster"); \
 		continue; \
 		continue; \
 	} \
 	} \
 	tileCtx.getClusterIndices(clusterZ)[inf.m_offset++] = i; \
 	tileCtx.getClusterIndices(clusterZ)[inf.m_offset++] = i; \

+ 4 - 2
src/anki/renderer/Dbg.cpp

@@ -12,12 +12,14 @@
 #include <anki/Scene.h>
 #include <anki/Scene.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Enum.h>
 #include <anki/util/Enum.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/collision/ConvexHullShape.h>
 #include <anki/collision/ConvexHullShape.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_dbgEnabled, 0, 0, 1)
+
 Dbg::Dbg(Renderer* r)
 Dbg::Dbg(Renderer* r)
 	: RendererObject(r)
 	: RendererObject(r)
 {
 {
@@ -29,7 +31,7 @@ Dbg::~Dbg()
 
 
 Error Dbg::init(const ConfigSet& initializer)
 Error Dbg::init(const ConfigSet& initializer)
 {
 {
-	m_enabled = initializer.getBool("r.dbg.enabled");
+	m_enabled = initializer.getBool("r_dbgEnabled");
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 

+ 4 - 2
src/anki/renderer/FinalComposite.cpp

@@ -16,11 +16,13 @@
 #include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/UiStage.h>
 #include <anki/renderer/UiStage.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Logger.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_motionBlurSamples, 32, 1, 2048)
+
 FinalComposite::FinalComposite(Renderer* r)
 FinalComposite::FinalComposite(Renderer* r)
 	: RendererObject(r)
 	: RendererObject(r)
 {
 {
@@ -51,7 +53,7 @@ Error FinalComposite::initInternal(const ConfigSet& config)
 	ShaderProgramResourceConstantValueInitList<3> consts(m_prog);
 	ShaderProgramResourceConstantValueInitList<3> consts(m_prog);
 	consts.add("LUT_SIZE", U32(LUT_SIZE))
 	consts.add("LUT_SIZE", U32(LUT_SIZE))
 		.add("FB_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()))
 		.add("FB_SIZE", UVec2(m_r->getWidth(), m_r->getHeight()))
-		.add("MOTION_BLUR_SAMPLES", config.getNumberU32("r.final.motionBlurSamples"));
+		.add("MOTION_BLUR_SAMPLES", config.getNumberU32("r_motionBlurSamples"));
 
 
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(mutations.get(), consts.get(), variant);
 	m_prog->getOrCreateVariant(mutations.get(), consts.get(), variant);

+ 1 - 1
src/anki/renderer/GBuffer.cpp

@@ -9,7 +9,7 @@
 #include <anki/renderer/LensFlare.h>
 #include <anki/renderer/LensFlare.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {

+ 4 - 4
src/anki/renderer/GBufferPost.cpp

@@ -7,7 +7,7 @@
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/GBuffer.h>
 #include <anki/renderer/GBuffer.h>
 #include <anki/renderer/LightShading.h>
 #include <anki/renderer/LightShading.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -34,9 +34,9 @@ Error GBufferPost::initInternal(const ConfigSet& cfg)
 	ANKI_CHECK(getResourceManager().loadResource("shaders/GBufferPost.glslp", m_prog));
 	ANKI_CHECK(getResourceManager().loadResource("shaders/GBufferPost.glslp", m_prog));
 
 
 	ShaderProgramResourceConstantValueInitList<3> consts(m_prog);
 	ShaderProgramResourceConstantValueInitList<3> consts(m_prog);
-	consts.add("CLUSTER_COUNT_X", cfg.getNumberU32("r.clusterSizeX"));
-	consts.add("CLUSTER_COUNT_Y", cfg.getNumberU32("r.clusterSizeY"));
-	consts.add("CLUSTER_COUNT_Z", cfg.getNumberU32("r.clusterSizeZ"));
+	consts.add("CLUSTER_COUNT_X", cfg.getNumberU32("r_clusterSizeX"));
+	consts.add("CLUSTER_COUNT_Y", cfg.getNumberU32("r_clusterSizeY"));
+	consts.add("CLUSTER_COUNT_Z", cfg.getNumberU32("r_clusterSizeZ"));
 
 
 	const ShaderProgramResourceVariant* variant;
 	const ShaderProgramResourceVariant* variant;
 	m_prog->getOrCreateVariant(consts.get(), variant);
 	m_prog->getOrCreateVariant(consts.get(), variant);

+ 12 - 7
src/anki/renderer/GlobalIllumination.cpp

@@ -6,7 +6,7 @@
 #include <anki/renderer/GlobalIllumination.h>
 #include <anki/renderer/GlobalIllumination.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
 #include <anki/collision/Aabb.h>
 #include <anki/collision/Aabb.h>
 #include <anki/collision/Functions.h>
 #include <anki/collision/Functions.h>
@@ -14,6 +14,11 @@
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_giTileResolution, 32, 4, 2048)
+ANKI_REGISTER_CONFIG_OPTION(r_giShadowMapResolution, 128, 4, 2048)
+ANKI_REGISTER_CONFIG_OPTION(r_giMaxCachedProbes, 16, 4, 2048)
+ANKI_REGISTER_CONFIG_OPTION(r_giMaxVisibleProbes, 8, 1, 256)
+
 /// Given a cell index compute its world position.
 /// Given a cell index compute its world position.
 static Vec3 computeProbeCellPosition(U32 cellIdx, const GlobalIlluminationProbeQueueElement& probe)
 static Vec3 computeProbeCellPosition(U32 cellIdx, const GlobalIlluminationProbeQueueElement& probe)
 {
 {
@@ -117,9 +122,9 @@ Error GlobalIllumination::init(const ConfigSet& cfg)
 
 
 Error GlobalIllumination::initInternal(const ConfigSet& cfg)
 Error GlobalIllumination::initInternal(const ConfigSet& cfg)
 {
 {
-	m_tileSize = cfg.getNumberU32("r.gi.tileResolution");
-	m_cacheEntries.create(getAllocator(), cfg.getNumberU32("r.gi.maxCachedProbes"));
-	m_maxVisibleProbes = cfg.getNumberU32("r.gi.maxVisibleProbes");
+	m_tileSize = cfg.getNumberU32("r_giTileResolution");
+	m_cacheEntries.create(getAllocator(), cfg.getNumberU32("r_giMaxCachedProbes"));
+	m_maxVisibleProbes = cfg.getNumberU32("r_giMaxVisibleProbes");
 	ANKI_ASSERT(m_maxVisibleProbes <= MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
 	ANKI_ASSERT(m_maxVisibleProbes <= MAX_VISIBLE_GLOBAL_ILLUMINATION_PROBES);
 	ANKI_ASSERT(m_cacheEntries.getSize() >= m_maxVisibleProbes);
 	ANKI_ASSERT(m_cacheEntries.getSize() >= m_maxVisibleProbes);
 
 
@@ -175,7 +180,7 @@ Error GlobalIllumination::initGBuffer(const ConfigSet& cfg)
 
 
 Error GlobalIllumination::initShadowMapping(const ConfigSet& cfg)
 Error GlobalIllumination::initShadowMapping(const ConfigSet& cfg)
 {
 {
-	const U32 resolution = cfg.getNumberU32("r.gi.shadowMapResolution");
+	const U32 resolution = cfg.getNumberU32("r_giShadowMapResolution");
 	ANKI_ASSERT(resolution > 8);
 	ANKI_ASSERT(resolution > 8);
 
 
 	// RT descr
 	// RT descr
@@ -451,7 +456,7 @@ void GlobalIllumination::prepareProbes(InternalContext& giCtx)
 	{
 	{
 		if(newListOfProbeCount + 1 >= m_maxVisibleProbes)
 		if(newListOfProbeCount + 1 >= m_maxVisibleProbes)
 		{
 		{
-			ANKI_R_LOGW("Can't have more that %u visible probes. Increase the r.gi.maxVisibleProbes or (somehow) "
+			ANKI_R_LOGW("Can't have more that %u visible probes. Increase the r_giMaxVisibleProbes or (somehow) "
 						"decrease the visible probes",
 						"decrease the visible probes",
 				m_maxVisibleProbes);
 				m_maxVisibleProbes);
 			break;
 			break;
@@ -466,7 +471,7 @@ void GlobalIllumination::prepareProbes(InternalContext& giCtx)
 		{
 		{
 			// Failed
 			// Failed
 			ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
 			ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
-						"Increase the r.gi.maxCachedProbes or (somehow) decrease the visible probes");
+						"Increase the r_giMaxCachedProbes or (somehow) decrease the visible probes");
 			continue;
 			continue;
 		}
 		}
 
 

+ 6 - 3
src/anki/renderer/LensFlare.cpp

@@ -7,13 +7,16 @@
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/Functions.h>
 #include <anki/util/Functions.h>
 #include <shaders/glsl_cpp_common/LensFlareSprite.h>
 #include <shaders/glsl_cpp_common/LensFlareSprite.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_lensFlareMaxSpritesPerFlare, 8, 4, 256)
+ANKI_REGISTER_CONFIG_OPTION(r_lensFlareMaxFlares, 16, 8, 256)
+
 LensFlare::~LensFlare()
 LensFlare::~LensFlare()
 {
 {
 }
 }
@@ -41,8 +44,8 @@ Error LensFlare::initInternal(const ConfigSet& config)
 
 
 Error LensFlare::initSprite(const ConfigSet& config)
 Error LensFlare::initSprite(const ConfigSet& config)
 {
 {
-	m_maxSpritesPerFlare = config.getNumberU8("r.lensFlare.maxSpritesPerFlare");
-	m_maxFlares = config.getNumberU8("r.lensFlare.maxFlares");
+	m_maxSpritesPerFlare = config.getNumberU8("r_lensFlareMaxSpritesPerFlare");
+	m_maxFlares = config.getNumberU8("r_lensFlareMaxFlares");
 
 
 	if(m_maxSpritesPerFlare < 1 || m_maxFlares < 1)
 	if(m_maxSpritesPerFlare < 1 || m_maxFlares < 1)
 	{
 	{

+ 1 - 1
src/anki/renderer/LightShading.cpp

@@ -15,7 +15,7 @@
 #include <anki/renderer/Ssao.h>
 #include <anki/renderer/Ssao.h>
 #include <anki/renderer/Ssr.h>
 #include <anki/renderer/Ssr.h>
 #include <anki/renderer/GlobalIllumination.h>
 #include <anki/renderer/GlobalIllumination.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/util/HighRezTimer.h>
 
 
 namespace anki
 namespace anki

+ 4 - 2
src/anki/renderer/MainRenderer.cpp

@@ -13,13 +13,15 @@
 #include <anki/util/File.h>
 #include <anki/util/File.h>
 #include <anki/util/Filesystem.h>
 #include <anki/util/Filesystem.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/util/ThreadHive.h>
 #include <anki/util/ThreadHive.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_renderingQuality, 1.0, 0.5, 1.0, "A factor over the requested renderingresolution")
+
 MainRenderer::MainRenderer()
 MainRenderer::MainRenderer()
 {
 {
 }
 }
@@ -48,7 +50,7 @@ Error MainRenderer::init(ThreadHive* hive,
 	m_width = config.getNumberU32("width");
 	m_width = config.getNumberU32("width");
 	m_height = config.getNumberU32("height");
 	m_height = config.getNumberU32("height");
 	ConfigSet config2 = config;
 	ConfigSet config2 = config;
-	m_renderingQuality = config.getNumberF32("r.renderingQuality");
+	m_renderingQuality = config.getNumberF32("r_renderingQuality");
 	UVec2 size(U32(m_renderingQuality * F32(m_width)), U32(m_renderingQuality * F32(m_height)));
 	UVec2 size(U32(m_renderingQuality * F32(m_width)), U32(m_renderingQuality * F32(m_height)));
 
 
 	config2.set("width", size.x());
 	config2.set("width", size.x());

+ 12 - 7
src/anki/renderer/ProbeReflections.cpp

@@ -8,7 +8,7 @@
 #include <anki/renderer/FinalComposite.h>
 #include <anki/renderer/FinalComposite.h>
 #include <anki/renderer/GBuffer.h>
 #include <anki/renderer/GBuffer.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
-#include <anki/core/Config.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
 #include <anki/resource/MeshResource.h>
 #include <anki/resource/MeshResource.h>
 #include <shaders/glsl_cpp_common/TraditionalDeferredShading.h>
 #include <shaders/glsl_cpp_common/TraditionalDeferredShading.h>
@@ -16,6 +16,11 @@
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_probeReflectionResolution, 128, 4, 2048)
+ANKI_REGISTER_CONFIG_OPTION(r_probeReflectionIrradianceResolution, 16, 4, 2048)
+ANKI_REGISTER_CONFIG_OPTION(r_probeRefectionlMaxSimultaneousProbeCount, 32, 4, 256)
+ANKI_REGISTER_CONFIG_OPTION(r_probeReflectionShadowMapResolution, 64, 4, 2048)
+
 ProbeReflections::ProbeReflections(Renderer* r)
 ProbeReflections::ProbeReflections(Renderer* r)
 	: RendererObject(r)
 	: RendererObject(r)
 	, m_lightShading(r)
 	, m_lightShading(r)
@@ -44,7 +49,7 @@ Error ProbeReflections::init(const ConfigSet& config)
 Error ProbeReflections::initInternal(const ConfigSet& config)
 Error ProbeReflections::initInternal(const ConfigSet& config)
 {
 {
 	// Init cache entries
 	// Init cache entries
-	m_cacheEntries.create(getAllocator(), config.getNumberU32("r.indirect.maxSimultaneousProbeCount"));
+	m_cacheEntries.create(getAllocator(), config.getNumberU32("r_probeRefectionlMaxSimultaneousProbeCount"));
 
 
 	ANKI_CHECK(initGBuffer(config));
 	ANKI_CHECK(initGBuffer(config));
 	ANKI_CHECK(initLightShading(config));
 	ANKI_CHECK(initLightShading(config));
@@ -68,7 +73,7 @@ Error ProbeReflections::initInternal(const ConfigSet& config)
 
 
 Error ProbeReflections::initGBuffer(const ConfigSet& config)
 Error ProbeReflections::initGBuffer(const ConfigSet& config)
 {
 {
-	m_gbuffer.m_tileSize = config.getNumberU32("r.indirect.reflectionResolution");
+	m_gbuffer.m_tileSize = config.getNumberU32("r_probeReflectionResolution");
 
 
 	// Create RT descriptions
 	// Create RT descriptions
 	{
 	{
@@ -115,7 +120,7 @@ Error ProbeReflections::initGBuffer(const ConfigSet& config)
 
 
 Error ProbeReflections::initLightShading(const ConfigSet& config)
 Error ProbeReflections::initLightShading(const ConfigSet& config)
 {
 {
-	m_lightShading.m_tileSize = config.getNumberU32("r.indirect.reflectionResolution");
+	m_lightShading.m_tileSize = config.getNumberU32("r_probeReflectionResolution");
 	m_lightShading.m_mipCount = computeMaxMipmapCount2d(m_lightShading.m_tileSize, m_lightShading.m_tileSize, 8);
 	m_lightShading.m_mipCount = computeMaxMipmapCount2d(m_lightShading.m_tileSize, m_lightShading.m_tileSize, 8);
 
 
 	// Init cube arr
 	// Init cube arr
@@ -143,7 +148,7 @@ Error ProbeReflections::initLightShading(const ConfigSet& config)
 
 
 Error ProbeReflections::initIrradiance(const ConfigSet& config)
 Error ProbeReflections::initIrradiance(const ConfigSet& config)
 {
 {
-	m_irradiance.m_workgroupSize = config.getNumberU32("r.indirect.irradianceResolution");
+	m_irradiance.m_workgroupSize = config.getNumberU32("r_probeReflectionIrradianceResolution");
 
 
 	// Create prog
 	// Create prog
 	{
 	{
@@ -188,7 +193,7 @@ Error ProbeReflections::initIrradianceToRefl(const ConfigSet& cfg)
 
 
 Error ProbeReflections::initShadowMapping(const ConfigSet& cfg)
 Error ProbeReflections::initShadowMapping(const ConfigSet& cfg)
 {
 {
-	const U32 resolution = cfg.getNumberU32("r.indirect.shadowMapResolution");
+	const U32 resolution = cfg.getNumberU32("r_probeReflectionShadowMapResolution");
 	ANKI_ASSERT(resolution > 8);
 	ANKI_ASSERT(resolution > 8);
 
 
 	// RT descr
 	// RT descr
@@ -264,7 +269,7 @@ void ProbeReflections::prepareProbes(RenderingContext& ctx,
 		{
 		{
 			// Failed
 			// Failed
 			ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
 			ANKI_R_LOGW("There is not enough space in the indirect lighting atlas for more probes. "
-						"Increase the r.indirect.maxSimultaneousProbeCount or decrease the scene's probes");
+						"Increase the r_probeRefectionlMaxSimultaneousProbeCount or decrease the scene's probes");
 			continue;
 			continue;
 		}
 		}
 
 

+ 14 - 7
src/anki/renderer/Renderer.cpp

@@ -6,7 +6,7 @@
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/collision/Aabb.h>
 #include <anki/collision/Aabb.h>
 
 
@@ -36,6 +36,13 @@
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_lodDistance0, 20.0, 1.0, MAX_F64, "Distance that will be used to calculate the LOD 0")
+ANKI_REGISTER_CONFIG_OPTION(r_lodDistance1, 40.0, 2.0, MAX_F64, "Distance that will be used to calculate the LOD 1")
+ANKI_REGISTER_CONFIG_OPTION(r_clusterSizeX, 32, 1, 256)
+ANKI_REGISTER_CONFIG_OPTION(r_clusterSizeY, 26, 1, 256)
+ANKI_REGISTER_CONFIG_OPTION(r_clusterSizeZ, 32, 1, 256)
+ANKI_REGISTER_CONFIG_OPTION(r_textureAnisotropy, 8, 1, 16)
+
 Renderer::Renderer()
 Renderer::Renderer()
 	: m_sceneDrawer(this)
 	: m_sceneDrawer(this)
 {
 {
@@ -81,13 +88,13 @@ Error Renderer::initInternal(const ConfigSet& config)
 	ANKI_R_LOGI("Initializing offscreen renderer. Size %ux%u", m_width, m_height);
 	ANKI_R_LOGI("Initializing offscreen renderer. Size %ux%u", m_width, m_height);
 
 
 	ANKI_ASSERT(m_lodDistances.getSize() == 2);
 	ANKI_ASSERT(m_lodDistances.getSize() == 2);
-	m_lodDistances[0] = config.getNumberF32("r.lodDistance0");
-	m_lodDistances[1] = config.getNumberF32("r.lodDistance1");
+	m_lodDistances[0] = config.getNumberF32("r_lodDistance0");
+	m_lodDistances[1] = config.getNumberF32("r_lodDistance1");
 	m_frameCount = 0;
 	m_frameCount = 0;
 
 
-	m_clusterCount[0] = config.getNumberU32("r.clusterSizeX");
-	m_clusterCount[1] = config.getNumberU32("r.clusterSizeY");
-	m_clusterCount[2] = config.getNumberU32("r.clusterSizeZ");
+	m_clusterCount[0] = config.getNumberU32("r_clusterSizeX");
+	m_clusterCount[1] = config.getNumberU32("r_clusterSizeY");
+	m_clusterCount[2] = config.getNumberU32("r_clusterSizeZ");
 	m_clusterCount[3] = m_clusterCount[0] * m_clusterCount[1] * m_clusterCount[2];
 	m_clusterCount[3] = m_clusterCount[0] * m_clusterCount[1] * m_clusterCount[2];
 
 
 	m_clusterBin.init(m_alloc, m_clusterCount[0], m_clusterCount[1], m_clusterCount[2], config);
 	m_clusterBin.init(m_alloc, m_clusterCount[0], m_clusterCount[1], m_clusterCount[2], config);
@@ -201,7 +208,7 @@ Error Renderer::initInternal(const ConfigSet& config)
 		sinit.m_addressing = SamplingAddressing::REPEAT;
 		sinit.m_addressing = SamplingAddressing::REPEAT;
 		m_samplers.m_trilinearRepeat = m_gr->newSampler(sinit);
 		m_samplers.m_trilinearRepeat = m_gr->newSampler(sinit);
 
 
-		sinit.m_anisotropyLevel = U8(config.getNumberU32("r.textureAnisotropy"));
+		sinit.m_anisotropyLevel = U8(config.getNumberU32("r_textureAnisotropy"));
 		m_samplers.m_trilinearRepeatAniso = m_gr->newSampler(sinit);
 		m_samplers.m_trilinearRepeatAniso = m_gr->newSampler(sinit);
 	}
 	}
 
 

+ 21 - 10
src/anki/renderer/ShadowMapping.cpp

@@ -6,13 +6,24 @@
 #include <anki/renderer/ShadowMapping.h>
 #include <anki/renderer/ShadowMapping.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/ThreadHive.h>
 #include <anki/util/ThreadHive.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_shadowMappingTileResolution, 128, 16, 2048)
+ANKI_REGISTER_CONFIG_OPTION(r_shadowMappingTileCountPerRowOrColumn, 16, 1, 256)
+ANKI_REGISTER_CONFIG_OPTION(r_shadowMappingScratchTileCountX,
+	4 * (MAX_SHADOW_CASCADES + 2),
+	1u,
+	256u,
+	"Number of tiles of the scratch buffer in X")
+ANKI_REGISTER_CONFIG_OPTION(r_shadowMappingScratchTileCountY, 4, 1, 256, "Number of tiles of the scratch buffer in Y")
+ANKI_REGISTER_CONFIG_OPTION(r_shadowMappingLightLodDistance0, 10.0, 1.0, MAX_F64)
+ANKI_REGISTER_CONFIG_OPTION(r_shadowMappingLightLodDistance1, 20.0, 2.0, MAX_F64)
+
 class ShadowMapping::Scratch::WorkItem
 class ShadowMapping::Scratch::WorkItem
 {
 {
 public:
 public:
@@ -69,9 +80,9 @@ Error ShadowMapping::initScratch(const ConfigSet& cfg)
 {
 {
 	// Init the shadowmaps and FBs
 	// Init the shadowmaps and FBs
 	{
 	{
-		m_scratch.m_tileCountX = cfg.getNumberU32("r.shadowMapping.scratchTileCountX");
-		m_scratch.m_tileCountY = cfg.getNumberU32("r.shadowMapping.scratchTileCountY");
-		m_scratch.m_tileResolution = cfg.getNumberU32("r.shadowMapping.tileResolution");
+		m_scratch.m_tileCountX = cfg.getNumberU32("r_shadowMappingScratchTileCountX");
+		m_scratch.m_tileCountY = cfg.getNumberU32("r_shadowMappingScratchTileCountY");
+		m_scratch.m_tileResolution = cfg.getNumberU32("r_shadowMappingTileResolution");
 
 
 		// RT
 		// RT
 		m_scratch.m_rtDescr = m_r->create2DRenderTargetDescription(m_scratch.m_tileResolution * m_scratch.m_tileCountX,
 		m_scratch.m_rtDescr = m_r->create2DRenderTargetDescription(m_scratch.m_tileResolution * m_scratch.m_tileCountX,
@@ -96,8 +107,8 @@ Error ShadowMapping::initAtlas(const ConfigSet& cfg)
 {
 {
 	// Init RT
 	// Init RT
 	{
 	{
-		m_atlas.m_tileResolution = cfg.getNumberU32("r.shadowMapping.tileResolution");
-		m_atlas.m_tileCountBothAxis = cfg.getNumberU32("r.shadowMapping.tileCountPerRowOrColumn");
+		m_atlas.m_tileResolution = cfg.getNumberU32("r_shadowMappingTileResolution");
+		m_atlas.m_tileCountBothAxis = cfg.getNumberU32("r_shadowMappingTileCountPerRowOrColumn");
 
 
 		// RT
 		// RT
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
 		TextureInitInfo texinit = m_r->create2DRenderTargetInitInfo(
@@ -139,8 +150,8 @@ Error ShadowMapping::initInternal(const ConfigSet& cfg)
 	ANKI_CHECK(initScratch(cfg));
 	ANKI_CHECK(initScratch(cfg));
 	ANKI_CHECK(initAtlas(cfg));
 	ANKI_CHECK(initAtlas(cfg));
 
 
-	m_lodDistances[0] = cfg.getNumberF32("r.shadowMapping.lightLodDistance0");
-	m_lodDistances[1] = cfg.getNumberF32("r.shadowMapping.lightLodDistance1");
+	m_lodDistances[0] = cfg.getNumberF32("r_shadowMappingLightLodDistance0");
+	m_lodDistances[1] = cfg.getNumberF32("r_shadowMappingLightLodDistance1");
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }
@@ -405,7 +416,7 @@ TileAllocatorResult ShadowMapping::allocateTilesAndScratchTiles(U64 lightUuid,
 		if(res == TileAllocatorResult::ALLOCATION_FAILED)
 		if(res == TileAllocatorResult::ALLOCATION_FAILED)
 		{
 		{
 			ANKI_R_LOGW("There is not enough space in the shadow atlas for more shadow maps. "
 			ANKI_R_LOGW("There is not enough space in the shadow atlas for more shadow maps. "
-						"Increase the r.shadowMapping.tileCountPerRowOrColumn or decrease the scene's shadow casters");
+						"Increase the r_shadowMappingTileCountPerRowOrColumn or decrease the scene's shadow casters");
 
 
 			// Invalidate cache entries for what we already allocated
 			// Invalidate cache entries for what we already allocated
 			for(U j = 0; j < i; ++j)
 			for(U j = 0; j < i; ++j)
@@ -446,7 +457,7 @@ TileAllocatorResult ShadowMapping::allocateTilesAndScratchTiles(U64 lightUuid,
 		if(res == TileAllocatorResult::ALLOCATION_FAILED)
 		if(res == TileAllocatorResult::ALLOCATION_FAILED)
 		{
 		{
 			ANKI_R_LOGW("Don't have enough space in the scratch shadow mapping buffer. "
 			ANKI_R_LOGW("Don't have enough space in the scratch shadow mapping buffer. "
-						"If you see this message too often increase r.shadowMapping.scratchTileCountX/Y");
+						"If you see this message too often increase r_shadowMappingScratchTileCountX/Y");
 
 
 			// Invalidate atlas tiles
 			// Invalidate atlas tiles
 			for(U j = 0; j < faceCount; ++j)
 			for(U j = 0; j < faceCount; ++j)

+ 1 - 1
src/anki/renderer/Ssao.cpp

@@ -9,7 +9,7 @@
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/util/Functions.h>
 #include <anki/util/Functions.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {

+ 6 - 3
src/anki/renderer/Ssr.cpp

@@ -9,12 +9,15 @@
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/DepthDownscale.h>
 #include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/DownscaleBlur.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <shaders/glsl_cpp_common/Ssr.h>
 #include <shaders/glsl_cpp_common/Ssr.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_ssrMaxSteps, 64, 1, 2048)
+ANKI_REGISTER_CONFIG_OPTION(r_ssrHistoryBlendFactor, 0.3, 0.0, MAX_F64)
+
 Ssr::~Ssr()
 Ssr::~Ssr()
 {
 {
 }
 }
@@ -50,9 +53,9 @@ Error Ssr::initInternal(const ConfigSet& cfg)
 	ShaderProgramResourceConstantValueInitList<5> consts(m_prog);
 	ShaderProgramResourceConstantValueInitList<5> consts(m_prog);
 	consts.add("FB_SIZE", UVec2(width, height));
 	consts.add("FB_SIZE", UVec2(width, height));
 	consts.add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
 	consts.add("WORKGROUP_SIZE", UVec2(m_workgroupSize[0], m_workgroupSize[1]));
-	consts.add("MAX_STEPS", cfg.getNumberU32("r.ssr.maxSteps"));
+	consts.add("MAX_STEPS", cfg.getNumberU32("r_ssrMaxSteps"));
 	consts.add("LIGHT_BUFFER_MIP_COUNT", U32(m_r->getDownscaleBlur().getMipmapCount()));
 	consts.add("LIGHT_BUFFER_MIP_COUNT", U32(m_r->getDownscaleBlur().getMipmapCount()));
-	consts.add("HISTORY_COLOR_BLEND_FACTOR", cfg.getNumberF32("r.ssr.historyBlendFactor"));
+	consts.add("HISTORY_COLOR_BLEND_FACTOR", cfg.getNumberF32("r_ssrHistoryBlendFactor"));
 
 
 	ShaderProgramResourceMutationInitList<1> mutators(m_prog);
 	ShaderProgramResourceMutationInitList<1> mutators(m_prog);
 	mutators.add("VARIANT", 0);
 	mutators.add("VARIANT", 0);

+ 4 - 4
src/anki/renderer/VolumetricFog.cpp

@@ -10,7 +10,7 @@
 #include <anki/renderer/LightShading.h>
 #include <anki/renderer/LightShading.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/RenderQueue.h>
 #include <anki/renderer/VolumetricLightingAccumulation.h>
 #include <anki/renderer/VolumetricLightingAccumulation.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {
@@ -18,11 +18,11 @@ namespace anki
 Error VolumetricFog::init(const ConfigSet& config)
 Error VolumetricFog::init(const ConfigSet& config)
 {
 {
 	// Misc
 	// Misc
-	const U32 fractionXY = config.getNumberU32("r.volumetricLightingAccumulation.clusterFractionXY");
+	const U32 fractionXY = config.getNumberU32("r_volumetricLightingAccumulationClusterFractionXY");
 	ANKI_ASSERT(fractionXY >= 1);
 	ANKI_ASSERT(fractionXY >= 1);
-	const U32 fractionZ = config.getNumberU32("r.volumetricLightingAccumulation.clusterFractionZ");
+	const U32 fractionZ = config.getNumberU32("r_volumetricLightingAccumulationClusterFractionZ");
 	ANKI_ASSERT(fractionZ >= 1);
 	ANKI_ASSERT(fractionZ >= 1);
-	m_finalClusterZ = config.getNumberU32("r.volumetricLightingAccumulation.finalClusterInZ");
+	m_finalClusterZ = config.getNumberU32("r_volumetricLightingAccumulationFinalClusterInZ");
 	ANKI_ASSERT(m_finalClusterZ > 0 && m_finalClusterZ < m_r->getClusterCount()[2]);
 	ANKI_ASSERT(m_finalClusterZ > 0 && m_finalClusterZ < m_r->getClusterCount()[2]);
 
 
 	m_volumeSize[0] = m_r->getClusterCount()[0] * fractionXY;
 	m_volumeSize[0] = m_r->getClusterCount()[0] * fractionXY;

+ 8 - 4
src/anki/renderer/VolumetricLightingAccumulation.cpp

@@ -8,11 +8,15 @@
 #include <anki/renderer/GlobalIllumination.h>
 #include <anki/renderer/GlobalIllumination.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/renderer/Renderer.h>
 #include <anki/resource/TextureResource.h>
 #include <anki/resource/TextureResource.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(r_volumetricLightingAccumulationClusterFractionXY, 4, 1, 16)
+ANKI_REGISTER_CONFIG_OPTION(r_volumetricLightingAccumulationClusterFractionZ, 4, 1, 16)
+ANKI_REGISTER_CONFIG_OPTION(r_volumetricLightingAccumulationFinalClusterInZ, 26, 1, 256)
+
 VolumetricLightingAccumulation::VolumetricLightingAccumulation(Renderer* r)
 VolumetricLightingAccumulation::VolumetricLightingAccumulation(Renderer* r)
 	: RendererObject(r)
 	: RendererObject(r)
 {
 {
@@ -25,11 +29,11 @@ VolumetricLightingAccumulation::~VolumetricLightingAccumulation()
 Error VolumetricLightingAccumulation::init(const ConfigSet& config)
 Error VolumetricLightingAccumulation::init(const ConfigSet& config)
 {
 {
 	// Misc
 	// Misc
-	const U32 fractionXY = config.getNumberU32("r.volumetricLightingAccumulation.clusterFractionXY");
+	const U32 fractionXY = config.getNumberU32("r_volumetricLightingAccumulationClusterFractionXY");
 	ANKI_ASSERT(fractionXY >= 1);
 	ANKI_ASSERT(fractionXY >= 1);
-	const U32 fractionZ = config.getNumberU32("r.volumetricLightingAccumulation.clusterFractionZ");
+	const U32 fractionZ = config.getNumberU32("r_volumetricLightingAccumulationClusterFractionZ");
 	ANKI_ASSERT(fractionZ >= 1);
 	ANKI_ASSERT(fractionZ >= 1);
-	m_finalClusterZ = config.getNumberU32("r.volumetricLightingAccumulation.finalClusterInZ");
+	m_finalClusterZ = config.getNumberU32("r_volumetricLightingAccumulationFinalClusterInZ");
 	ANKI_ASSERT(m_finalClusterZ > 0 && m_finalClusterZ < m_r->getClusterCount()[2]);
 	ANKI_ASSERT(m_finalClusterZ > 0 && m_finalClusterZ < m_r->getClusterCount()[2]);
 
 
 	m_volumeSize[0] = m_r->getClusterCount()[0] * fractionXY;
 	m_volumeSize[0] = m_r->getClusterCount()[0] * fractionXY;

+ 3 - 3
src/anki/resource/ResourceFilesystem.cpp

@@ -5,7 +5,7 @@
 
 
 #include <anki/resource/ResourceFilesystem.h>
 #include <anki/resource/ResourceFilesystem.h>
 #include <anki/util/Filesystem.h>
 #include <anki/util/Filesystem.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
 #include <contrib/minizip/unzip.h>
 #include <contrib/minizip/unzip.h>
 
 
@@ -208,11 +208,11 @@ ResourceFilesystem::~ResourceFilesystem()
 Error ResourceFilesystem::init(const ConfigSet& config, const CString& cacheDir)
 Error ResourceFilesystem::init(const ConfigSet& config, const CString& cacheDir)
 {
 {
 	StringListAuto paths(m_alloc);
 	StringListAuto paths(m_alloc);
-	paths.splitString(config.getString("rsrc.dataPaths"), ':');
+	paths.splitString(config.getString("rsrc_dataPaths"), ':');
 
 
 	if(paths.getSize() < 1)
 	if(paths.getSize() < 1)
 	{
 	{
-		ANKI_RESOURCE_LOGE("Config option \"rsrc.dataPaths\" is empty");
+		ANKI_RESOURCE_LOGE("Config option \"rsrc_dataPaths\" is empty");
 		return Error::USER_DATA;
 		return Error::USER_DATA;
 	}
 	}
 
 

+ 10 - 4
src/anki/resource/ResourceManager.cpp

@@ -17,12 +17,18 @@
 #include <anki/resource/TextureAtlasResource.h>
 #include <anki/resource/TextureAtlasResource.h>
 #include <anki/resource/ShaderProgramResource.h>
 #include <anki/resource/ShaderProgramResource.h>
 #include <anki/util/Logger.h>
 #include <anki/util/Logger.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/gr/ShaderCompiler.h>
 #include <anki/gr/ShaderCompiler.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(rsrc_maxTextureSize, 1024u * 1024u, 4u, MAX_U32)
+ANKI_REGISTER_CONFIG_OPTION(rsrc_dumpShaderSources, 0, 0, 1)
+ANKI_REGISTER_CONFIG_OPTION(
+	rsrc_dataPaths, ".", "The engine loads assets only in from these paths. Separate them with :")
+ANKI_REGISTER_CONFIG_OPTION(rsrc_transferScratchMemorySize, 256_MB, 1_MB, 4_GB)
+
 ResourceManager::ResourceManager()
 ResourceManager::ResourceManager()
 {
 {
 }
 }
@@ -47,8 +53,8 @@ Error ResourceManager::init(ResourceManagerInitInfo& init)
 	m_cacheDir.create(m_alloc, init.m_cacheDir);
 	m_cacheDir.create(m_alloc, init.m_cacheDir);
 
 
 	// Init some constants
 	// Init some constants
-	m_maxTextureSize = init.m_config->getNumberU32("rsrc.maxTextureSize");
-	m_dumpShaderSource = init.m_config->getBool("rsrc.dumpShaderSources");
+	m_maxTextureSize = init.m_config->getNumberU32("rsrc_maxTextureSize");
+	m_dumpShaderSource = init.m_config->getBool("rsrc_dumpShaderSources");
 
 
 	// Init type resource managers
 	// Init type resource managers
 #define ANKI_INSTANTIATE_RESOURCE(rsrc_, ptr_) TypeResourceManager<rsrc_>::init(m_alloc);
 #define ANKI_INSTANTIATE_RESOURCE(rsrc_, ptr_) TypeResourceManager<rsrc_>::init(m_alloc);
@@ -64,7 +70,7 @@ Error ResourceManager::init(ResourceManagerInitInfo& init)
 	m_asyncLoader->init(m_alloc);
 	m_asyncLoader->init(m_alloc);
 
 
 	m_transferGpuAlloc = m_alloc.newInstance<TransferGpuAllocator>();
 	m_transferGpuAlloc = m_alloc.newInstance<TransferGpuAllocator>();
-	ANKI_CHECK(m_transferGpuAlloc->init(init.m_config->getNumberU32("rsrc.transferScratchMemorySize"), m_gr, m_alloc));
+	ANKI_CHECK(m_transferGpuAlloc->init(init.m_config->getNumberU32("rsrc_transferScratchMemorySize"), m_gr, m_alloc));
 
 
 	m_shaderCompiler = m_alloc.newInstance<ShaderCompilerCache>(m_alloc, m_cacheDir.toCString());
 	m_shaderCompiler = m_alloc.newInstance<ShaderCompilerCache>(m_alloc, m_cacheDir.toCString());
 
 

+ 11 - 4
src/anki/scene/SceneGraph.cpp

@@ -12,13 +12,20 @@
 #include <anki/physics/PhysicsWorld.h>
 #include <anki/physics/PhysicsWorld.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/resource/ResourceManager.h>
 #include <anki/renderer/MainRenderer.h>
 #include <anki/renderer/MainRenderer.h>
-#include <anki/misc/ConfigSet.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/ThreadHive.h>
 #include <anki/util/ThreadHive.h>
 #include <anki/util/Tracer.h>
 #include <anki/util/Tracer.h>
 
 
 namespace anki
 namespace anki
 {
 {
 
 
+ANKI_REGISTER_CONFIG_OPTION(
+	scene_earlyZDistance, 10.0, 0.0, MAX_F64, "Objects with distance lower than that will be used in early Z")
+ANKI_REGISTER_CONFIG_OPTION(
+	scene_reflectionProbeEffectiveDistance, 256.0, 1.0, MAX_F64, "How far reflection probes can look")
+ANKI_REGISTER_CONFIG_OPTION(
+	scene_reflectionProbeShadowEffectiveDistance, 32.0, 1.0, MAX_F64, "How far to render shadows for reflection probes")
+
 const U NODE_UPDATE_BATCH = 10;
 const U NODE_UPDATE_BATCH = 10;
 
 
 class SceneGraph::UpdateSceneNodesCtx
 class SceneGraph::UpdateSceneNodesCtx
@@ -74,10 +81,10 @@ Error SceneGraph::init(AllocAlignedCallback allocCb,
 	m_frameAlloc = SceneFrameAllocator<U8>(allocCb, allocCbData, 1 * 1024 * 1024);
 	m_frameAlloc = SceneFrameAllocator<U8>(allocCb, allocCbData, 1 * 1024 * 1024);
 
 
 	// Limits
 	// Limits
-	m_limits.m_earlyZDistance = config.getNumberF32("scene.earlyZDistance");
-	m_limits.m_reflectionProbeEffectiveDistance = config.getNumberF32("scene.reflectionProbeEffectiveDistance");
+	m_limits.m_earlyZDistance = config.getNumberF32("scene_earlyZDistance");
+	m_limits.m_reflectionProbeEffectiveDistance = config.getNumberF32("scene_reflectionProbeEffectiveDistance");
 	m_limits.m_reflectionProbeShadowEffectiveDistance =
 	m_limits.m_reflectionProbeShadowEffectiveDistance =
-		config.getNumberF32("scene.reflectionProbeShadowEffectiveDistance");
+		config.getNumberF32("scene_reflectionProbeShadowEffectiveDistance");
 
 
 	ANKI_CHECK(m_events.init(this));
 	ANKI_CHECK(m_events.init(this));
 
 

+ 5 - 5
tests/framework/Framework.cpp

@@ -223,14 +223,14 @@ void deleteTesterSingleton()
 	}
 	}
 }
 }
 
 
-void initConfig(Config& cfg)
+void initConfig(ConfigSet& cfg)
 {
 {
 	cfg.set("width", 1920);
 	cfg.set("width", 1920);
 	cfg.set("height", 1080);
 	cfg.set("height", 1080);
-	cfg.set("rsrc.dataPaths", ".:..");
+	cfg.set("rsrc_dataPaths", ".:..");
 }
 }
 
 
-NativeWindow* createWindow(const Config& cfg)
+NativeWindow* createWindow(const ConfigSet& cfg)
 {
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 
@@ -245,7 +245,7 @@ NativeWindow* createWindow(const Config& cfg)
 	return win;
 	return win;
 }
 }
 
 
-GrManager* createGrManager(const Config& cfg, NativeWindow* win)
+GrManager* createGrManager(const ConfigSet& cfg, NativeWindow* win)
 {
 {
 	GrManagerInitInfo inf;
 	GrManagerInitInfo inf;
 	inf.m_allocCallback = allocAligned;
 	inf.m_allocCallback = allocAligned;
@@ -259,7 +259,7 @@ GrManager* createGrManager(const Config& cfg, NativeWindow* win)
 }
 }
 
 
 ResourceManager* createResourceManager(
 ResourceManager* createResourceManager(
-	const Config& cfg, GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs)
+	const ConfigSet& cfg, GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs)
 {
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 

+ 4 - 4
tests/framework/Framework.h

@@ -221,13 +221,13 @@ extern void deleteTesterSingleton();
 /// Check error code.
 /// Check error code.
 #define ANKI_TEST_EXPECT_ERR(x_, y_) ANKI_TEST_EXPECT_EQ_IMPL(__FILE__, __LINE__, __func__, x_, y_)
 #define ANKI_TEST_EXPECT_ERR(x_, y_) ANKI_TEST_EXPECT_EQ_IMPL(__FILE__, __LINE__, __func__, x_, y_)
 
 
-void initConfig(Config& cfg);
+void initConfig(ConfigSet& cfg);
 
 
-NativeWindow* createWindow(const Config& cfg);
+NativeWindow* createWindow(const ConfigSet& cfg);
 
 
-GrManager* createGrManager(const Config& cfg, NativeWindow* win);
+GrManager* createGrManager(const ConfigSet& cfg, NativeWindow* win);
 
 
 ResourceManager* createResourceManager(
 ResourceManager* createResourceManager(
-	const Config& cfg, GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs);
+	const ConfigSet& cfg, GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs);
 
 
 } // end namespace anki
 } // end namespace anki

+ 5 - 5
tests/gr/Gr.cpp

@@ -6,7 +6,7 @@
 #include <tests/framework/Framework.h>
 #include <tests/framework/Framework.h>
 #include <anki/Gr.h>
 #include <anki/Gr.h>
 #include <anki/core/NativeWindow.h>
 #include <anki/core/NativeWindow.h>
-#include <anki/core/Config.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/core/StagingGpuMemoryManager.h>
 #include <anki/core/StagingGpuMemoryManager.h>
 #include <anki/resource/TransferGpuAllocator.h>
 #include <anki/resource/TransferGpuAllocator.h>
@@ -286,14 +286,14 @@ static StagingGpuMemoryManager* stagingMem = nullptr;
 
 
 #define COMMON_BEGIN() \
 #define COMMON_BEGIN() \
 	stagingMem = new StagingGpuMemoryManager(); \
 	stagingMem = new StagingGpuMemoryManager(); \
-	Config cfg; \
+	ConfigSet cfg = DefaultConfigSet::get(); \
 	cfg.set("width", WIDTH); \
 	cfg.set("width", WIDTH); \
 	cfg.set("height", HEIGHT); \
 	cfg.set("height", HEIGHT); \
-	cfg.set("window.debugContext", true); \
-	cfg.set("window.vsync", false); \
+	cfg.set("gr_debugContext", true); \
+	cfg.set("gr_vsync", false); \
 	win = createWindow(cfg); \
 	win = createWindow(cfg); \
 	gr = createGrManager(cfg, win); \
 	gr = createGrManager(cfg, win); \
-	ANKI_TEST_EXPECT_NO_ERR(stagingMem->init(gr, Config())); \
+	ANKI_TEST_EXPECT_NO_ERR(stagingMem->init(gr, cfg)); \
 	TransferGpuAllocator* transfAlloc = new TransferGpuAllocator(); \
 	TransferGpuAllocator* transfAlloc = new TransferGpuAllocator(); \
 	ANKI_TEST_EXPECT_NO_ERR(transfAlloc->init(128_MB, gr, gr->getAllocator())); \
 	ANKI_TEST_EXPECT_NO_ERR(transfAlloc->init(128_MB, gr, gr->getAllocator())); \
 	{
 	{

+ 2 - 2
tests/resource/ResourceManager.cpp

@@ -6,7 +6,7 @@
 #include "tests/framework/Framework.h"
 #include "tests/framework/Framework.h"
 #include "anki/resource/DummyResource.h"
 #include "anki/resource/DummyResource.h"
 #include "anki/resource/ResourceManager.h"
 #include "anki/resource/ResourceManager.h"
-#include "anki/core/Config.h"
+#include "anki/core/ConfigSet.h"
 
 
 namespace anki
 namespace anki
 {
 {
@@ -14,7 +14,7 @@ namespace anki
 ANKI_TEST(Resource, ResourceManager)
 ANKI_TEST(Resource, ResourceManager)
 {
 {
 	// Create
 	// Create
-	Config config;
+	ConfigSet config = DefaultConfigSet::get();
 
 
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 

+ 5 - 5
tests/ui/Ui.cpp

@@ -4,7 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <tests/framework/Framework.h>
 #include <tests/framework/Framework.h>
-#include <anki/core/Config.h>
+#include <anki/core/ConfigSet.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/util/HighRezTimer.h>
 #include <anki/Ui.h>
 #include <anki/Ui.h>
 #include <anki/Input.h>
 #include <anki/Input.h>
@@ -54,13 +54,13 @@ public:
 
 
 ANKI_TEST(Ui, Ui)
 ANKI_TEST(Ui, Ui)
 {
 {
-	Config cfg;
+	ConfigSet cfg = DefaultConfigSet::get();
 	initConfig(cfg);
 	initConfig(cfg);
-	cfg.set("window.vsync", 1);
-	cfg.set("window.debugContext", 0);
+	cfg.set("gr_vsync", 1);
+	cfg.set("gr_debugContext", 0);
 	cfg.set("width", 1024);
 	cfg.set("width", 1024);
 	cfg.set("height", 760);
 	cfg.set("height", 760);
-	cfg.set("rsrc.dataPaths", "engine_data");
+	cfg.set("rsrc_dataPaths", "engine_data");
 
 
 	NativeWindow* win = createWindow(cfg);
 	NativeWindow* win = createWindow(cfg);
 	Input* in = new Input();
 	Input* in = new Input();