瀏覽代碼

Merge branch 'dlss' into DLSS_Integration

Panagiotis Christopoulos Charitos 3 年之前
父節點
當前提交
510962c320
共有 75 個文件被更改,包括 930 次插入404 次删除
  1. 15 0
      .editorconfig
  2. 9 9
      AnKi/Core/ConfigSet.cpp
  3. 9 8
      AnKi/Core/CoreTracer.cpp
  4. 4 4
      AnKi/Core/StatsUi.cpp
  5. 4 3
      AnKi/Gr/Vulkan/GrManagerImpl.cpp
  6. 11 10
      AnKi/Gr/Vulkan/ShaderProgramImpl.cpp
  7. 80 80
      AnKi/Importer/GltfImporter.cpp
  8. 1 1
      AnKi/Importer/GltfImporterMaterial.cpp
  9. 8 0
      AnKi/Renderer/Bloom.cpp
  10. 3 0
      AnKi/Renderer/Bloom.h
  11. 1 1
      AnKi/Renderer/ConfigVars.defs.h
  12. 5 0
      AnKi/Renderer/DepthDownscale.cpp
  13. 7 4
      AnKi/Renderer/DownscaleBlur.cpp
  14. 1 1
      AnKi/Renderer/IndirectDiffuseProbes.cpp
  15. 15 0
      AnKi/Renderer/LightShading.cpp
  16. 6 0
      AnKi/Renderer/LightShading.h
  17. 1 1
      AnKi/Renderer/ProbeReflections.cpp
  18. 13 10
      AnKi/Renderer/Scale.cpp
  19. 1 1
      AnKi/Renderer/TemporalAA.cpp
  20. 2 6
      AnKi/Renderer/TemporalAA.h
  21. 278 38
      AnKi/Script/Scene.cpp
  22. 35 0
      AnKi/Script/Scene.xml
  23. 10 10
      AnKi/ShaderCompiler/Glslang.cpp
  24. 1 1
      AnKi/ShaderCompiler/Glslang.h
  25. 1 1
      AnKi/ShaderCompiler/MaliOfflineCompiler.cpp
  26. 11 4
      AnKi/ShaderCompiler/ShaderProgramCompiler.cpp
  27. 2 2
      AnKi/ShaderCompiler/ShaderProgramParser.cpp
  28. 19 7
      AnKi/Shaders/DownscaleBlur.glsl
  29. 10 1
      AnKi/Shaders/LightShadingSkybox.ankiprog
  30. 2 2
      AnKi/Shaders/PackFunctions.glsl
  31. 2 2
      AnKi/Shaders/TemporalAA.glsl
  32. 39 10
      AnKi/Shaders/TonemappingFunctions.glsl
  33. 23 0
      AnKi/Shaders/VisualizeHdrRenderTarget.ankiprog
  34. 7 7
      AnKi/Shaders/VrsSriGenerationCompute.ankiprog
  35. 1 1
      AnKi/Ui/ImGuiConfig.h
  36. 26 7
      AnKi/Util/File.cpp
  37. 5 1
      AnKi/Util/File.h
  38. 2 2
      AnKi/Util/Logger.cpp
  39. 0 1
      AnKi/Util/SparseArray.inl.h
  40. 26 8
      AnKi/Util/String.cpp
  41. 7 7
      AnKi/Util/String.h
  42. 49 0
      AnKi/Util/StringList.cpp
  43. 8 28
      AnKi/Util/StringList.h
  44. 1 0
      AnKi/Util/Thread.h
  45. 51 26
      CMakeLists.txt
  46. 2 3
      Samples/Common/SampleApp.cpp
  47. 33 6
      Samples/PhysicsPlayground/Main.cpp
  48. 17 0
      Tests/Framework/Framework.h
  49. 2 4
      Tests/Gr/Gr.cpp
  50. 2 1
      Tests/Gr/GrCommon.h
  51. 0 4
      Tests/Gr/GrTextureBuffer.cpp
  52. 0 4
      Tests/Renderer/TileAllocator.cpp
  53. 5 3
      Tests/Resource/AsyncLoader.cpp
  54. 0 4
      Tests/Resource/ResourceFilesystem.cpp
  55. 0 4
      Tests/Resource/ResourceManager.cpp
  56. 0 4
      Tests/Scene/Octree.cpp
  57. 12 12
      Tests/Script/LuaBinder.cpp
  58. 5 3
      Tests/Ui/Ui.cpp
  59. 1 3
      Tests/Util/BuddyAllocatorBuilder.cpp
  60. 1 3
      Tests/Util/ClassAllocatorBuilder.cpp
  61. 1 1
      Tests/Util/HashMap.cpp
  62. 1 1
      Tests/Util/Process.cpp
  63. 2 2
      Tests/Util/SparseArray.cpp
  64. 0 4
      Tests/Util/String.cpp
  65. 0 4
      Tests/Util/StringList.cpp
  66. 0 4
      Tests/Util/Thread.cpp
  67. 9 3
      Tests/Util/ThreadHive.cpp
  68. 3 3
      ThirdParty/Bullet/CMakeLists.txt
  69. 1 1
      ThirdParty/Bullet/src/LinearMath/btAlignedObjectArray.h
  70. 12 12
      ThirdParty/FidelityFX/ffx_fsr1.h
  71. 1 0
      ThirdParty/Glslang/SPIRV/GlslangToSpv.cpp
  72. 3 1
      ThirdParty/ImGui/CMakeLists.txt
  73. 1 0
      ThirdParty/Sdl2/src/video/yuv2rgb/yuv_rgb_std_func.h
  74. 2 2
      Tools/GltfImporter/Main.cpp
  75. 2 3
      Tools/Image/ImageViewerMain.cpp

+ 15 - 0
.editorconfig

@@ -0,0 +1,15 @@
+# top-most EditorConfig file
+root = true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_style = tab
+indent_size = 4
+
+[*.py]
+indent_style = space
+
+[*.md]
+trim_trailing_whitespace = false

+ 9 - 9
AnKi/Core/ConfigSet.cpp

@@ -170,24 +170,24 @@ Error ConfigSet::saveToFile(CString filename) const
 	File file;
 	File file;
 	ANKI_CHECK(file.open(filename, FileOpenFlag::WRITE));
 	ANKI_CHECK(file.open(filename, FileOpenFlag::WRITE));
 
 
-	ANKI_CHECK(file.writeText("%s\n<config>\n", XmlDocument::XML_HEADER.cstr()));
+	ANKI_CHECK(file.writeTextf("%s\n<config>\n", XmlDocument::XML_HEADER.cstr()));
 
 
 #define ANKI_NUMERIC_UINT(name) \
 #define ANKI_NUMERIC_UINT(name) \
-	ANKI_CHECK(file.writeText("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
-	ANKI_CHECK( \
-		file.writeText("\t<%s>%llu</%s>\n", m_##name.m_name.cstr(), U64(m_##name.m_value), m_##name.m_name.cstr()));
+	ANKI_CHECK(file.writeTextf("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
+	ANKI_CHECK(file.writeTextf("\t<%s>%" PRIu64 "</%s>\n", m_##name.m_name.cstr(), U64(m_##name.m_value), \
+							   m_##name.m_name.cstr()));
 
 
 #define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_U8(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_U32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_PTR_SIZE(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_F32(name, defaultValue, minValue, maxValue, description) ANKI_NUMERIC_UINT(name)
 #define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) \
 #define ANKI_CONFIG_VAR_BOOL(name, defaultValue, description) \
-	ANKI_CHECK(file.writeText("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
-	ANKI_CHECK(file.writeText("\t<%s>%s</%s>\n", m_##name.m_name.cstr(), (m_##name.m_value) ? "true" : "false", \
-							  m_##name.m_name.cstr()));
+	ANKI_CHECK(file.writeTextf("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
+	ANKI_CHECK(file.writeTextf("\t<%s>%s</%s>\n", m_##name.m_name.cstr(), (m_##name.m_value) ? "true" : "false", \
+							   m_##name.m_name.cstr()));
 #define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
 #define ANKI_CONFIG_VAR_STRING(name, defaultValue, description) \
-	ANKI_CHECK(file.writeText("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
-	ANKI_CHECK(file.writeText("\t<%s>%s</%s>\n", m_##name.m_name.cstr(), m_##name.m_value, m_##name.m_name.cstr()));
+	ANKI_CHECK(file.writeTextf("\t<!-- %s -->\n", m_##name.m_description.cstr())); \
+	ANKI_CHECK(file.writeTextf("\t<%s>%s</%s>\n", m_##name.m_name.cstr(), m_##name.m_value, m_##name.m_name.cstr()));
 #include <AnKi/Core/AllConfigVars.defs.h>
 #include <AnKi/Core/AllConfigVars.defs.h>
 #undef ANKI_NUMERIC_UINT
 #undef ANKI_NUMERIC_UINT
 
 

+ 9 - 8
AnKi/Core/CoreTracer.cpp

@@ -191,9 +191,10 @@ Error CoreTracer::writeEvents(ThreadWorkItem& item)
 		// Do a hack
 		// Do a hack
 		const ThreadId tid = (event.m_name == "GPU_TIME") ? 1 : item.m_tid;
 		const ThreadId tid = (event.m_name == "GPU_TIME") ? 1 : item.m_tid;
 
 
-		ANKI_CHECK(m_traceJsonFile.writeText("{\"name\": \"%s\", \"cat\": \"PERF\", \"ph\": \"X\", "
-											 "\"pid\": 1, \"tid\": %llu, \"ts\": %lld, \"dur\": %lld},\n",
-											 event.m_name.cstr(), tid, startMicroSec, durMicroSec));
+		ANKI_CHECK(m_traceJsonFile.writeTextf("{\"name\": \"%s\", \"cat\": \"PERF\", \"ph\": \"X\", "
+											  "\"pid\": 1, \"tid\": %" PRIu64 ", \"ts\": %" PRIi64 ", \"dur\": %" PRIi64
+											  "},\n",
+											  event.m_name.cstr(), tid, startMicroSec, durMicroSec));
 	}
 	}
 
 
 	// Store counters
 	// Store counters
@@ -340,14 +341,14 @@ Error CoreTracer::writeCountersForReal()
 	ANKI_CHECK(m_countersCsvFile.writeText("Frame"));
 	ANKI_CHECK(m_countersCsvFile.writeText("Frame"));
 	for(U32 i = 0; i < m_counterNames.getSize(); ++i)
 	for(U32 i = 0; i < m_counterNames.getSize(); ++i)
 	{
 	{
-		ANKI_CHECK(m_countersCsvFile.writeText(",%s", m_counterNames[i].cstr()));
+		ANKI_CHECK(m_countersCsvFile.writeTextf(",%s", m_counterNames[i].cstr()));
 	}
 	}
 	ANKI_CHECK(m_countersCsvFile.writeText("\n"));
 	ANKI_CHECK(m_countersCsvFile.writeText("\n"));
 
 
 	// Write each frame
 	// Write each frame
 	for(const PerFrameCounters& frame : m_frameCounters)
 	for(const PerFrameCounters& frame : m_frameCounters)
 	{
 	{
-		ANKI_CHECK(m_countersCsvFile.writeText("%llu", frame.m_frame));
+		ANKI_CHECK(m_countersCsvFile.writeTextf("%" PRIu64, frame.m_frame));
 
 
 		for(U32 j = 0; j < m_counterNames.getSize(); ++j)
 		for(U32 j = 0; j < m_counterNames.getSize(); ++j)
 		{
 		{
@@ -362,7 +363,7 @@ Error CoreTracer::writeCountersForReal()
 				}
 				}
 			}
 			}
 
 
-			ANKI_CHECK(m_countersCsvFile.writeText(",%llu", value));
+			ANKI_CHECK(m_countersCsvFile.writeTextf(",%" PRIu64, value));
 		}
 		}
 
 
 		ANKI_CHECK(m_countersCsvFile.writeText("\n"));
 		ANKI_CHECK(m_countersCsvFile.writeText("\n"));
@@ -377,8 +378,8 @@ Error CoreTracer::writeCountersForReal()
 		{
 		{
 			Array<char, 3> columnName;
 			Array<char, 3> columnName;
 			getSpreadsheetColumnName(i + 1, columnName);
 			getSpreadsheetColumnName(i + 1, columnName);
-			ANKI_CHECK(m_countersCsvFile.writeText(",=%s(%s2:%s%u)", func, &columnName[0], &columnName[0],
-												   m_frameCounters.getSize() + 1));
+			ANKI_CHECK(m_countersCsvFile.writeTextf(",=%s(%s2:%s%zu)", func, &columnName[0], &columnName[0],
+													m_frameCounters.getSize() + 1));
 		}
 		}
 
 
 		ANKI_CHECK(m_countersCsvFile.writeText("\n"));
 		ANKI_CHECK(m_countersCsvFile.writeText("\n"));

+ 4 - 4
AnKi/Core/StatsUi.cpp

@@ -39,19 +39,19 @@ void StatsUi::labelBytes(PtrSize val, CString name) const
 	StringAuto timestamp(getAllocator());
 	StringAuto timestamp(getAllocator());
 	if(gb)
 	if(gb)
 	{
 	{
-		timestamp.sprintf("%s: %u,%04u,%04u,%04u", name.cstr(), gb, mb, kb, b);
+		timestamp.sprintf("%s: %zu,%04zu,%04zu,%04zu", name.cstr(), gb, mb, kb, b);
 	}
 	}
 	else if(mb)
 	else if(mb)
 	{
 	{
-		timestamp.sprintf("%s: %u,%04u,%04u", name.cstr(), mb, kb, b);
+		timestamp.sprintf("%s: %zu,%04zu,%04zu", name.cstr(), mb, kb, b);
 	}
 	}
 	else if(kb)
 	else if(kb)
 	{
 	{
-		timestamp.sprintf("%s: %u,%04u", name.cstr(), kb, b);
+		timestamp.sprintf("%s: %zu,%04zu", name.cstr(), kb, b);
 	}
 	}
 	else
 	else
 	{
 	{
-		timestamp.sprintf("%s: %u", name.cstr(), b);
+		timestamp.sprintf("%s: %zu", name.cstr(), b);
 	}
 	}
 	ImGui::TextUnformatted(timestamp.cstr());
 	ImGui::TextUnformatted(timestamp.cstr());
 }
 }

+ 4 - 3
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -1537,7 +1537,7 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 												   "stage 5 VGPR,stage 5 SGPR\n"));
 												   "stage 5 VGPR,stage 5 SGPR\n"));
 		}
 		}
 
 
-		ANKI_CHECK(m_shaderStatsFile.writeText("%s,0x%" PRIx64 ",", name.cstr(), hash));
+		ANKI_CHECK(m_shaderStatsFile.writeTextf("%s,0x%" PRIx64 ",", name.cstr(), hash));
 
 
 		StringAuto str(getAllocator());
 		StringAuto str(getAllocator());
 
 
@@ -1558,8 +1558,9 @@ Error GrManagerImpl::printPipelineShaderInfoInternal(VkPipeline ppline, CString
 						   .sprintf("Stage %u: VGRPS %02u, SGRPS %02u ", U32(type), stats.resourceUsage.numUsedVgprs,
 						   .sprintf("Stage %u: VGRPS %02u, SGRPS %02u ", U32(type), stats.resourceUsage.numUsedVgprs,
 									stats.resourceUsage.numUsedSgprs));
 									stats.resourceUsage.numUsedSgprs));
 
 
-			ANKI_CHECK(m_shaderStatsFile.writeText((type != ShaderType::LAST) ? "%u,%u," : "%u,%u\n",
-												   stats.resourceUsage.numUsedVgprs, stats.resourceUsage.numUsedSgprs));
+			ANKI_CHECK(m_shaderStatsFile.writeTextf((type != ShaderType::LAST) ? "%u,%u," : "%u,%u\n",
+													stats.resourceUsage.numUsedVgprs,
+													stats.resourceUsage.numUsedSgprs));
 		}
 		}
 
 
 		ANKI_VK_LOGI("Pipeline \"%s\" (0x%016" PRIx64 ") stats: %s", name.cstr(), hash, str.cstr());
 		ANKI_VK_LOGI("Pipeline \"%s\" (0x%016" PRIx64 ") stats: %s", name.cstr(), hash, str.cstr());

+ 11 - 10
AnKi/Gr/Vulkan/ShaderProgramImpl.cpp

@@ -163,11 +163,11 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 	//
 	//
 	for(U32 set = 0; set < descriptorSetCount; ++set)
 	for(U32 set = 0; set < descriptorSetCount; ++set)
 	{
 	{
-		DescriptorSetLayoutInitInfo inf;
-		inf.m_bindings = WeakArray<DescriptorBinding>((counts[set]) ? &bindings[set][0] : nullptr, counts[set]);
+		DescriptorSetLayoutInitInfo dsinf;
+		dsinf.m_bindings = WeakArray<DescriptorBinding>((counts[set]) ? &bindings[set][0] : nullptr, counts[set]);
 
 
 		ANKI_CHECK(
 		ANKI_CHECK(
-			getGrManagerImpl().getDescriptorSetFactory().newDescriptorSetLayout(inf, m_descriptorSetLayouts[set]));
+			getGrManagerImpl().getDescriptorSetFactory().newDescriptorSetLayout(dsinf, m_descriptorSetLayouts[set]));
 
 
 		// Even if the dslayout is empty we will have to list it because we'll have to bind a DS for it.
 		// Even if the dslayout is empty we will have to list it because we'll have to bind a DS for it.
 		m_refl.m_descriptorSetMask.set(set);
 		m_refl.m_descriptorSetMask.set(set);
@@ -206,13 +206,14 @@ Error ShaderProgramImpl::init(const ShaderProgramInitInfo& inf)
 		{
 		{
 			const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*shader);
 			const ShaderImpl& shaderImpl = static_cast<const ShaderImpl&>(*shader);
 
 
-			VkPipelineShaderStageCreateInfo& inf = m_graphics.m_shaderCreateInfos[m_graphics.m_shaderCreateInfoCount++];
-			inf = {};
-			inf.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
-			inf.stage = VkShaderStageFlagBits(convertShaderTypeBit(ShaderTypeBit(1 << shader->getShaderType())));
-			inf.pName = "main";
-			inf.module = shaderImpl.m_handle;
-			inf.pSpecializationInfo = shaderImpl.getSpecConstInfo();
+			VkPipelineShaderStageCreateInfo& createInf =
+				m_graphics.m_shaderCreateInfos[m_graphics.m_shaderCreateInfoCount++];
+			createInf = {};
+			createInf.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
+			createInf.stage = VkShaderStageFlagBits(convertShaderTypeBit(ShaderTypeBit(1 << shader->getShaderType())));
+			createInf.pName = "main";
+			createInf.module = shaderImpl.m_handle;
+			createInf.pSpecializationInfo = shaderImpl.getSpecConstInfo();
 		}
 		}
 	}
 	}
 
 

+ 80 - 80
AnKi/Importer/GltfImporter.cpp

@@ -229,7 +229,7 @@ Error GltfImporter::writeAll()
 	StringAuto sceneFname(m_alloc);
 	StringAuto sceneFname(m_alloc);
 	sceneFname.sprintf("%sScene.lua", m_outDir.cstr());
 	sceneFname.sprintf("%sScene.lua", m_outDir.cstr());
 	ANKI_CHECK(m_sceneFile.open(sceneFname.toCString(), FileOpenFlag::WRITE));
 	ANKI_CHECK(m_sceneFile.open(sceneFname.toCString(), FileOpenFlag::WRITE));
-	ANKI_CHECK(m_sceneFile.writeText("-- Generated by: %s\n", m_comment.cstr()));
+	ANKI_CHECK(m_sceneFile.writeTextf("-- Generated by: %s\n", m_comment.cstr()));
 	ANKI_CHECK(m_sceneFile.writeText("local scene = getSceneGraph()\nlocal events = getEventManager()\n"));
 	ANKI_CHECK(m_sceneFile.writeText("local scene = getSceneGraph()\nlocal events = getEventManager()\n"));
 
 
 	// Nodes
 	// Nodes
@@ -458,12 +458,12 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 				gpuParticles = true;
 				gpuParticles = true;
 			}
 			}
 
 
-			ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:new%sParticleEmitterNode(\"%s\")\n",
-											 (gpuParticles) ? "Gpu" : "", getNodeName(node).cstr()));
+			ANKI_CHECK(m_sceneFile.writeTextf("\nnode = scene:new%sParticleEmitterNode(\"%s\")\n",
+											  (gpuParticles) ? "Gpu" : "", getNodeName(node).cstr()));
 
 
-			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():get%sParticleEmitterComponent()\n",
-											 (gpuParticles) ? "Gpu" : ""));
-			ANKI_CHECK(m_sceneFile.writeText("comp:loadParticleEmitterResource(\"%s\")\n", fname.cstr()));
+			ANKI_CHECK(m_sceneFile.writeTextf("comp = node:getSceneNodeBase():get%sParticleEmitterComponent()\n",
+											  (gpuParticles) ? "Gpu" : ""));
+			ANKI_CHECK(m_sceneFile.writeTextf("comp:loadParticleEmitterResource(\"%s\")\n", fname.cstr()));
 
 
 			Transform localTrf;
 			Transform localTrf;
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(getNodeTransform(node, localTrf));
@@ -474,7 +474,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 		{
 		{
 			// Atmosphere
 			// Atmosphere
 
 
-			ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newSkyboxNode(\"%s\")\n", getNodeName(node).cstr()));
+			ANKI_CHECK(m_sceneFile.writeTextf("\nnode = scene:newSkyboxNode(\"%s\")\n", getNodeName(node).cstr()));
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getSkyboxComponent()\n"));
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getSkyboxComponent()\n"));
 
 
 			if((it = extras.find("skybox_solid_color")) != extras.getEnd())
 			if((it = extras.find("skybox_solid_color")) != extras.getEnd())
@@ -502,40 +502,40 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 					solidColor[count++] = f;
 					solidColor[count++] = f;
 				}
 				}
 
 
-				ANKI_CHECK(m_sceneFile.writeText("comp:setSolidColor(Vec3.new(%f, %f, %f))\n", solidColor.x(),
-												 solidColor.y(), solidColor.z()));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setSolidColor(Vec3.new(%f, %f, %f))\n", solidColor.x(),
+												  solidColor.y(), solidColor.z()));
 			}
 			}
 			else if((it = extras.find("skybox_image")) != extras.getEnd())
 			else if((it = extras.find("skybox_image")) != extras.getEnd())
 			{
 			{
-				ANKI_CHECK(m_sceneFile.writeText("comp:setImage(\"%s\")\n", it->cstr()));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setImage(\"%s\")\n", it->cstr()));
 			}
 			}
 
 
 			if((it = extras.find("fog_min_density")) != extras.getEnd())
 			if((it = extras.find("fog_min_density")) != extras.getEnd())
 			{
 			{
 				F32 val;
 				F32 val;
 				ANKI_CHECK(it->toNumber(val));
 				ANKI_CHECK(it->toNumber(val));
-				ANKI_CHECK(m_sceneFile.writeText("comp:setMinFogDensity(\"%f\")\n", val));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setMinFogDensity(\"%f\")\n", val));
 			}
 			}
 
 
 			if((it = extras.find("fog_max_density")) != extras.getEnd())
 			if((it = extras.find("fog_max_density")) != extras.getEnd())
 			{
 			{
 				F32 val;
 				F32 val;
 				ANKI_CHECK(it->toNumber(val));
 				ANKI_CHECK(it->toNumber(val));
-				ANKI_CHECK(m_sceneFile.writeText("comp:setMaxFogDensity(\"%f\")\n", val));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setMaxFogDensity(\"%f\")\n", val));
 			}
 			}
 
 
 			if((it = extras.find("fog_height_of_min_density")) != extras.getEnd())
 			if((it = extras.find("fog_height_of_min_density")) != extras.getEnd())
 			{
 			{
 				F32 val;
 				F32 val;
 				ANKI_CHECK(it->toNumber(val));
 				ANKI_CHECK(it->toNumber(val));
-				ANKI_CHECK(m_sceneFile.writeText("comp:setHeightOfMinFogDensity(\"%f\")\n", val));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setHeightOfMinFogDensity(\"%f\")\n", val));
 			}
 			}
 
 
 			if((it = extras.find("fog_height_of_max_density")) != extras.getEnd())
 			if((it = extras.find("fog_height_of_max_density")) != extras.getEnd())
 			{
 			{
 				F32 val;
 				F32 val;
 				ANKI_CHECK(it->toNumber(val));
 				ANKI_CHECK(it->toNumber(val));
-				ANKI_CHECK(m_sceneFile.writeText("comp:setHeightOfMaxFogDensity(\"%f\")\n", val));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setHeightOfMaxFogDensity(\"%f\")\n", val));
 			}
 			}
 
 
 			Transform localTrf;
 			Transform localTrf;
@@ -545,11 +545,11 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 		else if((it = extras.find("collision")) != extras.getEnd() && (*it == "true" || *it == "1"))
 		else if((it = extras.find("collision")) != extras.getEnd() && (*it == "true" || *it == "1"))
 		{
 		{
 			ANKI_CHECK(
 			ANKI_CHECK(
-				m_sceneFile.writeText("\nnode = scene:newStaticCollisionNode(\"%s\")\n", getNodeName(node).cstr()));
+				m_sceneFile.writeTextf("\nnode = scene:newStaticCollisionNode(\"%s\")\n", getNodeName(node).cstr()));
 
 
 			ANKI_CHECK(m_sceneFile.writeText("comp = scene:getSceneNodeBase():getBodyComponent()\n"));
 			ANKI_CHECK(m_sceneFile.writeText("comp = scene:getSceneNodeBase():getBodyComponent()\n"));
 			const StringAuto meshFname = computeMeshResourceFilename(*node.mesh);
 			const StringAuto meshFname = computeMeshResourceFilename(*node.mesh);
-			ANKI_CHECK(m_sceneFile.writeText("comp:loadMeshResource(\"%s%s\")\n", m_rpath.cstr(), meshFname.cstr()));
+			ANKI_CHECK(m_sceneFile.writeTextf("comp:loadMeshResource(\"%s%s\")\n", m_rpath.cstr(), meshFname.cstr()));
 
 
 			Transform localTrf;
 			Transform localTrf;
 			ANKI_CHECK(getNodeTransform(node, localTrf));
 			ANKI_CHECK(getNodeTransform(node, localTrf));
@@ -565,11 +565,11 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 			const Vec3 boxSize = scale * 2.0f;
 			const Vec3 boxSize = scale * 2.0f;
 
 
 			ANKI_CHECK(
 			ANKI_CHECK(
-				m_sceneFile.writeText("\nnode = scene:newReflectionProbeNode(\"%s\")\n", getNodeName(node).cstr()));
+				m_sceneFile.writeTextf("\nnode = scene:newReflectionProbeNode(\"%s\")\n", getNodeName(node).cstr()));
 
 
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getReflectionProbeComponent()\n"));
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getReflectionProbeComponent()\n"));
-			ANKI_CHECK(m_sceneFile.writeText("comp:setBoxVolumeSize(Vec3.new(%f, %f, %f))\n", boxSize.x(), boxSize.y(),
-											 boxSize.z()));
+			ANKI_CHECK(m_sceneFile.writeTextf("comp:setBoxVolumeSize(Vec3.new(%f, %f, %f))\n", boxSize.x(), boxSize.y(),
+											  boxSize.z()));
 
 
 			const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
 			const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
 			ANKI_CHECK(writeTransform(parentTrf.combineTransformations(localTrf)));
@@ -595,20 +595,20 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 				ANKI_CHECK(it->toNumber(cellSize));
 				ANKI_CHECK(it->toNumber(cellSize));
 			}
 			}
 
 
-			ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newGlobalIlluminationProbeNode(\"%s\")\n",
-											 getNodeName(node).cstr()));
+			ANKI_CHECK(m_sceneFile.writeTextf("\nnode = scene:newGlobalIlluminationProbeNode(\"%s\")\n",
+											  getNodeName(node).cstr()));
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getGlobalIlluminationProbeComponent()\n"));
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getGlobalIlluminationProbeComponent()\n"));
-			ANKI_CHECK(m_sceneFile.writeText("comp:setBoxVolumeSize(Vec3.new(%f, %f, %f))\n", boxSize.x(), boxSize.y(),
-											 boxSize.z()));
+			ANKI_CHECK(m_sceneFile.writeTextf("comp:setBoxVolumeSize(Vec3.new(%f, %f, %f))\n", boxSize.x(), boxSize.y(),
+											  boxSize.z()));
 
 
 			if(fadeDistance > 0.0f)
 			if(fadeDistance > 0.0f)
 			{
 			{
-				ANKI_CHECK(m_sceneFile.writeText("comp:setFadeDistance(%f)\n", fadeDistance));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setFadeDistance(%f)\n", fadeDistance));
 			}
 			}
 
 
 			if(cellSize > 0.0f)
 			if(cellSize > 0.0f)
 			{
 			{
-				ANKI_CHECK(m_sceneFile.writeText("comp:setCellSize(%f)\n", cellSize));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setCellSize(%f)\n", cellSize));
 			}
 			}
 
 
 			const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
 			const Transform localTrf = Transform(tsl.xyz0(), Mat3x4(Vec3(0.0f), rot), 1.0f);
@@ -652,17 +652,17 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 				ANKI_CHECK(it->toNumber(specularRougnessMetallicFactor));
 				ANKI_CHECK(it->toNumber(specularRougnessMetallicFactor));
 			}
 			}
 
 
-			ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newDecalNode(\"%s\")\n", getNodeName(node).cstr()));
+			ANKI_CHECK(m_sceneFile.writeTextf("\nnode = scene:newDecalNode(\"%s\")\n", getNodeName(node).cstr()));
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getDecalComponent()\n"));
 			ANKI_CHECK(m_sceneFile.writeText("comp = node:getSceneNodeBase():getDecalComponent()\n"));
 			if(diffuseAtlas)
 			if(diffuseAtlas)
 			{
 			{
-				ANKI_CHECK(m_sceneFile.writeText("comp:setDiffuseDecal(\"%s\", \"%s\", %f)\n", diffuseAtlas.cstr(),
-												 diffuseSubtexture.cstr(), diffuseFactor));
+				ANKI_CHECK(m_sceneFile.writeTextf("comp:setDiffuseDecal(\"%s\", \"%s\", %f)\n", diffuseAtlas.cstr(),
+												  diffuseSubtexture.cstr(), diffuseFactor));
 			}
 			}
 
 
 			if(specularRougnessMetallicAtlas)
 			if(specularRougnessMetallicAtlas)
 			{
 			{
-				ANKI_CHECK(m_sceneFile.writeText(
+				ANKI_CHECK(m_sceneFile.writeTextf(
 					"comp:setSpecularRoughnessDecal(\"%s\", \"%s\", %f)\n", specularRougnessMetallicAtlas.cstr(),
 					"comp:setSpecularRoughnessDecal(\"%s\", \"%s\", %f)\n", specularRougnessMetallicAtlas.cstr(),
 					specularRougnessMetallicSubtexture.cstr(), specularRougnessMetallicFactor));
 					specularRougnessMetallicSubtexture.cstr(), specularRougnessMetallicFactor));
 			}
 			}
@@ -771,15 +771,15 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 
 
 			if(selfCollision)
 			if(selfCollision)
 			{
 			{
-				ANKI_CHECK(m_sceneFile.writeText("node2 = scene:newStaticCollisionNode(\"%s_cl\")\n",
-												 getNodeName(node).cstr()));
+				ANKI_CHECK(m_sceneFile.writeTextf("node2 = scene:newStaticCollisionNode(\"%s_cl\")\n",
+												  getNodeName(node).cstr()));
 
 
 				ANKI_CHECK(m_sceneFile.writeText("comp = node2:getSceneNodeBase():getBodyComponent()\n"));
 				ANKI_CHECK(m_sceneFile.writeText("comp = node2:getSceneNodeBase():getBodyComponent()\n"));
 
 
 				const StringAuto meshFname = computeMeshResourceFilename(*node.mesh, maxLod);
 				const StringAuto meshFname = computeMeshResourceFilename(*node.mesh, maxLod);
 
 
 				ANKI_CHECK(
 				ANKI_CHECK(
-					m_sceneFile.writeText("comp:loadMeshResource(\"%s%s\")\n", m_rpath.cstr(), meshFname.cstr()));
+					m_sceneFile.writeTextf("comp:loadMeshResource(\"%s%s\")\n", m_rpath.cstr(), meshFname.cstr()));
 				ANKI_CHECK(m_sceneFile.writeText("comp:setWorldTransform(trf)\n"));
 				ANKI_CHECK(m_sceneFile.writeText("comp:setWorldTransform(trf)\n"));
 			}
 			}
 		}
 		}
@@ -810,18 +810,18 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 Error GltfImporter::writeTransform(const Transform& trf)
 Error GltfImporter::writeTransform(const Transform& trf)
 {
 {
 	ANKI_CHECK(m_sceneFile.writeText("trf = Transform.new()\n"));
 	ANKI_CHECK(m_sceneFile.writeText("trf = Transform.new()\n"));
-	ANKI_CHECK(m_sceneFile.writeText("trf:setOrigin(Vec4.new(%f, %f, %f, 0))\n", trf.getOrigin().x(),
-									 trf.getOrigin().y(), trf.getOrigin().z()));
+	ANKI_CHECK(m_sceneFile.writeTextf("trf:setOrigin(Vec4.new(%f, %f, %f, 0))\n", trf.getOrigin().x(),
+									  trf.getOrigin().y(), trf.getOrigin().z()));
 
 
 	ANKI_CHECK(m_sceneFile.writeText("rot = Mat3x4.new()\n"));
 	ANKI_CHECK(m_sceneFile.writeText("rot = Mat3x4.new()\n"));
 	ANKI_CHECK(m_sceneFile.writeText("rot:setAll("));
 	ANKI_CHECK(m_sceneFile.writeText("rot:setAll("));
 	for(U i = 0; i < 12; i++)
 	for(U i = 0; i < 12; i++)
 	{
 	{
-		ANKI_CHECK(m_sceneFile.writeText((i != 11) ? "%f, " : "%f)\n", trf.getRotation()[i]));
+		ANKI_CHECK(m_sceneFile.writeTextf((i != 11) ? "%f, " : "%f)\n", trf.getRotation()[i]));
 	}
 	}
 	ANKI_CHECK(m_sceneFile.writeText("trf:setRotation(rot)\n"));
 	ANKI_CHECK(m_sceneFile.writeText("trf:setRotation(rot)\n"));
 
 
-	ANKI_CHECK(m_sceneFile.writeText("trf:setScale(%f)\n", trf.getScale()));
+	ANKI_CHECK(m_sceneFile.writeTextf("trf:setScale(%f)\n", trf.getScale()));
 
 
 	ANKI_CHECK(m_sceneFile.writeText("node:getSceneNodeBase():getMoveComponent():setLocalTransform(trf)\n"));
 	ANKI_CHECK(m_sceneFile.writeText("node:getSceneNodeBase():getMoveComponent():setLocalTransform(trf)\n"));
 
 
@@ -852,24 +852,24 @@ Error GltfImporter::writeModel(const cgltf_mesh& mesh)
 		}
 		}
 		else
 		else
 		{
 		{
-			ANKI_CHECK(file.writeText("\t\t<modelPatch subMeshIndex=\"%u\">\n", primIdx));
+			ANKI_CHECK(file.writeTextf("\t\t<modelPatch subMeshIndex=\"%u\">\n", primIdx));
 		}
 		}
 
 
 		{
 		{
 			const StringAuto meshFname = computeMeshResourceFilename(mesh);
 			const StringAuto meshFname = computeMeshResourceFilename(mesh);
-			ANKI_CHECK(file.writeText("\t\t\t<mesh>%s%s</mesh>\n", m_rpath.cstr(), meshFname.cstr()));
+			ANKI_CHECK(file.writeTextf("\t\t\t<mesh>%s%s</mesh>\n", m_rpath.cstr(), meshFname.cstr()));
 		}
 		}
 
 
 		if(m_lodCount > 1 && !skipMeshLod(mesh, 1))
 		if(m_lodCount > 1 && !skipMeshLod(mesh, 1))
 		{
 		{
 			const StringAuto meshFname = computeMeshResourceFilename(mesh, 1);
 			const StringAuto meshFname = computeMeshResourceFilename(mesh, 1);
-			ANKI_CHECK(file.writeText("\t\t\t<mesh1>%s%s</mesh1>\n", m_rpath.cstr(), meshFname.cstr()));
+			ANKI_CHECK(file.writeTextf("\t\t\t<mesh1>%s%s</mesh1>\n", m_rpath.cstr(), meshFname.cstr()));
 		}
 		}
 
 
 		if(m_lodCount > 2 && !skipMeshLod(mesh, 2))
 		if(m_lodCount > 2 && !skipMeshLod(mesh, 2))
 		{
 		{
 			const StringAuto meshFname = computeMeshResourceFilename(mesh, 2);
 			const StringAuto meshFname = computeMeshResourceFilename(mesh, 2);
-			ANKI_CHECK(file.writeText("\t\t\t<mesh2>%s%s</mesh2>\n", m_rpath.cstr(), meshFname.cstr()));
+			ANKI_CHECK(file.writeTextf("\t\t\t<mesh2>%s%s</mesh2>\n", m_rpath.cstr(), meshFname.cstr()));
 		}
 		}
 
 
 		HashMapAuto<CString, StringAuto> materialExtras(m_alloc);
 		HashMapAuto<CString, StringAuto> materialExtras(m_alloc);
@@ -877,12 +877,12 @@ Error GltfImporter::writeModel(const cgltf_mesh& mesh)
 		auto mtlOverride = materialExtras.find("material_override");
 		auto mtlOverride = materialExtras.find("material_override");
 		if(mtlOverride != materialExtras.getEnd())
 		if(mtlOverride != materialExtras.getEnd())
 		{
 		{
-			ANKI_CHECK(file.writeText("\t\t\t<material>%s</material>\n", mtlOverride->cstr()));
+			ANKI_CHECK(file.writeTextf("\t\t\t<material>%s</material>\n", mtlOverride->cstr()));
 		}
 		}
 		else
 		else
 		{
 		{
 			const StringAuto mtlFname = computeMaterialResourceFilename(*mesh.primitives[primIdx].material);
 			const StringAuto mtlFname = computeMaterialResourceFilename(*mesh.primitives[primIdx].material);
-			ANKI_CHECK(file.writeText("\t\t\t<material>%s%s</material>\n", m_rpath.cstr(), mtlFname.cstr()));
+			ANKI_CHECK(file.writeTextf("\t\t\t<material>%s%s</material>\n", m_rpath.cstr(), mtlFname.cstr()));
 		}
 		}
 
 
 		ANKI_CHECK(file.writeText("\t\t</modelPatch>\n"));
 		ANKI_CHECK(file.writeText("\t\t</modelPatch>\n"));
@@ -1150,12 +1150,12 @@ Error GltfImporter::writeAnimation(const cgltf_animation& anim)
 	File file;
 	File file;
 	ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
 	ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
 
 
-	ANKI_CHECK(file.writeText("%s\n<animation>\n", XML_HEADER));
+	ANKI_CHECK(file.writeTextf("%s\n<animation>\n", XML_HEADER));
 	ANKI_CHECK(file.writeText("\t<channels>\n"));
 	ANKI_CHECK(file.writeText("\t<channels>\n"));
 
 
 	for(const GltfAnimChannel& channel : tempChannels)
 	for(const GltfAnimChannel& channel : tempChannels)
 	{
 	{
-		ANKI_CHECK(file.writeText("\t\t<channel name=\"%s\">\n", channel.m_name.cstr()));
+		ANKI_CHECK(file.writeTextf("\t\t<channel name=\"%s\">\n", channel.m_name.cstr()));
 
 
 		// Positions
 		// Positions
 		if(channel.m_positions.getSize())
 		if(channel.m_positions.getSize())
@@ -1163,8 +1163,8 @@ Error GltfImporter::writeAnimation(const cgltf_animation& anim)
 			ANKI_CHECK(file.writeText("\t\t\t<positionKeys>\n"));
 			ANKI_CHECK(file.writeText("\t\t\t<positionKeys>\n"));
 			for(const GltfAnimKey<Vec3>& key : channel.m_positions)
 			for(const GltfAnimKey<Vec3>& key : channel.m_positions)
 			{
 			{
-				ANKI_CHECK(file.writeText("\t\t\t\t<key time=\"%f\">%f %f %f</key>\n", key.m_time, key.m_value.x(),
-										  key.m_value.y(), key.m_value.z()));
+				ANKI_CHECK(file.writeTextf("\t\t\t\t<key time=\"%f\">%f %f %f</key>\n", key.m_time, key.m_value.x(),
+										   key.m_value.y(), key.m_value.z()));
 			}
 			}
 			ANKI_CHECK(file.writeText("\t\t\t</positionKeys>\n"));
 			ANKI_CHECK(file.writeText("\t\t\t</positionKeys>\n"));
 		}
 		}
@@ -1175,8 +1175,8 @@ Error GltfImporter::writeAnimation(const cgltf_animation& anim)
 			ANKI_CHECK(file.writeText("\t\t\t<rotationKeys>\n"));
 			ANKI_CHECK(file.writeText("\t\t\t<rotationKeys>\n"));
 			for(const GltfAnimKey<Quat>& key : channel.m_rotations)
 			for(const GltfAnimKey<Quat>& key : channel.m_rotations)
 			{
 			{
-				ANKI_CHECK(file.writeText("\t\t\t\t<key time=\"%f\">%f %f %f %f</key>\n", key.m_time, key.m_value.x(),
-										  key.m_value.y(), key.m_value.z(), key.m_value.w()));
+				ANKI_CHECK(file.writeTextf("\t\t\t\t<key time=\"%f\">%f %f %f %f</key>\n", key.m_time, key.m_value.x(),
+										   key.m_value.y(), key.m_value.z(), key.m_value.w()));
 			}
 			}
 			ANKI_CHECK(file.writeText("\t\t\t</rotationKeys>\n"));
 			ANKI_CHECK(file.writeText("\t\t\t</rotationKeys>\n"));
 		}
 		}
@@ -1187,7 +1187,7 @@ Error GltfImporter::writeAnimation(const cgltf_animation& anim)
 			ANKI_CHECK(file.writeText("\t\t\t<scaleKeys>\n"));
 			ANKI_CHECK(file.writeText("\t\t\t<scaleKeys>\n"));
 			for(const GltfAnimKey<F32>& key : channel.m_scales)
 			for(const GltfAnimKey<F32>& key : channel.m_scales)
 			{
 			{
-				ANKI_CHECK(file.writeText("\t\t\t\t<key time=\"%f\">%f</key>\n", key.m_time, key.m_value));
+				ANKI_CHECK(file.writeTextf("\t\t\t\t<key time=\"%f\">%f</key>\n", key.m_time, key.m_value));
 			}
 			}
 			ANKI_CHECK(file.writeText("\t\t\t</scaleKeys>\n"));
 			ANKI_CHECK(file.writeText("\t\t\t</scaleKeys>\n"));
 		}
 		}
@@ -1220,8 +1220,8 @@ Error GltfImporter::writeSkeleton(const cgltf_skin& skin)
 	File file;
 	File file;
 	ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
 	ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
 
 
-	ANKI_CHECK(file.writeText("%s\n<skeleton>\n", XML_HEADER));
-	ANKI_CHECK(file.writeText("\t<bones>\n", XML_HEADER));
+	ANKI_CHECK(file.writeTextf("%s\n<skeleton>\n", XML_HEADER));
+	ANKI_CHECK(file.writeTextf("\t<bones>\n"));
 
 
 	for(U32 i = 0; i < skin.joints_count; ++i)
 	for(U32 i = 0; i < skin.joints_count; ++i)
 	{
 	{
@@ -1230,10 +1230,10 @@ Error GltfImporter::writeSkeleton(const cgltf_skin& skin)
 		StringAuto parent(m_alloc);
 		StringAuto parent(m_alloc);
 
 
 		// Name & parent
 		// Name & parent
-		ANKI_CHECK(file.writeText("\t\t<bone name=\"%s\" ", getNodeName(boneNode).cstr()));
+		ANKI_CHECK(file.writeTextf("\t\t<bone name=\"%s\" ", getNodeName(boneNode).cstr()));
 		if(boneNode.parent && getNodeName(*boneNode.parent) != skin.name)
 		if(boneNode.parent && getNodeName(*boneNode.parent) != skin.name)
 		{
 		{
-			ANKI_CHECK(file.writeText("parent=\"%s\" ", getNodeName(*boneNode.parent).cstr()));
+			ANKI_CHECK(file.writeTextf("parent=\"%s\" ", getNodeName(*boneNode.parent).cstr()));
 		}
 		}
 
 
 		// Bone transform
 		// Bone transform
@@ -1242,7 +1242,7 @@ Error GltfImporter::writeSkeleton(const cgltf_skin& skin)
 		btrf.transpose();
 		btrf.transpose();
 		for(U32 j = 0; j < 16; j++)
 		for(U32 j = 0; j < 16; j++)
 		{
 		{
-			ANKI_CHECK(file.writeText("%f ", btrf[j]));
+			ANKI_CHECK(file.writeTextf("%f ", btrf[j]));
 		}
 		}
 		ANKI_CHECK(file.writeText("\" "));
 		ANKI_CHECK(file.writeText("\" "));
 
 
@@ -1253,7 +1253,7 @@ Error GltfImporter::writeSkeleton(const cgltf_skin& skin)
 		ANKI_CHECK(file.writeText("transform=\""));
 		ANKI_CHECK(file.writeText("transform=\""));
 		for(U j = 0; j < 16; j++)
 		for(U j = 0; j < 16; j++)
 		{
 		{
-			ANKI_CHECK(file.writeText("%f ", mat[j]));
+			ANKI_CHECK(file.writeTextf("%f ", mat[j]));
 		}
 		}
 		ANKI_CHECK(file.writeText("\" "));
 		ANKI_CHECK(file.writeText("\" "));
 
 
@@ -1292,14 +1292,14 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 		return Error::USER_DATA;
 		return Error::USER_DATA;
 	}
 	}
 
 
-	ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:new%sLightNode(\"%s\")\n", lightTypeStr.cstr(), nodeName.cstr()));
+	ANKI_CHECK(m_sceneFile.writeTextf("\nnode = scene:new%sLightNode(\"%s\")\n", lightTypeStr.cstr(), nodeName.cstr()));
 	ANKI_CHECK(m_sceneFile.writeText("lcomp = node:getSceneNodeBase():getLightComponent()\n"));
 	ANKI_CHECK(m_sceneFile.writeText("lcomp = node:getSceneNodeBase():getLightComponent()\n"));
 
 
 	Vec3 color(light.color[0], light.color[1], light.color[2]);
 	Vec3 color(light.color[0], light.color[1], light.color[2]);
 	color *= light.intensity;
 	color *= light.intensity;
 	color *= m_lightIntensityScale;
 	color *= m_lightIntensityScale;
 	ANKI_CHECK(
 	ANKI_CHECK(
-		m_sceneFile.writeText("lcomp:setDiffuseColor(Vec4.new(%f, %f, %f, 1))\n", color.x(), color.y(), color.z()));
+		m_sceneFile.writeTextf("lcomp:setDiffuseColor(Vec4.new(%f, %f, %f, 1))\n", color.x(), color.y(), color.z()));
 
 
 	auto shadow = extras.find("shadow");
 	auto shadow = extras.find("shadow");
 	if(shadow != extras.getEnd())
 	if(shadow != extras.getEnd())
@@ -1316,16 +1316,16 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 
 
 	if(light.type == cgltf_light_type_point)
 	if(light.type == cgltf_light_type_point)
 	{
 	{
-		ANKI_CHECK(m_sceneFile.writeText("lcomp:setRadius(%f)\n",
-										 (light.range > 0.0f) ? light.range : computeLightRadius(color)));
+		ANKI_CHECK(m_sceneFile.writeTextf("lcomp:setRadius(%f)\n",
+										  (light.range > 0.0f) ? light.range : computeLightRadius(color)));
 	}
 	}
 	else if(light.type == cgltf_light_type_spot)
 	else if(light.type == cgltf_light_type_spot)
 	{
 	{
-		ANKI_CHECK(m_sceneFile.writeText("lcomp:setDistance(%f)\n",
-										 (light.range > 0.0f) ? light.range : computeLightRadius(color)));
+		ANKI_CHECK(m_sceneFile.writeTextf("lcomp:setDistance(%f)\n",
+										  (light.range > 0.0f) ? light.range : computeLightRadius(color)));
 
 
 		const F32 outer = light.spot_outer_cone_angle * 2.0f;
 		const F32 outer = light.spot_outer_cone_angle * 2.0f;
-		ANKI_CHECK(m_sceneFile.writeText("lcomp:setOuterAngle(%f)\n", outer));
+		ANKI_CHECK(m_sceneFile.writeTextf("lcomp:setOuterAngle(%f)\n", outer));
 
 
 		auto angStr = extras.find("inner_cone_angle_factor");
 		auto angStr = extras.find("inner_cone_angle_factor");
 		F32 inner;
 		F32 inner;
@@ -1345,14 +1345,14 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 			inner = 0.75f * outer;
 			inner = 0.75f * outer;
 		}
 		}
 
 
-		ANKI_CHECK(m_sceneFile.writeText("lcomp:setInnerAngle(%f)\n", inner));
+		ANKI_CHECK(m_sceneFile.writeTextf("lcomp:setInnerAngle(%f)\n", inner));
 	}
 	}
 
 
 	auto lensFlaresFname = extras.find("lens_flare");
 	auto lensFlaresFname = extras.find("lens_flare");
 	if(lensFlaresFname != extras.getEnd())
 	if(lensFlaresFname != extras.getEnd())
 	{
 	{
-		ANKI_CHECK(m_sceneFile.writeText("lfcomp = node:getSceneNodeBase():getLensFlareComponent()\n"));
-		ANKI_CHECK(m_sceneFile.writeText("lfcomp:loadImageResource(\"%s\")\n", lensFlaresFname->cstr()));
+		ANKI_CHECK(m_sceneFile.writeTextf("lfcomp = node:getSceneNodeBase():getLensFlareComponent()\n"));
+		ANKI_CHECK(m_sceneFile.writeTextf("lfcomp:loadImageResource(\"%s\")\n", lensFlaresFname->cstr()));
 
 
 		auto lsSpriteSize = extras.find("lens_flare_first_sprite_size");
 		auto lsSpriteSize = extras.find("lens_flare_first_sprite_size");
 		auto lsColor = extras.find("lens_flare_color");
 		auto lsColor = extras.find("lens_flare_color");
@@ -1363,7 +1363,7 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 			const U32 count = 2;
 			const U32 count = 2;
 			ANKI_CHECK(parseArrayOfNumbers(lsSpriteSize->toCString(), numbers, &count));
 			ANKI_CHECK(parseArrayOfNumbers(lsSpriteSize->toCString(), numbers, &count));
 
 
-			ANKI_CHECK(m_sceneFile.writeText("lfcomp:setFirstFlareSize(Vec2.new(%f, %f))\n", numbers[0], numbers[1]));
+			ANKI_CHECK(m_sceneFile.writeTextf("lfcomp:setFirstFlareSize(Vec2.new(%f, %f))\n", numbers[0], numbers[1]));
 		}
 		}
 
 
 		if(lsColor != extras.getEnd())
 		if(lsColor != extras.getEnd())
@@ -1372,8 +1372,8 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 			const U32 count = 4;
 			const U32 count = 4;
 			ANKI_CHECK(parseArrayOfNumbers(lsColor->toCString(), numbers, &count));
 			ANKI_CHECK(parseArrayOfNumbers(lsColor->toCString(), numbers, &count));
 
 
-			ANKI_CHECK(m_sceneFile.writeText("lfcomp:setColorMultiplier(Vec4.new(%f, %f, %f, %f))\n", numbers[0],
-											 numbers[1], numbers[2], numbers[3]));
+			ANKI_CHECK(m_sceneFile.writeTextf("lfcomp:setColorMultiplier(Vec4.new(%f, %f, %f, %f))\n", numbers[0],
+											  numbers[1], numbers[2], numbers[3]));
 		}
 		}
 	}
 	}
 
 
@@ -1388,8 +1388,8 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 			DynamicArrayAuto<F64> numbers(m_alloc);
 			DynamicArrayAuto<F64> numbers(m_alloc);
 			const U32 count = 4;
 			const U32 count = 4;
 			ANKI_CHECK(parseArrayOfNumbers(lightEventIntensity->toCString(), numbers, &count));
 			ANKI_CHECK(parseArrayOfNumbers(lightEventIntensity->toCString(), numbers, &count));
-			ANKI_CHECK(m_sceneFile.writeText("event:setIntensityMultiplier(Vec4.new(%f, %f, %f, %f))\n", numbers[0],
-											 numbers[1], numbers[2], numbers[3]));
+			ANKI_CHECK(m_sceneFile.writeTextf("event:setIntensityMultiplier(Vec4.new(%f, %f, %f, %f))\n", numbers[0],
+											  numbers[1], numbers[2], numbers[3]));
 		}
 		}
 
 
 		if(lightEventFrequency != extras.getEnd())
 		if(lightEventFrequency != extras.getEnd())
@@ -1397,7 +1397,7 @@ Error GltfImporter::writeLight(const cgltf_node& node, const HashMapAuto<CString
 			DynamicArrayAuto<F64> numbers(m_alloc);
 			DynamicArrayAuto<F64> numbers(m_alloc);
 			const U32 count = 2;
 			const U32 count = 2;
 			ANKI_CHECK(parseArrayOfNumbers(lightEventFrequency->toCString(), numbers, &count));
 			ANKI_CHECK(parseArrayOfNumbers(lightEventFrequency->toCString(), numbers, &count));
-			ANKI_CHECK(m_sceneFile.writeText("event:setFrequency(%f, %f)\n", numbers[0], numbers[1]));
+			ANKI_CHECK(m_sceneFile.writeTextf("event:setFrequency(%f, %f)\n", numbers[0], numbers[1]));
 		}
 		}
 	}
 	}
 
 
@@ -1416,14 +1416,14 @@ Error GltfImporter::writeCamera(const cgltf_node& node,
 	const cgltf_camera_perspective& cam = node.camera->data.perspective;
 	const cgltf_camera_perspective& cam = node.camera->data.perspective;
 	ANKI_IMPORTER_LOGV("Importing camera %s", getNodeName(node).cstr());
 	ANKI_IMPORTER_LOGV("Importing camera %s", getNodeName(node).cstr());
 
 
-	ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newPerspectiveCameraNode(\"%s\")\n", getNodeName(node).cstr()));
+	ANKI_CHECK(m_sceneFile.writeTextf("\nnode = scene:newPerspectiveCameraNode(\"%s\")\n", getNodeName(node).cstr()));
 	ANKI_CHECK(m_sceneFile.writeText("scene:setActiveCameraNode(node:getSceneNodeBase())\n"));
 	ANKI_CHECK(m_sceneFile.writeText("scene:setActiveCameraNode(node:getSceneNodeBase())\n"));
 	ANKI_CHECK(m_sceneFile.writeText("frustumc = node:getSceneNodeBase():getFrustumComponent()\n"));
 	ANKI_CHECK(m_sceneFile.writeText("frustumc = node:getSceneNodeBase():getFrustumComponent()\n"));
 
 
-	ANKI_CHECK(m_sceneFile.writeText("frustumc:setPerspective(%f, %f, getMainRenderer():getAspectRatio() * %f, %f)\n",
-									 cam.znear, cam.zfar, cam.yfov, cam.yfov));
+	ANKI_CHECK(m_sceneFile.writeTextf("frustumc:setPerspective(%f, %f, getMainRenderer():getAspectRatio() * %f, %f)\n",
+									  cam.znear, cam.zfar, cam.yfov, cam.yfov));
 	ANKI_CHECK(m_sceneFile.writeText("frustumc:setShadowCascadesDistancePower(1.5)\n"));
 	ANKI_CHECK(m_sceneFile.writeText("frustumc:setShadowCascadesDistancePower(1.5)\n"));
-	ANKI_CHECK(m_sceneFile.writeText("frustumc:setEffectiveShadowDistance(%f)\n", min(cam.zfar, 100.0f)));
+	ANKI_CHECK(m_sceneFile.writeTextf("frustumc:setEffectiveShadowDistance(%f)\n", min(cam.zfar, 100.0f)));
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }
@@ -1437,14 +1437,14 @@ Error GltfImporter::writeModelNode(const cgltf_node& node, const HashMapAuto<CSt
 
 
 	const StringAuto modelFname = computeModelResourceFilename(*node.mesh);
 	const StringAuto modelFname = computeModelResourceFilename(*node.mesh);
 
 
-	ANKI_CHECK(m_sceneFile.writeText("\nnode = scene:newModelNode(\"%s\")\n", getNodeName(node).cstr()));
-	ANKI_CHECK(m_sceneFile.writeText("node:getSceneNodeBase():getModelComponent():loadModelResource(\"%s%s\")\n",
-									 m_rpath.cstr(), modelFname.cstr()));
+	ANKI_CHECK(m_sceneFile.writeTextf("\nnode = scene:newModelNode(\"%s\")\n", getNodeName(node).cstr()));
+	ANKI_CHECK(m_sceneFile.writeTextf("node:getSceneNodeBase():getModelComponent():loadModelResource(\"%s%s\")\n",
+									  m_rpath.cstr(), modelFname.cstr()));
 
 
 	if(node.skin)
 	if(node.skin)
 	{
 	{
-		ANKI_CHECK(m_sceneFile.writeText("node:getSceneNodeBase():getSkinComponent():loadSkeletonResource(\"%s%s\")\n",
-										 m_rpath.cstr(), computeSkeletonResourceFilename(*node.skin).cstr()));
+		ANKI_CHECK(m_sceneFile.writeTextf("node:getSceneNodeBase():getSkinComponent():loadSkeletonResource(\"%s%s\")\n",
+										  m_rpath.cstr(), computeSkeletonResourceFilename(*node.skin).cstr()));
 	}
 	}
 
 
 	return Error::NONE;
 	return Error::NONE;

+ 1 - 1
AnKi/Importer/GltfImporterMaterial.cpp

@@ -336,7 +336,7 @@ Error GltfImporter::writeMaterial(const cgltf_material& mtl, Bool writeRayTracin
 	// Write file
 	// Write file
 	File file;
 	File file;
 	ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
 	ANKI_CHECK(file.open(fname.toCString(), FileOpenFlag::WRITE));
-	ANKI_CHECK(file.writeText("%s", xml.cstr()));
+	ANKI_CHECK(file.writeText(xml));
 
 
 	return Error::NONE;
 	return Error::NONE;
 }
 }

+ 8 - 0
AnKi/Renderer/Bloom.cpp

@@ -15,6 +15,7 @@ namespace anki {
 Bloom::Bloom(Renderer* r)
 Bloom::Bloom(Renderer* r)
 	: RendererObject(r)
 	: RendererObject(r)
 {
 {
+	registerDebugRenderTarget("Bloom");
 }
 }
 
 
 Bloom::~Bloom()
 Bloom::~Bloom()
@@ -216,4 +217,11 @@ void Bloom::populateRenderGraph(RenderingContext& ctx)
 	}
 	}
 }
 }
 
 
+void Bloom::getDebugRenderTarget([[maybe_unused]] CString rtName, RenderTargetHandle& handle,
+								 [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const
+{
+	ANKI_ASSERT(rtName == "Bloom");
+	handle = m_runCtx.m_upscaleRt;
+}
+
 } // end namespace anki
 } // end namespace anki

+ 3 - 0
AnKi/Renderer/Bloom.h

@@ -83,6 +83,9 @@ private:
 	Error initUpscale();
 	Error initUpscale();
 
 
 	Error initInternal();
 	Error initInternal();
+
+	void getDebugRenderTarget(CString rtName, RenderTargetHandle& handle,
+							  [[maybe_unused]] ShaderProgramPtr& optionalShaderProgram) const override;
 };
 };
 
 
 /// @}
 /// @}

+ 1 - 1
AnKi/Renderer/ConfigVars.defs.h

@@ -30,7 +30,7 @@ ANKI_CONFIG_VAR_BOOL(RDbgEnabled, false, "Enable or not debugging")
 // VRS
 // VRS
 ANKI_CONFIG_VAR_BOOL(RVrs, true, "Enable VRS in multiple passes")
 ANKI_CONFIG_VAR_BOOL(RVrs, true, "Enable VRS in multiple passes")
 ANKI_CONFIG_VAR_BOOL(RGBufferVrs, false, "Enable VRS in GBuffer")
 ANKI_CONFIG_VAR_BOOL(RGBufferVrs, false, "Enable VRS in GBuffer")
-ANKI_CONFIG_VAR_F32(RVrsThreshold, 0.05f, 0.0f, 1.0f, "Threshold under which a lower shading rate will be applied")
+ANKI_CONFIG_VAR_F32(RVrsThreshold, 0.1f, 0.0f, 1.0f, "Threshold under which a lower shading rate will be applied")
 ANKI_CONFIG_VAR_BOOL(RVrsLimitTo2x2, false, "If true the max rate will be 2x2")
 ANKI_CONFIG_VAR_BOOL(RVrsLimitTo2x2, false, "If true the max rate will be 2x2")
 
 
 // SSR
 // SSR

+ 5 - 0
AnKi/Renderer/DepthDownscale.cpp

@@ -12,12 +12,17 @@
 #	pragma GCC diagnostic push
 #	pragma GCC diagnostic push
 #	pragma GCC diagnostic ignored "-Wunused-function"
 #	pragma GCC diagnostic ignored "-Wunused-function"
 #	pragma GCC diagnostic ignored "-Wignored-qualifiers"
 #	pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#elif ANKI_COMPILER_MSVC
+#	pragma warning(push)
+#	pragma warning(disable : 4505)
 #endif
 #endif
 #define A_CPU
 #define A_CPU
 #include <ThirdParty/FidelityFX/ffx_a.h>
 #include <ThirdParty/FidelityFX/ffx_a.h>
 #include <ThirdParty/FidelityFX/ffx_spd.h>
 #include <ThirdParty/FidelityFX/ffx_spd.h>
 #if ANKI_COMPILER_GCC_COMPATIBLE
 #if ANKI_COMPILER_GCC_COMPATIBLE
 #	pragma GCC diagnostic pop
 #	pragma GCC diagnostic pop
+#elif ANKI_COMPILER_MSVC
+#	pragma warning(pop)
 #endif
 #endif
 
 
 namespace anki {
 namespace anki {

+ 7 - 4
AnKi/Renderer/DownscaleBlur.cpp

@@ -178,14 +178,17 @@ void DownscaleBlur::run(U32 passIdx, RenderPassWorkContext& rgraphCtx)
 			0, 1, m_r->getScale().getUsingDLSS() ? m_r->getLightShading().getRt() : m_r->getTemporalAA().getHdrRt());
 			0, 1, m_r->getScale().getUsingDLSS() ? m_r->getLightShading().getRt() : m_r->getTemporalAA().getHdrRt());
 	}
 	}
 
 
+	rgraphCtx.bindUniformBuffer(0, 2, m_r->getTonemapping().getAverageLuminanceBuffer());
+
+	const Bool revertTonemap = passIdx == 0;
+	const UVec4 fbSize(vpWidth, vpHeight, revertTonemap, 0);
+	cmdb->setPushConstants(&fbSize, sizeof(fbSize));
+
 	if(getConfig().getRPreferCompute())
 	if(getConfig().getRPreferCompute())
 	{
 	{
 		TextureSubresourceInfo sampleSubresource;
 		TextureSubresourceInfo sampleSubresource;
 		sampleSubresource.m_firstMipmap = passIdx;
 		sampleSubresource.m_firstMipmap = passIdx;
-		rgraphCtx.bindImage(0, 2, m_runCtx.m_rt, sampleSubresource);
-
-		UVec4 fbSize(vpWidth, vpHeight, 0, 0);
-		cmdb->setPushConstants(&fbSize, sizeof(fbSize));
+		rgraphCtx.bindImage(0, 3, m_runCtx.m_rt, sampleSubresource);
 
 
 		dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], vpWidth, vpHeight);
 		dispatchPPCompute(cmdb, m_workgroupSize[0], m_workgroupSize[1], vpWidth, vpHeight);
 	}
 	}

+ 1 - 1
AnKi/Renderer/IndirectDiffuseProbes.cpp

@@ -130,7 +130,7 @@ Error IndirectDiffuseProbes::initGBuffer()
 			m_tileSize * 6, m_tileSize, GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "GI GBuffer");
 			m_tileSize * 6, m_tileSize, GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "GI GBuffer");
 
 
 		// Create color RT descriptions
 		// Create color RT descriptions
-		for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
+		for(U32 i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 		{
 		{
 			texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
 			texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
 			m_gbuffer.m_colorRtDescrs[i] = texinit;
 			m_gbuffer.m_colorRtDescrs[i] = texinit;

+ 15 - 0
AnKi/Renderer/LightShading.cpp

@@ -24,6 +24,7 @@ namespace anki {
 LightShading::LightShading(Renderer* r)
 LightShading::LightShading(Renderer* r)
 	: RendererObject(r)
 	: RendererObject(r)
 {
 {
+	registerDebugRenderTarget("LightShading");
 }
 }
 
 
 LightShading::~LightShading()
 LightShading::~LightShading()
@@ -97,6 +98,12 @@ Error LightShading::initLightShading()
 
 
 	m_lightShading.m_fbDescr.bake();
 	m_lightShading.m_fbDescr.bake();
 
 
+	// Debug visualization
+	ANKI_CHECK(
+		getResourceManager().loadResource("ShaderBinaries/VisualizeHdrRenderTarget.ankiprogbin", m_visualizeRtProg));
+	m_visualizeRtProg->getOrCreateVariant(variant);
+	m_visualizeRtGrProg = variant->getProgram();
+
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
@@ -402,4 +409,12 @@ void LightShading::populateRenderGraph(RenderingContext& ctx)
 	m_r->getForwardShading().setDependencies(ctx, pass);
 	m_r->getForwardShading().setDependencies(ctx, pass);
 }
 }
 
 
+void LightShading::getDebugRenderTarget([[maybe_unused]] CString rtName, RenderTargetHandle& handle,
+										ShaderProgramPtr& optionalShaderProgram) const
+{
+	ANKI_ASSERT(rtName == "LightShading");
+	handle = m_runCtx.m_rt;
+	optionalShaderProgram = m_visualizeRtGrProg;
+}
+
 } // end namespace anki
 } // end namespace anki

+ 6 - 0
AnKi/Renderer/LightShading.h

@@ -69,12 +69,18 @@ private:
 		RenderTargetHandle m_rt;
 		RenderTargetHandle m_rt;
 	} m_runCtx; ///< Run context.
 	} m_runCtx; ///< Run context.
 
 
+	ShaderProgramResourcePtr m_visualizeRtProg;
+	ShaderProgramPtr m_visualizeRtGrProg;
+
 	Error initLightShading();
 	Error initLightShading();
 	Error initSkybox();
 	Error initSkybox();
 	Error initApplyFog();
 	Error initApplyFog();
 	Error initApplyIndirect();
 	Error initApplyIndirect();
 
 
 	void run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx);
 	void run(const RenderingContext& ctx, RenderPassWorkContext& rgraphCtx);
+
+	void getDebugRenderTarget(CString rtName, RenderTargetHandle& handle,
+							  ShaderProgramPtr& optionalShaderProgram) const override;
 };
 };
 /// @}
 /// @}
 
 

+ 1 - 1
AnKi/Renderer/ProbeReflections.cpp

@@ -74,7 +74,7 @@ Error ProbeReflections::initGBuffer()
 												 GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "CubeRefl GBuffer");
 												 GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[0], "CubeRefl GBuffer");
 
 
 		// Create color RT descriptions
 		// Create color RT descriptions
-		for(U i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
+		for(U32 i = 0; i < GBUFFER_COLOR_ATTACHMENT_COUNT; ++i)
 		{
 		{
 			texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
 			texinit.m_format = GBUFFER_COLOR_ATTACHMENT_PIXEL_FORMATS[i];
 			m_gbuffer.m_colorRtDescrs[i] = texinit;
 			m_gbuffer.m_colorRtDescrs[i] = texinit;

+ 13 - 10
AnKi/Renderer/Scale.cpp

@@ -17,12 +17,17 @@
 #	pragma GCC diagnostic push
 #	pragma GCC diagnostic push
 #	pragma GCC diagnostic ignored "-Wunused-function"
 #	pragma GCC diagnostic ignored "-Wunused-function"
 #	pragma GCC diagnostic ignored "-Wignored-qualifiers"
 #	pragma GCC diagnostic ignored "-Wignored-qualifiers"
+#elif ANKI_COMPILER_MSVC
+#	pragma warning(push)
+#	pragma warning(disable : 4505)
 #endif
 #endif
 #define A_CPU
 #define A_CPU
 #include <ThirdParty/FidelityFX/ffx_a.h>
 #include <ThirdParty/FidelityFX/ffx_a.h>
 #include <ThirdParty/FidelityFX/ffx_fsr1.h>
 #include <ThirdParty/FidelityFX/ffx_fsr1.h>
 #if ANKI_COMPILER_GCC_COMPATIBLE
 #if ANKI_COMPILER_GCC_COMPATIBLE
 #	pragma GCC diagnostic pop
 #	pragma GCC diagnostic pop
+#elif ANKI_COMPILER_MSVC
+#	pragma warning(pop)
 #endif
 #endif
 
 
 namespace anki {
 namespace anki {
@@ -135,8 +140,8 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 {
 {
 	if(!doScaling() && !doSharpening())
 	if(!doScaling() && !doSharpening())
 	{
 	{
-		m_runCtx.m_scaledRt = m_r->getTemporalAA().getTonemappedRt();
-		m_runCtx.m_sharpenedRt = m_r->getTemporalAA().getTonemappedRt();
+		m_runCtx.m_scaledRt = m_r->getTemporalAA().getRt();
+		m_runCtx.m_sharpenedRt = m_r->getTemporalAA().getRt();
 		return;
 		return;
 	}
 	}
 
 
@@ -199,9 +204,8 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 		if(preferCompute)
 		if(preferCompute)
 		{
 		{
 			ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Sharpen");
 			ComputeRenderPassDescription& pass = ctx.m_renderGraphDescr.newComputeRenderPass("Sharpen");
-			pass.newDependency(
-				RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getTonemappedRt() : m_runCtx.m_scaledRt,
-									 TextureUsageBit::SAMPLED_COMPUTE));
+			pass.newDependency(RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt,
+													TextureUsageBit::SAMPLED_COMPUTE));
 			pass.newDependency(RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
 			pass.newDependency(RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::IMAGE_COMPUTE_WRITE));
 
 
 			pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
 			pass.setWork([this](RenderPassWorkContext& rgraphCtx) {
@@ -213,9 +217,8 @@ void Scale::populateRenderGraph(RenderingContext& ctx)
 			GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Sharpen");
 			GraphicsRenderPassDescription& pass = ctx.m_renderGraphDescr.newGraphicsRenderPass("Sharpen");
 			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_sharpenedRt});
 			pass.setFramebufferInfo(m_fbDescr, {m_runCtx.m_sharpenedRt});
 
 
-			pass.newDependency(
-				RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getTonemappedRt() : m_runCtx.m_scaledRt,
-									 TextureUsageBit::SAMPLED_FRAGMENT));
+			pass.newDependency(RenderPassDependency((!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt,
+													TextureUsageBit::SAMPLED_FRAGMENT));
 			pass.newDependency(
 			pass.newDependency(
 				RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 				RenderPassDependency(m_runCtx.m_sharpenedRt, TextureUsageBit::FRAMEBUFFER_ATTACHMENT_WRITE));
 
 
@@ -234,7 +237,7 @@ void Scale::runScaling(RenderPassWorkContext& rgraphCtx)
 	cmdb->bindShaderProgram(m_scaleGrProg);
 	cmdb->bindShaderProgram(m_scaleGrProg);
 
 
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
-	rgraphCtx.bindColorTexture(0, 1, m_r->getTemporalAA().getTonemappedRt());
+	rgraphCtx.bindColorTexture(0, 1, m_r->getTemporalAA().getRt());
 
 
 	if(preferCompute)
 	if(preferCompute)
 	{
 	{
@@ -296,7 +299,7 @@ void Scale::runSharpening(RenderPassWorkContext& rgraphCtx)
 	cmdb->bindShaderProgram(m_sharpenGrProg);
 	cmdb->bindShaderProgram(m_sharpenGrProg);
 
 
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
 	cmdb->bindSampler(0, 0, m_r->getSamplers().m_trilinearClamp);
-	rgraphCtx.bindColorTexture(0, 1, (!doScaling()) ? m_r->getTemporalAA().getTonemappedRt() : m_runCtx.m_scaledRt);
+	rgraphCtx.bindColorTexture(0, 1, (!doScaling()) ? m_r->getTemporalAA().getRt() : m_runCtx.m_scaledRt);
 
 
 	if(preferCompute)
 	if(preferCompute)
 	{
 	{

+ 1 - 1
AnKi/Renderer/TemporalAA.cpp

@@ -44,7 +44,7 @@ Error TemporalAA::initInternal()
 
 
 	{
 	{
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
 		ShaderProgramResourceVariantInitInfo variantInitInfo(m_prog);
-		variantInitInfo.addConstant("VARIANCE_CLIPPING_GAMMA", 2.7f);
+		variantInitInfo.addConstant("VARIANCE_CLIPPING_GAMMA", 2.7f); // Variance clipping paper proposes 1.0
 		variantInitInfo.addConstant("BLEND_FACTOR", 1.0f / 16.0f);
 		variantInitInfo.addConstant("BLEND_FACTOR", 1.0f / 16.0f);
 		variantInitInfo.addMutation("VARIANCE_CLIPPING", 1);
 		variantInitInfo.addMutation("VARIANCE_CLIPPING", 1);
 		variantInitInfo.addMutation("YCBCR", 0);
 		variantInitInfo.addMutation("YCBCR", 0);

+ 2 - 6
AnKi/Renderer/TemporalAA.h

@@ -24,12 +24,8 @@ public:
 
 
 	void populateRenderGraph(RenderingContext& ctx);
 	void populateRenderGraph(RenderingContext& ctx);
 
 
-	RenderTargetHandle getHdrRt() const
-	{
-		return m_runCtx.m_renderRt;
-	}
-
-	RenderTargetHandle getTonemappedRt() const
+	/// Result is tonemaped.
+	RenderTargetHandle getRt() const
 	{
 	{
 		return m_runCtx.m_tonemappedRt;
 		return m_runCtx.m_tonemappedRt;
 	}
 	}

+ 278 - 38
AnKi/Script/Scene.cpp

@@ -62,7 +62,7 @@ using WeakArraySceneNodePtr = WeakArray<SceneNode*>;
 using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArraySceneNodePtr = {
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArraySceneNodePtr = {
-	7517956017451968767, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(),
+	-2049340231983728743, "WeakArraySceneNodePtr", LuaUserData::computeSizeForGarbageCollected<WeakArraySceneNodePtr>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -182,7 +182,7 @@ static inline void wrapWeakArraySceneNodePtr(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArrayBodyComponentPtr = {
 LuaUserDataTypeInfo luaUserDataTypeInfoWeakArrayBodyComponentPtr = {
-	2799694901015155860, "WeakArrayBodyComponentPtr",
+	-77306059902609659, "WeakArrayBodyComponentPtr",
 	LuaUserData::computeSizeForGarbageCollected<WeakArrayBodyComponentPtr>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<WeakArrayBodyComponentPtr>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -301,7 +301,7 @@ static inline void wrapWeakArrayBodyComponentPtr(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoMoveComponent = {2878484245099454523, "MoveComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoMoveComponent = {5705089883580564808, "MoveComponent",
 														LuaUserData::computeSizeForGarbageCollected<MoveComponent>(),
 														LuaUserData::computeSizeForGarbageCollected<MoveComponent>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -699,7 +699,7 @@ static inline void wrapMoveComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoLightComponent = {-103607696861964635, "LightComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoLightComponent = {1983317719094136706, "LightComponent",
 														 LuaUserData::computeSizeForGarbageCollected<LightComponent>(),
 														 LuaUserData::computeSizeForGarbageCollected<LightComponent>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -1263,7 +1263,7 @@ static inline void wrapLightComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoDecalComponent = {-5742387506649679238, "DecalComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoDecalComponent = {1608322450957771206, "DecalComponent",
 														 LuaUserData::computeSizeForGarbageCollected<DecalComponent>(),
 														 LuaUserData::computeSizeForGarbageCollected<DecalComponent>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -1467,7 +1467,7 @@ static inline void wrapDecalComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoLensFlareComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoLensFlareComponent = {
-	-1127553616444053780, "LensFlareComponent", LuaUserData::computeSizeForGarbageCollected<LensFlareComponent>(),
+	8907976916708253981, "LensFlareComponent", LuaUserData::computeSizeForGarbageCollected<LensFlareComponent>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -1639,7 +1639,7 @@ static inline void wrapLensFlareComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoBodyComponent = {4363228454195592721, "BodyComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoBodyComponent = {3200642028059037222, "BodyComponent",
 														LuaUserData::computeSizeForGarbageCollected<BodyComponent>(),
 														LuaUserData::computeSizeForGarbageCollected<BodyComponent>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -1812,7 +1812,7 @@ static inline void wrapBodyComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerComponent = {
-	-5210548852393382715, "TriggerComponent", LuaUserData::computeSizeForGarbageCollected<TriggerComponent>(), nullptr,
+	-6986213597269759334, "TriggerComponent", LuaUserData::computeSizeForGarbageCollected<TriggerComponent>(), nullptr,
 	nullptr};
 	nullptr};
 
 
 template<>
 template<>
@@ -1976,7 +1976,7 @@ static inline void wrapTriggerComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityComponent = {
-	5919969967561537856, "FogDensityComponent", LuaUserData::computeSizeForGarbageCollected<FogDensityComponent>(),
+	-5264030377238763574, "FogDensityComponent", LuaUserData::computeSizeForGarbageCollected<FogDensityComponent>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2180,7 +2180,7 @@ static inline void wrapFogDensityComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoFrustumComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoFrustumComponent = {
-	-1452670313602595932, "FrustumComponent", LuaUserData::computeSizeForGarbageCollected<FrustumComponent>(), nullptr,
+	-6878389274404774307, "FrustumComponent", LuaUserData::computeSizeForGarbageCollected<FrustumComponent>(), nullptr,
 	nullptr};
 	nullptr};
 
 
 template<>
 template<>
@@ -2357,7 +2357,7 @@ static inline void wrapFrustumComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeComponent = {
-	-507736817152660145, "GlobalIlluminationProbeComponent",
+	-915714841666302735, "GlobalIlluminationProbeComponent",
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2604,7 +2604,7 @@ static inline void wrapGlobalIlluminationProbeComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeComponent = {
-	8643136912299553576, "ReflectionProbeComponent",
+	-4107696363672449414, "ReflectionProbeComponent",
 	LuaUserData::computeSizeForGarbageCollected<ReflectionProbeComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<ReflectionProbeComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2720,7 +2720,7 @@ static inline void wrapReflectionProbeComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterComponent = {
-	8851706691625789910, "ParticleEmitterComponent",
+	149711203612747693, "ParticleEmitterComponent",
 	LuaUserData::computeSizeForGarbageCollected<ParticleEmitterComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<ParticleEmitterComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2794,7 +2794,7 @@ static inline void wrapParticleEmitterComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterComponent = {
-	5429206216431556194, "GpuParticleEmitterComponent",
+	-7426951470065804035, "GpuParticleEmitterComponent",
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterComponent>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterComponent>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -2867,7 +2867,7 @@ static inline void wrapGpuParticleEmitterComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoModelComponent = {2802412228105548973, "ModelComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoModelComponent = {6773543014035061075, "ModelComponent",
 														 LuaUserData::computeSizeForGarbageCollected<ModelComponent>(),
 														 LuaUserData::computeSizeForGarbageCollected<ModelComponent>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -2940,7 +2940,7 @@ static inline void wrapModelComponent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoSkinComponent = {491128508440292883, "SkinComponent",
+LuaUserDataTypeInfo luaUserDataTypeInfoSkinComponent = {-3949860037553736583, "SkinComponent",
 														LuaUserData::computeSizeForGarbageCollected<SkinComponent>(),
 														LuaUserData::computeSizeForGarbageCollected<SkinComponent>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -3014,7 +3014,7 @@ static inline void wrapSkinComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxComponent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxComponent = {
-	8030671638762256123, "SkyboxComponent", LuaUserData::computeSizeForGarbageCollected<SkyboxComponent>(), nullptr,
+	-4224390319590151870, "SkyboxComponent", LuaUserData::computeSizeForGarbageCollected<SkyboxComponent>(), nullptr,
 	nullptr};
 	nullptr};
 
 
 template<>
 template<>
@@ -3316,7 +3316,7 @@ static inline void wrapSkyboxComponent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode = {
-	-7018629585669663967, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(), nullptr, nullptr};
+	7340783203210742539, "SceneNode", LuaUserData::computeSizeForGarbageCollected<SceneNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneNode>()
@@ -4261,7 +4261,7 @@ static inline void wrapSceneNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoModelNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoModelNode = {
-	7947036873263424075, "ModelNode", LuaUserData::computeSizeForGarbageCollected<ModelNode>(), nullptr, nullptr};
+	-7084871930487371158, "ModelNode", LuaUserData::computeSizeForGarbageCollected<ModelNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ModelNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ModelNode>()
@@ -4324,7 +4324,7 @@ static inline void wrapModelNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoPerspectiveCameraNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoPerspectiveCameraNode = {
-	-5964752951304333777, "PerspectiveCameraNode", LuaUserData::computeSizeForGarbageCollected<PerspectiveCameraNode>(),
+	6296894285925075603, "PerspectiveCameraNode", LuaUserData::computeSizeForGarbageCollected<PerspectiveCameraNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4387,7 +4387,7 @@ static inline void wrapPerspectiveCameraNode(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoPointLightNode = {-4896561448118002695, "PointLightNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoPointLightNode = {6492387717863479905, "PointLightNode",
 														 LuaUserData::computeSizeForGarbageCollected<PointLightNode>(),
 														 LuaUserData::computeSizeForGarbageCollected<PointLightNode>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -4451,7 +4451,7 @@ static inline void wrapPointLightNode(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoSpotLightNode = {8633679056244334514, "SpotLightNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoSpotLightNode = {-8891132373613260050, "SpotLightNode",
 														LuaUserData::computeSizeForGarbageCollected<SpotLightNode>(),
 														LuaUserData::computeSizeForGarbageCollected<SpotLightNode>(),
 														nullptr, nullptr};
 														nullptr, nullptr};
 
 
@@ -4516,7 +4516,7 @@ static inline void wrapSpotLightNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoDirectionalLightNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoDirectionalLightNode = {
-	4062135726656667841, "DirectionalLightNode", LuaUserData::computeSizeForGarbageCollected<DirectionalLightNode>(),
+	3941685298661161126, "DirectionalLightNode", LuaUserData::computeSizeForGarbageCollected<DirectionalLightNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4580,7 +4580,7 @@ static inline void wrapDirectionalLightNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoStaticCollisionNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoStaticCollisionNode = {
-	-809820996183800061, "StaticCollisionNode", LuaUserData::computeSizeForGarbageCollected<StaticCollisionNode>(),
+	-6253595010562372816, "StaticCollisionNode", LuaUserData::computeSizeForGarbageCollected<StaticCollisionNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4644,7 +4644,7 @@ static inline void wrapStaticCollisionNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoParticleEmitterNode = {
-	6127829460659623106, "ParticleEmitterNode", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterNode>(),
+	-8333277180212471620, "ParticleEmitterNode", LuaUserData::computeSizeForGarbageCollected<ParticleEmitterNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4708,7 +4708,7 @@ static inline void wrapParticleEmitterNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGpuParticleEmitterNode = {
-	-1769837473744509244, "GpuParticleEmitterNode",
+	-5871911407760419933, "GpuParticleEmitterNode",
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterNode>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GpuParticleEmitterNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4772,7 +4772,7 @@ static inline void wrapGpuParticleEmitterNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoReflectionProbeNode = {
-	-7095114923609892328, "ReflectionProbeNode", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeNode>(),
+	3724239195748386698, "ReflectionProbeNode", LuaUserData::computeSizeForGarbageCollected<ReflectionProbeNode>(),
 	nullptr, nullptr};
 	nullptr, nullptr};
 
 
 template<>
 template<>
@@ -4836,7 +4836,7 @@ static inline void wrapReflectionProbeNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoDecalNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoDecalNode = {
-	7387769446515892914, "DecalNode", LuaUserData::computeSizeForGarbageCollected<DecalNode>(), nullptr, nullptr};
+	8580638555371839795, "DecalNode", LuaUserData::computeSizeForGarbageCollected<DecalNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<DecalNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<DecalNode>()
@@ -4899,7 +4899,7 @@ static inline void wrapDecalNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoTriggerNode = {
-	7073092902734740160, "TriggerNode", LuaUserData::computeSizeForGarbageCollected<TriggerNode>(), nullptr, nullptr};
+	4136814088244084712, "TriggerNode", LuaUserData::computeSizeForGarbageCollected<TriggerNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<TriggerNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<TriggerNode>()
@@ -4961,7 +4961,7 @@ static inline void wrapTriggerNode(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityNode = {3003031223599147128, "FogDensityNode",
+LuaUserDataTypeInfo luaUserDataTypeInfoFogDensityNode = {-758649891971596130, "FogDensityNode",
 														 LuaUserData::computeSizeForGarbageCollected<FogDensityNode>(),
 														 LuaUserData::computeSizeForGarbageCollected<FogDensityNode>(),
 														 nullptr, nullptr};
 														 nullptr, nullptr};
 
 
@@ -5026,7 +5026,7 @@ static inline void wrapFogDensityNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoGlobalIlluminationProbeNode = {
-	1877651491732536481, "GlobalIlluminationProbeNode",
+	-4911210073662168021, "GlobalIlluminationProbeNode",
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeNode>(), nullptr, nullptr};
 	LuaUserData::computeSizeForGarbageCollected<GlobalIlluminationProbeNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -5090,7 +5090,7 @@ static inline void wrapGlobalIlluminationProbeNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxNode = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSkyboxNode = {
-	1466480437730230524, "SkyboxNode", LuaUserData::computeSizeForGarbageCollected<SkyboxNode>(), nullptr, nullptr};
+	-1115369417956297324, "SkyboxNode", LuaUserData::computeSizeForGarbageCollected<SkyboxNode>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SkyboxNode>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SkyboxNode>()
@@ -5153,7 +5153,7 @@ static inline void wrapSkyboxNode(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneGraph = {
 LuaUserDataTypeInfo luaUserDataTypeInfoSceneGraph = {
-	8465984591995389462, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(), nullptr, nullptr};
+	-1529114004329230731, "SceneGraph", LuaUserData::computeSizeForGarbageCollected<SceneGraph>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneGraph>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<SceneGraph>()
@@ -5998,7 +5998,7 @@ static inline void wrapSceneGraph(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoEvent = {7664810165129558222, "Event",
+LuaUserDataTypeInfo luaUserDataTypeInfoEvent = {9135137537256635648, "Event",
 												LuaUserData::computeSizeForGarbageCollected<Event>(), nullptr, nullptr};
 												LuaUserData::computeSizeForGarbageCollected<Event>(), nullptr, nullptr};
 
 
 template<>
 template<>
@@ -6064,7 +6064,7 @@ static inline void wrapEvent(lua_State* l)
 }
 }
 
 
 LuaUserDataTypeInfo luaUserDataTypeInfoLightEvent = {
 LuaUserDataTypeInfo luaUserDataTypeInfoLightEvent = {
-	2170875482912253187, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(), nullptr, nullptr};
+	-2703942033941419884, "LightEvent", LuaUserData::computeSizeForGarbageCollected<LightEvent>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<LightEvent>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<LightEvent>()
@@ -6182,9 +6182,100 @@ static inline void wrapLightEvent(lua_State* l)
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
-LuaUserDataTypeInfo luaUserDataTypeInfoEventManager = {-6374301141225450663, "EventManager",
-													   LuaUserData::computeSizeForGarbageCollected<EventManager>(),
-													   nullptr, nullptr};
+LuaUserDataTypeInfo luaUserDataTypeInfoScriptEvent = {
+	2332491948276401877, "ScriptEvent", LuaUserData::computeSizeForGarbageCollected<ScriptEvent>(), nullptr, nullptr};
+
+template<>
+const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<ScriptEvent>()
+{
+	return luaUserDataTypeInfoScriptEvent;
+}
+
+/// Wrap class ScriptEvent.
+static inline void wrapScriptEvent(lua_State* l)
+{
+	LuaBinder::createClass(l, &luaUserDataTypeInfoScriptEvent);
+	lua_settop(l, 0);
+}
+
+LuaUserDataTypeInfo luaUserDataTypeInfoJitterMoveEvent = {
+	4544058840347801874, "JitterMoveEvent", LuaUserData::computeSizeForGarbageCollected<JitterMoveEvent>(), nullptr,
+	nullptr};
+
+template<>
+const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<JitterMoveEvent>()
+{
+	return luaUserDataTypeInfoJitterMoveEvent;
+}
+
+/// Pre-wrap method JitterMoveEvent::setPositionLimits.
+static inline int pwrapJitterMoveEventsetPositionLimits(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 3)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoJitterMoveEvent, ud))
+	{
+		return -1;
+	}
+
+	JitterMoveEvent* self = ud->getData<JitterMoveEvent>();
+
+	// Pop arguments
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoVec4;
+	if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, 2, luaUserDataTypeInfoVec4, ud)))
+	{
+		return -1;
+	}
+
+	Vec4* iarg0 = ud->getData<Vec4>();
+	const Vec4& arg0(*iarg0);
+
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoVec4;
+	if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, 3, luaUserDataTypeInfoVec4, ud)))
+	{
+		return -1;
+	}
+
+	Vec4* iarg1 = ud->getData<Vec4>();
+	const Vec4& arg1(*iarg1);
+
+	// Call the method
+	self->setPositionLimits(arg0, arg1);
+
+	return 0;
+}
+
+/// Wrap method JitterMoveEvent::setPositionLimits.
+static int wrapJitterMoveEventsetPositionLimits(lua_State* l)
+{
+	int res = pwrapJitterMoveEventsetPositionLimits(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Wrap class JitterMoveEvent.
+static inline void wrapJitterMoveEvent(lua_State* l)
+{
+	LuaBinder::createClass(l, &luaUserDataTypeInfoJitterMoveEvent);
+	LuaBinder::pushLuaCFuncMethod(l, "setPositionLimits", wrapJitterMoveEventsetPositionLimits);
+	lua_settop(l, 0);
+}
+
+LuaUserDataTypeInfo luaUserDataTypeInfoEventManager = {
+	-174784136875931487, "EventManager", LuaUserData::computeSizeForGarbageCollected<EventManager>(), nullptr, nullptr};
 
 
 template<>
 template<>
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<EventManager>()
 const LuaUserDataTypeInfo& LuaUserData::getDataTypeInfoFor<EventManager>()
@@ -6266,11 +6357,158 @@ static int wrapEventManagernewLightEvent(lua_State* l)
 	return 0;
 	return 0;
 }
 }
 
 
+/// Pre-wrap method EventManager::newScriptEvent.
+static inline int pwrapEventManagernewScriptEvent(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 4)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoEventManager, ud))
+	{
+		return -1;
+	}
+
+	EventManager* self = ud->getData<EventManager>();
+
+	// Pop arguments
+	F32 arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	F32 arg1;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 3, arg1)))
+	{
+		return -1;
+	}
+
+	const char* arg2;
+	if(ANKI_UNLIKELY(LuaBinder::checkString(l, 4, arg2)))
+	{
+		return -1;
+	}
+
+	// Call the method
+	ScriptEvent* ret = newEvent<ScriptEvent>(self, arg0, arg1, arg2);
+
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "ScriptEvent");
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoScriptEvent;
+	ud->initPointed(&luaUserDataTypeInfoScriptEvent, ret);
+
+	return 1;
+}
+
+/// Wrap method EventManager::newScriptEvent.
+static int wrapEventManagernewScriptEvent(lua_State* l)
+{
+	int res = pwrapEventManagernewScriptEvent(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
+/// Pre-wrap method EventManager::newJitterMoveEvent.
+static inline int pwrapEventManagernewJitterMoveEvent(lua_State* l)
+{
+	[[maybe_unused]] LuaUserData* ud;
+	[[maybe_unused]] void* voidp;
+	[[maybe_unused]] PtrSize size;
+
+	if(ANKI_UNLIKELY(LuaBinder::checkArgsCount(l, 4)))
+	{
+		return -1;
+	}
+
+	// Get "this" as "self"
+	if(LuaBinder::checkUserData(l, 1, luaUserDataTypeInfoEventManager, ud))
+	{
+		return -1;
+	}
+
+	EventManager* self = ud->getData<EventManager>();
+
+	// Pop arguments
+	F32 arg0;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 2, arg0)))
+	{
+		return -1;
+	}
+
+	F32 arg1;
+	if(ANKI_UNLIKELY(LuaBinder::checkNumber(l, 3, arg1)))
+	{
+		return -1;
+	}
+
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoSceneNode;
+	if(ANKI_UNLIKELY(LuaBinder::checkUserData(l, 4, luaUserDataTypeInfoSceneNode, ud)))
+	{
+		return -1;
+	}
+
+	SceneNode* iarg2 = ud->getData<SceneNode>();
+	SceneNode* arg2(iarg2);
+
+	// Call the method
+	JitterMoveEvent* ret = newEvent<JitterMoveEvent>(self, arg0, arg1, arg2);
+
+	// Push return value
+	if(ANKI_UNLIKELY(ret == nullptr))
+	{
+		lua_pushstring(l, "Glue code returned nullptr");
+		return -1;
+	}
+
+	voidp = lua_newuserdata(l, sizeof(LuaUserData));
+	ud = static_cast<LuaUserData*>(voidp);
+	luaL_setmetatable(l, "JitterMoveEvent");
+	extern LuaUserDataTypeInfo luaUserDataTypeInfoJitterMoveEvent;
+	ud->initPointed(&luaUserDataTypeInfoJitterMoveEvent, ret);
+
+	return 1;
+}
+
+/// Wrap method EventManager::newJitterMoveEvent.
+static int wrapEventManagernewJitterMoveEvent(lua_State* l)
+{
+	int res = pwrapEventManagernewJitterMoveEvent(l);
+	if(res >= 0)
+	{
+		return res;
+	}
+
+	lua_error(l);
+	return 0;
+}
+
 /// Wrap class EventManager.
 /// Wrap class EventManager.
 static inline void wrapEventManager(lua_State* l)
 static inline void wrapEventManager(lua_State* l)
 {
 {
 	LuaBinder::createClass(l, &luaUserDataTypeInfoEventManager);
 	LuaBinder::createClass(l, &luaUserDataTypeInfoEventManager);
 	LuaBinder::pushLuaCFuncMethod(l, "newLightEvent", wrapEventManagernewLightEvent);
 	LuaBinder::pushLuaCFuncMethod(l, "newLightEvent", wrapEventManagernewLightEvent);
+	LuaBinder::pushLuaCFuncMethod(l, "newScriptEvent", wrapEventManagernewScriptEvent);
+	LuaBinder::pushLuaCFuncMethod(l, "newJitterMoveEvent", wrapEventManagernewJitterMoveEvent);
 	lua_settop(l, 0);
 	lua_settop(l, 0);
 }
 }
 
 
@@ -6400,6 +6638,8 @@ void wrapModuleScene(lua_State* l)
 	wrapSceneGraph(l);
 	wrapSceneGraph(l);
 	wrapEvent(l);
 	wrapEvent(l);
 	wrapLightEvent(l);
 	wrapLightEvent(l);
+	wrapScriptEvent(l);
+	wrapJitterMoveEvent(l);
 	wrapEventManager(l);
 	wrapEventManager(l);
 	LuaBinder::pushLuaCFunc(l, "getSceneGraph", wrapgetSceneGraph);
 	LuaBinder::pushLuaCFunc(l, "getSceneGraph", wrapgetSceneGraph);
 	LuaBinder::pushLuaCFunc(l, "getEventManager", wrapgetEventManager);
 	LuaBinder::pushLuaCFunc(l, "getEventManager", wrapgetEventManager);

+ 35 - 0
AnKi/Script/Scene.xml

@@ -706,6 +706,7 @@ using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 				</method>
 				</method>
 			</methods>
 			</methods>
 		</class>
 		</class>
+
 		<class name="LightEvent">
 		<class name="LightEvent">
 			<methods>
 			<methods>
 				<method name="setIntensityMultiplier">
 				<method name="setIntensityMultiplier">
@@ -719,6 +720,20 @@ using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 				</method>
 				</method>
 			</methods>
 			</methods>
 		</class>
 		</class>
+
+		<class name="ScriptEvent"/>
+
+		<class name="JitterMoveEvent">
+			<methods>
+				<method name="setPositionLimits">
+					<args>
+						<arg>const Vec4&amp;</arg>
+						<arg>const Vec4&amp;</arg>
+					</args>
+				</method>
+			</methods>
+		</class>
+
 		<class name="EventManager">
 		<class name="EventManager">
 			<methods>
 			<methods>
 				<method name="newLightEvent">
 				<method name="newLightEvent">
@@ -730,6 +745,26 @@ using WeakArrayBodyComponentPtr = WeakArray<BodyComponent*>;
 					</args>
 					</args>
 					<return>LightEvent*</return>
 					<return>LightEvent*</return>
 				</method>
 				</method>
+
+				<method name="newScriptEvent">
+					<overrideCall><![CDATA[ScriptEvent* ret = newEvent<ScriptEvent>(self, arg0, arg1, arg2);]]></overrideCall>
+					<args>
+						<arg>F32</arg>
+						<arg>F32</arg>
+						<arg>CString</arg>
+					</args>
+					<return>ScriptEvent*</return>
+				</method>
+
+				<method name="newJitterMoveEvent">
+					<overrideCall><![CDATA[JitterMoveEvent* ret = newEvent<JitterMoveEvent>(self, arg0, arg1, arg2);]]></overrideCall>
+					<args>
+						<arg>F32</arg>
+						<arg>F32</arg>
+						<arg>SceneNode*</arg>
+					</args>
+					<return>JitterMoveEvent*</return>
+				</method>
 			</methods>
 			</methods>
 		</class>
 		</class>
 	</classes>
 	</classes>

+ 10 - 10
AnKi/ShaderCompiler/Glslang.cpp

@@ -214,7 +214,7 @@ static Error parseErrorLine(CString error, GenericMemoryPoolAllocator<U8> alloc,
 			if(tokens.getSize() < 3 || (tokens.getBegin() + 2)->toNumber(lineNumber) != Error::NONE)
 			if(tokens.getSize() < 3 || (tokens.getBegin() + 2)->toNumber(lineNumber) != Error::NONE)
 			{
 			{
 
 
-				ANKI_SHADER_COMPILER_LOGE("Failed to parse the error message: %s", error.cstr());
+				ANKI_SHADER_COMPILER_LOGE("Failed to parse the GLSlang error message: %s", error.cstr());
 				return Error::FUNCTION_FAILED;
 				return Error::FUNCTION_FAILED;
 			}
 			}
 			else
 			else
@@ -227,11 +227,13 @@ static Error parseErrorLine(CString error, GenericMemoryPoolAllocator<U8> alloc,
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
-static Error logShaderErrorCode(CString error, CString source, GenericMemoryPoolAllocator<U8> alloc)
+static void createErrorLog(CString glslangError, CString source, GenericMemoryPoolAllocator<U8> alloc,
+						   StringAuto& outError)
 {
 {
 	U32 errorLineNumberu = 0;
 	U32 errorLineNumberu = 0;
-	ANKI_CHECK(parseErrorLine(error, alloc, errorLineNumberu));
-	const I32 errorLineNumber = I32(errorLineNumberu);
+	const Error err = parseErrorLine(glslangError, alloc, errorLineNumberu);
+
+	const I32 errorLineNumber = (!err) ? I32(errorLineNumberu) : -1;
 
 
 	constexpr I32 lineCountAroundError = 4;
 	constexpr I32 lineCountAroundError = 4;
 
 
@@ -252,9 +254,7 @@ static Error logShaderErrorCode(CString error, CString source, GenericMemoryPool
 		}
 		}
 	}
 	}
 
 
-	ANKI_SHADER_COMPILER_LOGE("Shader compilation failed:\n%sIn:\n%s\n", error.cstr(), prettySrc.cstr());
-
-	return Error::NONE;
+	outError.sprintf("%sIn:\n%s\n", glslangError.cstr(), prettySrc.cstr());
 }
 }
 
 
 Error preprocessGlsl(CString in, StringAuto& out)
 Error preprocessGlsl(CString in, StringAuto& out)
@@ -278,7 +278,7 @@ Error preprocessGlsl(CString in, StringAuto& out)
 }
 }
 
 
 Error compilerGlslToSpirv(CString src, ShaderType shaderType, GenericMemoryPoolAllocator<U8> tmpAlloc,
 Error compilerGlslToSpirv(CString src, ShaderType shaderType, GenericMemoryPoolAllocator<U8> tmpAlloc,
-						  DynamicArrayAuto<U8>& spirv)
+						  DynamicArrayAuto<U8>& spirv, StringAuto& errorMessage)
 {
 {
 #if ANKI_GLSLANG_DUMP
 #if ANKI_GLSLANG_DUMP
 	// Dump it
 	// Dump it
@@ -307,7 +307,7 @@ Error compilerGlslToSpirv(CString src, ShaderType shaderType, GenericMemoryPoolA
 	shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4);
 	shader.setEnvTarget(glslang::EShTargetSpv, glslang::EShTargetSpv_1_4);
 	if(!shader.parse(&GLSLANG_LIMITS, 100, false, messages))
 	if(!shader.parse(&GLSLANG_LIMITS, 100, false, messages))
 	{
 	{
-		ANKI_CHECK(logShaderErrorCode(shader.getInfoLog(), src, tmpAlloc));
+		createErrorLog(shader.getInfoLog(), src, tmpAlloc, errorMessage);
 		return Error::USER_DATA;
 		return Error::USER_DATA;
 	}
 	}
 
 
@@ -317,7 +317,7 @@ Error compilerGlslToSpirv(CString src, ShaderType shaderType, GenericMemoryPoolA
 
 
 	if(!program.link(messages))
 	if(!program.link(messages))
 	{
 	{
-		ANKI_SHADER_COMPILER_LOGE("glslang failed to link a shader");
+		errorMessage.create("glslang failed to link a shader");
 		return Error::USER_DATA;
 		return Error::USER_DATA;
 	}
 	}
 
 

+ 1 - 1
AnKi/ShaderCompiler/Glslang.h

@@ -19,7 +19,7 @@ Error preprocessGlsl(CString in, StringAuto& out);
 
 
 /// Compile glsl to SPIR-V.
 /// Compile glsl to SPIR-V.
 Error compilerGlslToSpirv(CString src, ShaderType shaderType, GenericMemoryPoolAllocator<U8> tmpAlloc,
 Error compilerGlslToSpirv(CString src, ShaderType shaderType, GenericMemoryPoolAllocator<U8> tmpAlloc,
-						  DynamicArrayAuto<U8>& spirv);
+						  DynamicArrayAuto<U8>& spirv, StringAuto& errorMessage);
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 1 - 1
AnKi/ShaderCompiler/MaliOfflineCompiler.cpp

@@ -312,7 +312,7 @@ Error runMaliOfflineCompiler(CString maliocExecutable, ConstWeakArray<U8> spirv,
 	StringAuto tmpDir(tmpAlloc);
 	StringAuto tmpDir(tmpAlloc);
 	ANKI_CHECK(getTempDirectory(tmpDir));
 	ANKI_CHECK(getTempDirectory(tmpDir));
 	StringAuto spirvFilename(tmpAlloc);
 	StringAuto spirvFilename(tmpAlloc);
-	spirvFilename.sprintf("%s/AnKiMaliocTmpSpirv_%llu.spv", tmpDir.cstr(), getRandom());
+	spirvFilename.sprintf("%s/AnKiMaliocTmpSpirv_%" PRIu64 ".spv", tmpDir.cstr(), getRandom());
 
 
 	File spirvFile;
 	File spirvFile;
 	ANKI_CHECK(spirvFile.open(spirvFilename, FileOpenFlag::WRITE | FileOpenFlag::BINARY));
 	ANKI_CHECK(spirvFile.open(spirvFilename, FileOpenFlag::WRITE | FileOpenFlag::BINARY));

+ 11 - 4
AnKi/ShaderCompiler/ShaderProgramCompiler.cpp

@@ -168,7 +168,7 @@ static Bool spinDials(DynamicArrayAuto<U32>& dials, ConstWeakArray<ShaderProgram
 
 
 static Error compileSpirv(ConstWeakArray<MutatorValue> mutation, const ShaderProgramParser& parser,
 static Error compileSpirv(ConstWeakArray<MutatorValue> mutation, const ShaderProgramParser& parser,
 						  GenericMemoryPoolAllocator<U8>& tmpAlloc,
 						  GenericMemoryPoolAllocator<U8>& tmpAlloc,
-						  Array<DynamicArrayAuto<U8>, U32(ShaderType::COUNT)>& spirv)
+						  Array<DynamicArrayAuto<U8>, U32(ShaderType::COUNT)>& spirv, StringAuto& errorLog)
 {
 {
 	// Generate the source and the rest for the variant
 	// Generate the source and the rest for the variant
 	ShaderProgramParserVariant parserVariant;
 	ShaderProgramParserVariant parserVariant;
@@ -183,7 +183,8 @@ static Error compileSpirv(ConstWeakArray<MutatorValue> mutation, const ShaderPro
 		}
 		}
 
 
 		// Compile
 		// Compile
-		ANKI_CHECK(compilerGlslToSpirv(parserVariant.getSource(shaderType), shaderType, tmpAlloc, spirv[shaderType]));
+		ANKI_CHECK(compilerGlslToSpirv(parserVariant.getSource(shaderType), shaderType, tmpAlloc, spirv[shaderType],
+									   errorLog));
 		ANKI_ASSERT(spirv[shaderType].getSize() > 0);
 		ANKI_ASSERT(spirv[shaderType].getSize() > 0);
 	}
 	}
 
 
@@ -253,7 +254,8 @@ static void compileVariantAsync(ConstWeakArray<MutatorValue> mutation, const Sha
 																	   {tmpAlloc},
 																	   {tmpAlloc},
 																	   {tmpAlloc},
 																	   {tmpAlloc},
 																	   {tmpAlloc}}};
 																	   {tmpAlloc}}};
-		const Error err = compileSpirv(ctx.m_mutation, *ctx.m_parser, tmpAlloc, spirvs);
+		StringAuto errorLog(tmpAlloc);
+		const Error err = compileSpirv(ctx.m_mutation, *ctx.m_parser, tmpAlloc, spirvs, errorLog);
 
 
 		if(!err)
 		if(!err)
 		{
 		{
@@ -304,7 +306,12 @@ static void compileVariantAsync(ConstWeakArray<MutatorValue> mutation, const Sha
 		}
 		}
 		else
 		else
 		{
 		{
-			ctx.m_err->store(err._getCode());
+			// Inform about the error and print only one error message. Ignore other messages
+			const Error prevErr = ctx.m_err->exchange(err._getCode());
+			if(!prevErr)
+			{
+				ANKI_SHADER_COMPILER_LOGE("GLSL compilation failed:\n%s", errorLog.cstr());
+			}
 		}
 		}
 
 
 		// Cleanup
 		// Cleanup

+ 2 - 2
AnKi/ShaderCompiler/ShaderProgramParser.cpp

@@ -713,8 +713,8 @@ Error ShaderProgramParser::parseLine(CString line, CString fname, Bool& foundPra
 			// Add the guard unique for this file
 			// Add the guard unique for this file
 			foundPragmaOnce = true;
 			foundPragmaOnce = true;
 			const U64 hash = fname.computeHash();
 			const U64 hash = fname.computeHash();
-			m_codeLines.pushBackSprintf("#ifndef _ANKI_INCL_GUARD_%llu\n"
-										"#define _ANKI_INCL_GUARD_%llu",
+			m_codeLines.pushBackSprintf("#ifndef _ANKI_INCL_GUARD_%" PRIu64 "\n"
+										"#define _ANKI_INCL_GUARD_%" PRIu64,
 										hash, hash);
 										hash, hash);
 		}
 		}
 		else if(*token == "anki")
 		else if(*token == "anki")

+ 19 - 7
AnKi/Shaders/DownscaleBlur.glsl

@@ -5,24 +5,29 @@
 
 
 #pragma once
 #pragma once
 
 
-#include <AnKi/Shaders/Common.glsl>
+#include <AnKi/Shaders/TonemappingFunctions.glsl>
+#include <AnKi/Shaders/Functions.glsl>
 
 
 layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
 layout(set = 0, binding = 0) uniform sampler u_linearAnyClampSampler;
 layout(set = 0, binding = 1) uniform ANKI_RP texture2D u_tex;
 layout(set = 0, binding = 1) uniform ANKI_RP texture2D u_tex;
 
 
-#if defined(ANKI_COMPUTE_SHADER)
-const UVec2 WORKGROUP_SIZE = UVec2(16, 16);
-layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
+const U32 TONEMAPPING_SET = 0u;
+const U32 TONEMAPPING_BINDING = 2u;
+#include <AnKi/Shaders/TonemappingResources.glsl>
 
 
-// Push constants hold the size of the output image
 layout(push_constant, row_major, std140) uniform b_pc
 layout(push_constant, row_major, std140) uniform b_pc
 {
 {
 	UVec2 u_fbSize;
 	UVec2 u_fbSize;
-	UVec2 u_padding;
+	U32 u_revertTonemapping;
+	U32 u_padding;
 };
 };
 
 
+#if defined(ANKI_COMPUTE_SHADER)
+const UVec2 WORKGROUP_SIZE = UVec2(16, 16);
+layout(local_size_x = WORKGROUP_SIZE.x, local_size_y = WORKGROUP_SIZE.y, local_size_z = 1) in;
+
 Vec2 in_uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(u_fbSize);
 Vec2 in_uv = (Vec2(gl_GlobalInvocationID.xy) + 0.5) / Vec2(u_fbSize);
-layout(set = 0, binding = 2) writeonly uniform ANKI_RP image2D out_img;
+layout(set = 0, binding = 3) writeonly uniform ANKI_RP image2D out_img;
 ANKI_RP Vec3 out_color;
 ANKI_RP Vec3 out_color;
 #else
 #else
 layout(location = 0) in Vec2 in_uv;
 layout(location = 0) in Vec2 in_uv;
@@ -46,6 +51,13 @@ void main()
 	out_color += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), in_uv, 0.0, IVec2(+1, -1)).rgb * weight;
 	out_color += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), in_uv, 0.0, IVec2(+1, -1)).rgb * weight;
 	out_color += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), in_uv, 0.0, IVec2(-1, +1)).rgb * weight;
 	out_color += textureLodOffset(sampler2D(u_tex, u_linearAnyClampSampler), in_uv, 0.0, IVec2(-1, +1)).rgb * weight;
 
 
+	if(u_revertTonemapping != 0u)
+	{
+		out_color = saturate(out_color);
+		out_color = sRgbToLinear(out_color);
+		out_color = invertTonemap(out_color, u_exposureThreshold0);
+	}
+
 #if defined(ANKI_COMPUTE_SHADER)
 #if defined(ANKI_COMPUTE_SHADER)
 	imageStore(out_img, IVec2(gl_GlobalInvocationID.xy), Vec4(out_color, 0.0));
 	imageStore(out_img, IVec2(gl_GlobalInvocationID.xy), Vec4(out_color, 0.0));
 #endif
 #endif

+ 10 - 1
AnKi/Shaders/LightShadingSkybox.ankiprog

@@ -57,7 +57,16 @@ void main()
 	const Vec3 eyeToFrag = normalize(worldPos - u_cameraPos);
 	const Vec3 eyeToFrag = normalize(worldPos - u_cameraPos);
 
 
 	const Vec2 uv = equirectangularMapping(eyeToFrag);
 	const Vec2 uv = equirectangularMapping(eyeToFrag);
-	out_color = texture(u_envMapTex, u_trilinearAnySampler, uv).rgb;
+
+	// When uv is close to the edge of the texture the other quads might be in the oposit coordinate. Then the
+	// derivatives will be huge causing the texture to use the highest mip and thus create a visible seam. To fix this
+	// find when the derivatives are large and do some manual work to fix it
+	const Vec2 dx = abs(dFdx(uv));
+	const F32 maxD = max(dx.x, dx.y);
+
+	const F32 bias = (maxD > 0.9) ? -100.0f : 0.0f;
+
+	out_color = texture(u_envMapTex, u_trilinearAnySampler, uv, bias).rgb;
 #endif
 #endif
 }
 }
 
 

+ 2 - 2
AnKi/Shaders/PackFunctions.glsl

@@ -151,7 +151,7 @@ void packGBuffer(GbufferInfo g, out Vec4 rt0, out Vec4 rt1, out Vec4 rt2, out Ve
 {
 {
 	const F32 packedSubsurfaceMetallic = packUnorm2ToUnorm1(Vec2(g.m_subsurface, g.m_metallic));
 	const F32 packedSubsurfaceMetallic = packUnorm2ToUnorm1(Vec2(g.m_subsurface, g.m_metallic));
 
 
-	const Vec3 tonemappedEmission = invertibleTonemap(g.m_emission);
+	const Vec3 tonemappedEmission = invertReinhardTonemap(g.m_emission);
 
 
 	rt0 = Vec4(g.m_diffuse, packedSubsurfaceMetallic);
 	rt0 = Vec4(g.m_diffuse, packedSubsurfaceMetallic);
 	rt1 = Vec4(g.m_roughness, g.m_f0.x, tonemappedEmission.rb);
 	rt1 = Vec4(g.m_roughness, g.m_f0.x, tonemappedEmission.rb);
@@ -189,7 +189,7 @@ void unpackGBufferNoVelocity(ANKI_RP Vec4 rt0, ANKI_RP Vec4 rt1, ANKI_RP Vec4 rt
 
 
 	g.m_roughness = unpackRoughnessFromGBuffer(rt1);
 	g.m_roughness = unpackRoughnessFromGBuffer(rt1);
 	g.m_f0 = Vec3(rt1.y);
 	g.m_f0 = Vec3(rt1.y);
-	g.m_emission = invertInvertibleTonemap(Vec3(rt1.z, rt2.x, rt1.w));
+	g.m_emission = invertReinhardTonemap(Vec3(rt1.z, rt2.x, rt1.w));
 
 
 	g.m_normal = signedOctDecode(rt2.yzw);
 	g.m_normal = signedOctDecode(rt2.yzw);
 
 

+ 2 - 2
AnKi/Shaders/TemporalAA.glsl

@@ -95,8 +95,8 @@ void main()
 	const F32 lum1 = historyCol.r;
 	const F32 lum1 = historyCol.r;
 	const F32 maxLum = boxMax.r;
 	const F32 maxLum = boxMax.r;
 #else
 #else
-	const F32 lum0 = computeLuminance(invertibleTonemap(crntCol));
-	const F32 lum1 = computeLuminance(invertibleTonemap(historyCol));
+	const F32 lum0 = computeLuminance(reinhardTonemap(crntCol));
+	const F32 lum1 = computeLuminance(reinhardTonemap(historyCol));
 	const F32 maxLum = 1.0;
 	const F32 maxLum = 1.0;
 #endif
 #endif
 
 

+ 39 - 10
AnKi/Shaders/TonemappingFunctions.glsl

@@ -65,15 +65,28 @@ ANKI_RP Vec3 tonemapACESFilm(ANKI_RP Vec3 x)
 	return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
 	return saturate((x * (a * x + b)) / (x * (c * x + d) + e));
 }
 }
 
 
+ANKI_RP Vec3 invertTonemapACESFilm(ANKI_RP Vec3 x)
+{
+	const ANKI_RP F32 a = 2.51;
+	const ANKI_RP F32 b = 0.03;
+	const ANKI_RP F32 c = 2.43;
+	const ANKI_RP F32 d = 0.59;
+	const ANKI_RP F32 e = 0.14;
+
+	return (-0.59 * x + 0.03 - sqrt(-1.0127 * x * x + 1.3702 * x + 0.0009)) / (2.0 * (2.43 * x - 2.51));
+}
+
 ANKI_RP Vec3 tonemap(ANKI_RP Vec3 color, ANKI_RP F32 exposure)
 ANKI_RP Vec3 tonemap(ANKI_RP Vec3 color, ANKI_RP F32 exposure)
 {
 {
 	color *= exposure;
 	color *= exposure;
-#if 0
-	const ANKI_RP F32 saturation = 1.0;
-	return tonemapReinhard(color, saturation);
-#else
 	return tonemapACESFilm(color);
 	return tonemapACESFilm(color);
-#endif
+}
+
+ANKI_RP Vec3 invertTonemap(ANKI_RP Vec3 color, ANKI_RP F32 exposure)
+{
+	color = invertTonemapACESFilm(color);
+	color /= max(EPSILON, exposure);
+	return color;
 }
 }
 
 
 ANKI_RP Vec3 tonemap(ANKI_RP Vec3 color, ANKI_RP F32 avgLum, ANKI_RP F32 threshold)
 ANKI_RP Vec3 tonemap(ANKI_RP Vec3 color, ANKI_RP F32 avgLum, ANKI_RP F32 threshold)
@@ -83,14 +96,30 @@ ANKI_RP Vec3 tonemap(ANKI_RP Vec3 color, ANKI_RP F32 avgLum, ANKI_RP F32 thresho
 }
 }
 
 
 // https://graphicrants.blogspot.com/2013/12/tone-mapping.html
 // https://graphicrants.blogspot.com/2013/12/tone-mapping.html
-ANKI_RP Vec3 invertibleTonemap(ANKI_RP Vec3 colour)
+Vec3 reinhardTonemap(Vec3 colour)
 {
 {
-	// 1 / (1 + max(rgb))
+	// rgb / (1 + max(rgb))
 	return colour / (1.0 + max(max(colour.r, colour.g), colour.b));
 	return colour / (1.0 + max(max(colour.r, colour.g), colour.b));
 }
 }
 
 
-ANKI_RP Vec3 invertInvertibleTonemap(ANKI_RP Vec3 colour)
+F32 reinhardTonemap(F32 value)
+{
+	return value / (1.0 + value);
+}
+
+F16 reinhardTonemap(F16 value)
+{
+	return value / (1.0hf + value);
+}
+
+Vec3 invertReinhardTonemap(Vec3 colour)
+{
+	// rgb / (1 - max(rgb))
+	return colour / max(1.0 / 32768.0, 1.0 - max(max(colour.r, colour.g), colour.b));
+}
+
+HVec3 invertReinhardTonemap(HVec3 colour)
 {
 {
-	// 1 / (1 - max(rgb))
-	return colour / (1.0 - max(max(colour.r, colour.g), colour.b));
+	// rgb / (1 - max(rgb))
+	return colour / max(F16(1.0 / 32768.0), 1.0hf - max(max(colour.r, colour.g), colour.b));
 }
 }

+ 23 - 0
AnKi/Shaders/VisualizeHdrRenderTarget.ankiprog

@@ -0,0 +1,23 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#pragma anki start vert
+#include <AnKi/Shaders/QuadVert.glsl>
+#pragma anki end
+
+#pragma anki start frag
+#include <AnKi/Shaders/TonemappingFunctions.glsl>
+
+layout(set = 0, binding = 0) uniform texture2D u_inTex;
+layout(set = 0, binding = 1) uniform sampler u_nearestAnyClampSampler;
+
+layout(location = 0) in Vec2 in_uv;
+layout(location = 0) out Vec3 out_color;
+
+void main()
+{
+	out_color = reinhardTonemap(textureLod(u_inTex, u_nearestAnyClampSampler, in_uv, 0.0).rgb);
+}
+#pragma anki end

+ 7 - 7
AnKi/Shaders/VrsSriGenerationCompute.ankiprog

@@ -97,11 +97,11 @@ void main()
 	F32 averageLuma = (l0.x + l0.y + l0.z + l0.w) / 4.0;
 	F32 averageLuma = (l0.x + l0.y + l0.z + l0.w) / 4.0;
 #else
 #else
 	// Get luminance.
 	// Get luminance.
-	//       l2.z
-	// l1.z  l1.w  l2.y
-	// l1.x  l1.y
-	// l0.z  l0.w  l2.x
-	// l0.x  l0.y
+	//             l2.z
+	// l2.y  l1.z  l1.w
+	//       l1.x  l1.y
+	//       l0.z  l0.w  l2.x
+	//       l0.x  l0.y
 	Vec4 l0;
 	Vec4 l0;
 	l0.x = sampleLuma(0, 0);
 	l0.x = sampleLuma(0, 0);
 	l0.y = sampleLuma(1, 0);
 	l0.y = sampleLuma(1, 0);
@@ -116,12 +116,12 @@ void main()
 
 
 	Vec3 l2;
 	Vec3 l2;
 	l2.x = sampleLuma(2, 1);
 	l2.x = sampleLuma(2, 1);
-	l2.y = sampleLuma(2, 3);
+	l2.y = sampleLuma(-1, 3);
 	l2.z = sampleLuma(1, 4);
 	l2.z = sampleLuma(1, 4);
 
 
 	// Calculate derivatives.
 	// Calculate derivatives.
 	Vec4 a = Vec4(l0.y, l2.x, l1.y, l2.y);
 	Vec4 a = Vec4(l0.y, l2.x, l1.y, l2.y);
-	Vec4 b = Vec4(l0.x, l0.w, l1.x, l1.w);
+	Vec4 b = Vec4(l0.x, l0.w, l1.x, l1.z);
 	const Vec4 dx = abs(a - b);
 	const Vec4 dx = abs(a - b);
 
 
 	a = Vec4(l0.z, l0.w, l1.z, l2.z);
 	a = Vec4(l0.z, l0.w, l1.z, l2.z);

+ 1 - 1
AnKi/Ui/ImGuiConfig.h

@@ -6,7 +6,7 @@
 #pragma once
 #pragma once
 
 
 #include <AnKi/Util/Assert.h>
 #include <AnKi/Util/Assert.h>
-#include <AnKi/Math.h>
+#include <AnKi/Math/Vec.h>
 
 
 #define IM_ASSERT(_EXPR) ANKI_ASSERT(_EXPR)
 #define IM_ASSERT(_EXPR) ANKI_ASSERT(_EXPR)
 
 

+ 26 - 7
AnKi/Util/File.cpp

@@ -336,12 +336,11 @@ Error File::write(const void* buff, PtrSize size)
 	else
 	else
 #endif
 #endif
 	{
 	{
-		PtrSize writeSize = 0;
-		writeSize = std::fwrite(buff, 1, size, ANKI_CFILE);
+		const PtrSize writeSize = fwrite(buff, 1, size, ANKI_CFILE);
 
 
 		if(writeSize != size)
 		if(writeSize != size)
 		{
 		{
-			ANKI_UTIL_LOGE("std::fwrite() failed");
+			ANKI_UTIL_LOGE("fwrite() failed");
 			err = Error::FILE_ACCESS;
 			err = Error::FILE_ACCESS;
 		}
 		}
 	}
 	}
@@ -349,7 +348,7 @@ Error File::write(const void* buff, PtrSize size)
 	return err;
 	return err;
 }
 }
 
 
-Error File::writeText(CString format, ...)
+Error File::writeTextf(const Char* format, ...)
 {
 {
 	ANKI_ASSERT(m_file);
 	ANKI_ASSERT(m_file);
 	ANKI_ASSERT(m_flags != FileOpenFlag::NONE);
 	ANKI_ASSERT(m_flags != FileOpenFlag::NONE);
@@ -369,13 +368,34 @@ Error File::writeText(CString format, ...)
 	else
 	else
 #endif
 #endif
 	{
 	{
-		std::vfprintf(ANKI_CFILE, &format[0], args);
+		std::vfprintf(ANKI_CFILE, format, args);
 	}
 	}
 
 
 	va_end(args);
 	va_end(args);
 	return err;
 	return err;
 }
 }
 
 
+Error File::writeText(CString text)
+{
+	ANKI_ASSERT(m_file);
+	ANKI_ASSERT(m_flags != FileOpenFlag::NONE);
+	ANKI_ASSERT((m_flags & FileOpenFlag::WRITE) != FileOpenFlag::NONE);
+	ANKI_ASSERT((m_flags & FileOpenFlag::BINARY) == FileOpenFlag::NONE);
+
+	const PtrSize writeSize = text.getLength() + 1;
+	const PtrSize writenSize = fwrite(text.cstr(), 1, writeSize, ANKI_CFILE);
+
+	if(writeSize != writenSize)
+	{
+		ANKI_UTIL_LOGE("fwrite() failed");
+		return Error::FILE_ACCESS;
+	}
+	else
+	{
+		return Error::NONE;
+	}
+}
+
 Error File::seek(PtrSize offset, FileSeekOrigin origin)
 Error File::seek(PtrSize offset, FileSeekOrigin origin)
 {
 {
 	ANKI_ASSERT(m_file);
 	ANKI_ASSERT(m_file);
@@ -413,14 +433,13 @@ PtrSize File::tell()
 	if(!!(m_flags & FileOpenFlag::SPECIAL))
 	if(!!(m_flags & FileOpenFlag::SPECIAL))
 	{
 	{
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
+		return 0;
 	}
 	}
 	else
 	else
 #endif
 #endif
 	{
 	{
 		return ftell(ANKI_CFILE);
 		return ftell(ANKI_CFILE);
 	}
 	}
-
-	return 0;
 }
 }
 
 
 FileOpenFlag File::getMachineEndianness()
 FileOpenFlag File::getMachineEndianness()

+ 5 - 1
AnKi/Util/File.h

@@ -102,7 +102,11 @@ public:
 	Error write(const void* buff, PtrSize size);
 	Error write(const void* buff, PtrSize size);
 
 
 	/// Write formated text
 	/// Write formated text
-	Error writeText(CString format, ...);
+	ANKI_CHECK_FORMAT(1, 2)
+	Error writeTextf(const Char* format, ...);
+
+	/// Write plain text.
+	Error writeText(CString text);
 
 
 	/// Set the position indicator to a new position.
 	/// Set the position indicator to a new position.
 	/// @param offset Number of bytes to offset from origin
 	/// @param offset Number of bytes to offset from origin

+ 2 - 2
AnKi/Util/Logger.cpp

@@ -284,8 +284,8 @@ void Logger::fileMessageHandler(void* pfile, const LoggerMessageInfo& info)
 {
 {
 	File* file = reinterpret_cast<File*>(pfile);
 	File* file = reinterpret_cast<File*>(pfile);
 
 
-	Error err = file->writeText("[%s] %s (%s:%d %s)\n", MSG_TEXT[U(info.m_type)], info.m_msg, info.m_file, info.m_line,
-								info.m_func);
+	Error err = file->writeTextf("[%s] %s (%s:%d %s)\n", MSG_TEXT[U(info.m_type)], info.m_msg, info.m_file, info.m_line,
+								 info.m_func);
 
 
 	if(!err)
 	if(!err)
 	{
 	{

+ 0 - 1
AnKi/Util/SparseArray.inl.h

@@ -111,7 +111,6 @@ start:
 	grow(alloc);
 	grow(alloc);
 	goto start;
 	goto start;
 
 
-	ANKI_ASSERT(0);
 	return 0;
 	return 0;
 }
 }
 
 

+ 26 - 8
AnKi/Util/String.cpp

@@ -241,14 +241,14 @@ void String::appendInternal(Allocator& alloc, const Char* str, PtrSize strLen)
 	m_data = std::move(newData);
 	m_data = std::move(newData);
 }
 }
 
 
-String& String::sprintf(Allocator alloc, CString fmt, ...)
+void String::sprintf(Allocator& alloc, const Char* fmt, va_list& args)
 {
 {
 	Array<Char, 512> buffer;
 	Array<Char, 512> buffer;
-	va_list args;
 
 
-	va_start(args, fmt);
-	[[maybe_unused]] I len = std::vsnprintf(&buffer[0], sizeof(buffer), &fmt[0], args);
-	va_end(args);
+	va_list args2;
+	va_copy(args2, args); // vsnprintf will alter "args". Copy it case we need to call vsnprintf in the else bellow
+
+	I len = std::vsnprintf(&buffer[0], sizeof(buffer), fmt, args);
 
 
 	if(len < 0)
 	if(len < 0)
 	{
 	{
@@ -259,9 +259,7 @@ String& String::sprintf(Allocator alloc, CString fmt, ...)
 		I size = len + 1;
 		I size = len + 1;
 		m_data.create(alloc, size);
 		m_data.create(alloc, size);
 
 
-		va_start(args, fmt);
-		len = std::vsnprintf(&m_data[0], size, &fmt[0], args);
-		va_end(args);
+		len = std::vsnprintf(&m_data[0], size, fmt, args2);
 
 
 		ANKI_ASSERT((len + 1) == size);
 		ANKI_ASSERT((len + 1) == size);
 	}
 	}
@@ -271,6 +269,17 @@ String& String::sprintf(Allocator alloc, CString fmt, ...)
 		create(alloc, CString(&buffer[0]));
 		create(alloc, CString(&buffer[0]));
 	}
 	}
 
 
+	va_end(args2);
+}
+
+String& String::sprintf(Allocator alloc, const Char* fmt, ...)
+{
+	ANKI_ASSERT(fmt);
+	va_list args;
+	va_start(args, fmt);
+	sprintf(alloc, fmt, args);
+	va_end(args);
+
 	return *this;
 	return *this;
 }
 }
 
 
@@ -308,4 +317,13 @@ String& String::replaceAll(Allocator alloc, CString from, CString to)
 	return *this;
 	return *this;
 }
 }
 
 
+StringAuto& StringAuto::sprintf(const Char* fmt, ...)
+{
+	va_list args;
+	va_start(args, fmt);
+	Base::sprintf(m_alloc, fmt, args);
+	va_end(args);
+	return *this;
+}
+
 } // end namespace anki
 } // end namespace anki

+ 7 - 7
AnKi/Util/String.h

@@ -451,7 +451,8 @@ public:
 	}
 	}
 
 
 	/// Create formated string.
 	/// Create formated string.
-	String& sprintf(Allocator alloc, CString fmt, ...);
+	ANKI_CHECK_FORMAT(2, 3)
+	String& sprintf(Allocator alloc, const Char* fmt, ...);
 
 
 	/// Destroy the string.
 	/// Destroy the string.
 	void destroy(Allocator alloc)
 	void destroy(Allocator alloc)
@@ -647,6 +648,9 @@ public:
 		});
 		});
 	}
 	}
 
 
+	/// Internal don't use it.
+	ANKI_INTERNAL void sprintf(Allocator& alloc, const Char* fmt, va_list& args);
+
 protected:
 protected:
 	DynamicArray<Char, PtrSize> m_data;
 	DynamicArray<Char, PtrSize> m_data;
 
 
@@ -810,12 +814,8 @@ public:
 	}
 	}
 
 
 	/// Create formated string.
 	/// Create formated string.
-	template<typename... TArgs>
-	StringAuto& sprintf(CString fmt, TArgs... args)
-	{
-		Base::sprintf(m_alloc, fmt, args...);
-		return *this;
-	}
+	ANKI_CHECK_FORMAT(1, 2)
+	StringAuto& sprintf(const Char* fmt, ...);
 
 
 	/// Convert a number to a string.
 	/// Convert a number to a string.
 	template<typename TNumber>
 	template<typename TNumber>

+ 49 - 0
AnKi/Util/StringList.cpp

@@ -4,6 +4,7 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <AnKi/Util/StringList.h>
 #include <AnKi/Util/StringList.h>
+#include <cstdarg>
 
 
 namespace anki {
 namespace anki {
 
 
@@ -146,4 +147,52 @@ I StringList::getIndexOf(const CString& value) const
 	return (pos == Base::getSize()) ? -1 : pos;
 	return (pos == Base::getSize()) ? -1 : pos;
 }
 }
 
 
+void StringList::pushBackSprintf(Allocator alloc, const Char* fmt, ...)
+{
+	String str;
+	va_list args;
+	va_start(args, fmt);
+	str.sprintf(alloc, fmt, args);
+	va_end(args);
+
+	Base::emplaceBack(alloc);
+	Base::getBack() = std::move(str);
+}
+
+void StringList::pushFrontSprintf(Allocator alloc, const Char* fmt, ...)
+{
+	String str;
+	va_list args;
+	va_start(args, fmt);
+	str.sprintf(alloc, fmt, args);
+	va_end(args);
+
+	Base::emplaceFront(alloc);
+	Base::getFront() = std::move(str);
+}
+
+void StringListAuto::pushBackSprintf(const Char* fmt, ...)
+{
+	String str;
+	va_list args;
+	va_start(args, fmt);
+	str.sprintf(m_alloc, fmt, args);
+	va_end(args);
+
+	Base::emplaceBack(m_alloc);
+	Base::getBack() = std::move(str);
+}
+
+void StringListAuto::pushFrontSprintf(const Char* fmt, ...)
+{
+	String str;
+	va_list args;
+	va_start(args, fmt);
+	str.sprintf(m_alloc, fmt, args);
+	va_end(args);
+
+	Base::emplaceFront(m_alloc);
+	Base::getFront() = std::move(str);
+}
+
 } // end namespace anki
 } // end namespace anki

+ 8 - 28
AnKi/Util/StringList.h

@@ -53,26 +53,12 @@ public:
 	void sortAll(const Sort method = Sort::ASCENDING);
 	void sortAll(const Sort method = Sort::ASCENDING);
 
 
 	/// Push at the end of the list a formated string.
 	/// Push at the end of the list a formated string.
-	template<typename... TArgs>
-	void pushBackSprintf(Allocator alloc, CString fmt, TArgs... args)
-	{
-		String str;
-		str.sprintf(alloc, fmt, args...);
-
-		Base::emplaceBack(alloc);
-		Base::getBack() = std::move(str);
-	}
+	ANKI_CHECK_FORMAT(2, 3)
+	void pushBackSprintf(Allocator alloc, const Char* fmt, ...);
 
 
 	/// Push at the beginning of the list a formated string.
 	/// Push at the beginning of the list a formated string.
-	template<typename... TArgs>
-	void pushFrontSprintf(Allocator alloc, CString fmt, TArgs... args)
-	{
-		String str;
-		str.sprintf(alloc, fmt, args...);
-
-		Base::emplaceFront(alloc);
-		Base::getFront() = std::move(str);
-	}
+	ANKI_CHECK_FORMAT(2, 3)
+	void pushFrontSprintf(Allocator alloc, const Char* fmt, ...);
 
 
 	/// Push back plain CString.
 	/// Push back plain CString.
 	void pushBack(Allocator alloc, CString cstr)
 	void pushBack(Allocator alloc, CString cstr)
@@ -138,18 +124,12 @@ public:
 	}
 	}
 
 
 	/// Push at the end of the list a formated string
 	/// Push at the end of the list a formated string
-	template<typename... TArgs>
-	void pushBackSprintf(CString fmt, TArgs... args)
-	{
-		Base::pushBackSprintf(m_alloc, fmt, args...);
-	}
+	ANKI_CHECK_FORMAT(1, 2)
+	void pushBackSprintf(const Char* fmt, ...);
 
 
 	/// Push at the beginning of the list a formated string
 	/// Push at the beginning of the list a formated string
-	template<typename... TArgs>
-	void pushFrontSprintf(CString fmt, TArgs... args)
-	{
-		Base::pushFrontSprintf(m_alloc, fmt, args...);
-	}
+	ANKI_CHECK_FORMAT(1, 2)
+	void pushFrontSprintf(const Char* fmt, ...);
 
 
 	/// Push back plain CString.
 	/// Push back plain CString.
 	void pushBack(CString cstr)
 	void pushBack(CString cstr)

+ 1 - 0
AnKi/Util/Thread.h

@@ -479,6 +479,7 @@ public:
 		sem_init(&m_handle, 0, initialValue);
 		sem_init(&m_handle, 0, initialValue);
 #else
 #else
 		ANKI_ASSERT(!"TODO");
 		ANKI_ASSERT(!"TODO");
+		(void)initialValue;
 #endif
 #endif
 	}
 	}
 
 

+ 51 - 26
CMakeLists.txt

@@ -188,54 +188,52 @@ if(NOT DEFINED CMAKE_BUILD_TYPE)
 endif()
 endif()
 
 
 ################################################################################
 ################################################################################
-# Compiler & linker flags                                                      #
+# Common compiler & linker flags                                               #
 ################################################################################
 ################################################################################
 
 
 if(MINGW)
 if(MINGW)
-	set(COMPILER_FLAGS "${COMPILER_FLAGS} -mconsole ")
+	add_compile_options(-mconsole)
 endif()
 endif()
 
 
-add_definitions(-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS)
-add_definitions(-DANKI_BUILD)
-
-# ImGUI
-add_definitions(-DIMGUI_USER_CONFIG=<AnKi/Ui/ImGuiConfig.h>)
+add_definitions(
+	-DSPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
+	-DANKI_BUILD
+	-DIMGUI_USER_CONFIG=<AnKi/Ui/ImGuiConfig.h>)
 
 
 if(NOT MSVC)
 if(NOT MSVC)
 	# When building AnKi define this special flag
 	# When building AnKi define this special flag
-	add_definitions("-fPIC")
-
-	add_definitions("-fno-exceptions")
+	add_compile_options(-fPIC -fno-exceptions)
 
 
 	if(GCC AND NOT CLANG)
 	if(GCC AND NOT CLANG)
-		add_definitions("-static-libstdc++")
+		add_compile_options(-static-libstdc++)
 	endif()
 	endif()
 
 
 	if(X86)
 	if(X86)
-		add_definitions("-msse4")
+		add_compile_options(-msse4)
 	endif()
 	endif()
 
 
 	if(ANKI_LTO)
 	if(ANKI_LTO)
-		add_definitions("-flto ")
+		add_compile_options(-flto)
 		set(LINKER_FLAGS "${LINKER_FLAGS} -flto ")
 		set(LINKER_FLAGS "${LINKER_FLAGS} -flto ")
 	endif()
 	endif()
 
 
 	if(ANKI_STRIP)
 	if(ANKI_STRIP)
 		set(LINKER_FLAGS "${LINKER_FLAGS} -s ")
 		set(LINKER_FLAGS "${LINKER_FLAGS} -s ")
-		add_definitions("-s")
+		add_compile_options(-s)
 	endif()
 	endif()
 
 
 	if(ANKI_ADDRESS_SANITIZER)
 	if(ANKI_ADDRESS_SANITIZER)
-		add_definitions("-fsanitize=address ")
+		add_compile_options(-fsanitize=address)
 	endif()
 	endif()
 
 
 	if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
 	if(${CMAKE_BUILD_TYPE} STREQUAL "Release")
-		add_definitions("-O3 -DNDEBUG")
+		add_compile_options(-O3)
+		add_definitions(-DNDEBUG)
 	elseif(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
 	elseif(${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
-		add_definitions("-O3 -g3 -fno-omit-frame-pointer")
+		add_compile_options(-O3 -g3 -fno-omit-frame-pointer)
 		set(LINKER_FLAGS "${LINKER_FLAGS} -rdynamic ") # For backtrace()
 		set(LINKER_FLAGS "${LINKER_FLAGS} -rdynamic ") # For backtrace()
 	elseif(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
 	elseif(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
-		add_definitions("-O0 -g3")
+		add_compile_options(-O0 -g3)
 		set(LINKER_FLAGS "${LINKER_FLAGS} -rdynamic ") # For backtrace()
 		set(LINKER_FLAGS "${LINKER_FLAGS} -rdynamic ") # For backtrace()
 	else()
 	else()
 		message(FATAL_ERROR "Wrong CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
 		message(FATAL_ERROR "Wrong CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}")
@@ -245,14 +243,18 @@ if(NOT MSVC)
 	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
 	set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LINKER_FLAGS}")
 else()
 else()
 	#ProcessorCount(PC)
 	#ProcessorCount(PC)
-	add_compile_options("/MP")
+	add_compile_options(/MP)
 
 
 	if(${CMAKE_BUILD_TYPE} STREQUAL "Release" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
 	if(${CMAKE_BUILD_TYPE} STREQUAL "Release" OR ${CMAKE_BUILD_TYPE} STREQUAL "RelWithDebInfo")
-		#add_definitions("/Ox")
+		#add_definitions(/Ox)
 	endif()
 	endif()
 
 
+	add_definitions(
+		-D_CRT_SECURE_NO_WARNINGS=1 # Disable some string function warnings
+		-D_ITERATOR_DEBUG_LEVEL=0)
+
 	# Full paths in compiler diagnostics else you can't click on visual studio have it open the file+line
 	# Full paths in compiler diagnostics else you can't click on visual studio have it open the file+line
-	add_compile_options("/FC")
+	add_compile_options(/FC)
 endif()
 endif()
 
 
 # Use LLD or gold linker
 # Use LLD or gold linker
@@ -283,6 +285,7 @@ option(BUILD_BULLET3 OFF)
 option(BUILD_CPU_DEMOS OFF)
 option(BUILD_CPU_DEMOS OFF)
 option(BUILD_OPENGL3_DEMOS OFF)
 option(BUILD_OPENGL3_DEMOS OFF)
 option(BUILD_EXTRAS OFF)
 option(BUILD_EXTRAS OFF)
+option(BUILD_UNIT_TESTS OFF)
 
 
 if((LINUX OR MACOS OR WINDOWS) AND GL)
 if((LINUX OR MACOS OR WINDOWS) AND GL)
 	set(ANKI_EXTERN_SUB_DIRS ${ANKI_EXTERN_SUB_DIRS} GLEW)
 	set(ANKI_EXTERN_SUB_DIRS ${ANKI_EXTERN_SUB_DIRS} GLEW)
@@ -446,15 +449,37 @@ endif()
 
 
 # AnKi compiler flags (Mainly warnings)
 # AnKi compiler flags (Mainly warnings)
 if(NOT MSVC)
 if(NOT MSVC)
-	add_definitions(-pedantic -Wno-unknown-warning-option -Wall -W -Wextra -Wstrict-aliasing -Wwrite-strings -Wunused
-		-Wundef -Wno-ignored-attributes -Wno-implicit-fallthrough -Wunused-result
-		-Wconversion -Wno-sign-conversion -Wno-keyword-macro -Wno-string-conversion -Wno-class-memaccess
+	add_compile_options(
+		-pedantic
+		-Wno-unknown-warning-option
+		-Wall
+		-W
+		-Wextra
+		-Wstrict-aliasing
+		-Wwrite-strings
+		-Wunused
+		-Wundef
+		-Wno-ignored-attributes
+		-Wno-implicit-fallthrough
+		-Wunused-result
+		-Wconversion
+		-Wno-sign-conversion
+		-Wno-keyword-macro
+		-Wno-string-conversion
+		-Wno-class-memaccess
 		-Wunused-variable)
 		-Wunused-variable)
 
 
 	set(CMAKE_CXX_STANDARD 17)
 	set(CMAKE_CXX_STANDARD 17)
 else()
 else()
-	#add_definitions("/wd4996 /wd4244 /wd4262 /wd4267 /wd26495 /wd26439")
-	add_compile_definitions("_CRT_SECURE_NO_WARNINGS=1") # Disable some string function warnings
+	string(REPLACE "/W3" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+
+	add_compile_options(
+		/std:c++17
+		/W4
+		/wd4324
+		/wd4456
+		/wd4127
+		/wd4457)
 endif()
 endif()
 
 
 # Add AnKi sub libraries
 # Add AnKi sub libraries

+ 2 - 3
Samples/Common/SampleApp.cpp

@@ -109,9 +109,8 @@ Error SampleApp::userMainLoop(Bool& quit, Second elapsedTime)
 
 
 	if(in.getKey(KeyCode::L) == 1)
 	if(in.getKey(KeyCode::L) == 1)
 	{
 	{
-		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "MotionVectorsHistoryLength")
-												 ? ""
-												 : "MotionVectorsHistoryLength");
+		renderer.setCurrentDebugRenderTarget(
+			(renderer.getCurrentDebugRenderTarget() == "LightShading") ? "" : "LightShading");
 	}
 	}
 
 
 	if(in.getKey(KeyCode::H) == 1)
 	if(in.getKey(KeyCode::H) == 1)

+ 33 - 6
Samples/PhysicsPlayground/Main.cpp

@@ -153,7 +153,7 @@ Error MyApp::sampleExtraInit()
 		const U LINKS = 5;
 		const U LINKS = 5;
 
 
 		BodyNode* prevBody = nullptr;
 		BodyNode* prevBody = nullptr;
-		for(U i = 0; i < LINKS; ++i)
+		for(U32 i = 0; i < LINKS; ++i)
 		{
 		{
 			ModelNode* monkey;
 			ModelNode* monkey;
 			ANKI_CHECK(getSceneGraph().newSceneNode<ModelNode>(
 			ANKI_CHECK(getSceneGraph().newSceneNode<ModelNode>(
@@ -224,10 +224,37 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 																									 : "RtShadows");
 																									 : "RtShadows");
 	}
 	}
 
 
-	if(getInput().getKey(KeyCode::U) == 1)
+	if(getInput().getKey(KeyCode::P) == 1)
 	{
 	{
-		renderer.setCurrentDebugRenderTarget(
-			(renderer.getCurrentDebugRenderTarget() == "GBufferNormals") ? "" : "GBufferNormals");
+		static U32 idx = 3;
+		++idx;
+		idx %= 4;
+		if(idx == 0)
+		{
+			renderer.setCurrentDebugRenderTarget("IndirectDiffuseVrsSri");
+		}
+		else if(idx == 1)
+		{
+			renderer.setCurrentDebugRenderTarget("VrsSriDownscaled");
+		}
+		else if(idx == 2)
+		{
+			renderer.setCurrentDebugRenderTarget("VrsSri");
+		}
+		else
+		{
+			renderer.setCurrentDebugRenderTarget("");
+		}
+	}
+
+	if(getInput().getKey(KeyCode::L) == 1)
+	{
+		renderer.setCurrentDebugRenderTarget((renderer.getCurrentDebugRenderTarget() == "Bloom") ? "" : "Bloom");
+	}
+
+	if(getInput().getKey(KeyCode::J) == 1)
+	{
+		m_config.setRVrs(!m_config.getRVrs());
 	}
 	}
 
 
 	if(getInput().getKey(KeyCode::F1) == 1)
 	if(getInput().getKey(KeyCode::F1) == 1)
@@ -262,7 +289,7 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 	{
 	{
 		ANKI_LOGI("Firing a monkey");
 		ANKI_LOGI("Firing a monkey");
 
 
-		static U instance = 0;
+		static U32 instance = 0;
 
 
 		Transform camTrf =
 		Transform camTrf =
 			getSceneGraph().getActiveCameraNode().getFirstComponentOfType<MoveComponent>().getWorldTransform();
 			getSceneGraph().getActiveCameraNode().getFirstComponentOfType<MoveComponent>().getWorldTransform();
@@ -319,7 +346,7 @@ Error MyApp::userMainLoop(Bool& quit, [[maybe_unused]] Second elapsedTime)
 			Transform trf(ray.m_hitPosition.xyz0(), rot, 1.0f);
 			Transform trf(ray.m_hitPosition.xyz0(), rot, 1.0f);
 
 
 			// Create an obj
 			// Create an obj
-			static U id = 0;
+			static U32 id = 0;
 			ModelNode* monkey;
 			ModelNode* monkey;
 			ANKI_CHECK(getSceneGraph().newSceneNode(
 			ANKI_CHECK(getSceneGraph().newSceneNode(
 				StringAuto(getSceneGraph().getFrameAllocator()).sprintf("decal%u", id++).toCString(), monkey));
 				StringAuto(getSceneGraph().getFrameAllocator()).sprintf("decal%u", id++).toCString(), monkey));

+ 17 - 0
Tests/Framework/Framework.h

@@ -229,4 +229,21 @@ GrManager* createGrManager(ConfigSet* cfg, NativeWindow* win);
 ResourceManager* createResourceManager(ConfigSet* cfg, GrManager* gr, PhysicsWorld*& physics,
 ResourceManager* createResourceManager(ConfigSet* cfg, GrManager* gr, PhysicsWorld*& physics,
 									   ResourceFilesystem*& resourceFs);
 									   ResourceFilesystem*& resourceFs);
 
 
+/// Stolen from https://en.cppreference.com/w/cpp/algorithm/random_shuffle because std::random_suffle got deprecated
+template<class TRandomIt>
+static void randomShuffle(TRandomIt first, TRandomIt last)
+{
+	typename std::iterator_traits<TRandomIt>::difference_type i, n;
+	n = last - first;
+	for(i = n - 1; i > 0; --i)
+	{
+		using std::swap;
+		swap(first[i], first[std::rand() % (i + 1)]);
+		// rand() % (i+1) isn't actually correct, because the generated number
+		// is not uniformly distributed for most values of i. A correct implementation
+		// will need to essentially reimplement C++11 std::uniform_int_distribution,
+		// which is beyond the scope of this example.
+	}
+}
+
 } // end namespace anki
 } // end namespace anki

+ 2 - 4
Tests/Gr/Gr.cpp

@@ -18,7 +18,7 @@
 #include <AnKi/Collision/Aabb.h>
 #include <AnKi/Collision/Aabb.h>
 #include <ctime>
 #include <ctime>
 
 
-namespace anki {
+using namespace anki;
 
 
 const U WIDTH = 1024;
 const U WIDTH = 1024;
 const U HEIGHT = 768;
 const U HEIGHT = 768;
@@ -3050,7 +3050,7 @@ F32 scatteringPdfLambertian(Vec3 normal, Vec3 scatteredDir)
 #undef MAGIC_MACRO
 #undef MAGIC_MACRO
 
 
 		StringAuto commonSrc(alloc);
 		StringAuto commonSrc(alloc);
-		commonSrc.sprintf(commonSrcPart, rtTypesStr.cstr());
+		commonSrc.sprintf(commonSrcPart.cstr(), rtTypesStr.cstr());
 
 
 		const CString lambertianSrc = R"(
 		const CString lambertianSrc = R"(
 layout(location = PAYLOAD_LOCATION) rayPayloadInEXT PayLoad s_payLoad;
 layout(location = PAYLOAD_LOCATION) rayPayloadInEXT PayLoad s_payLoad;
@@ -3643,5 +3643,3 @@ void main()
 
 
 	COMMON_END()
 	COMMON_END()
 }
 }
-
-} // end namespace anki

+ 2 - 1
Tests/Gr/GrCommon.h

@@ -20,7 +20,8 @@ inline ShaderPtr createShader(CString src, ShaderType type, GrManager& gr,
 	ShaderProgramParser::generateAnkiShaderHeader(type, compilerOptions, header);
 	ShaderProgramParser::generateAnkiShaderHeader(type, compilerOptions, header);
 	header.append(src);
 	header.append(src);
 	DynamicArrayAuto<U8> spirv(alloc);
 	DynamicArrayAuto<U8> spirv(alloc);
-	ANKI_TEST_EXPECT_NO_ERR(compilerGlslToSpirv(header, type, alloc, spirv));
+	StringAuto errorLog(alloc);
+	ANKI_TEST_EXPECT_NO_ERR(compilerGlslToSpirv(header, type, alloc, spirv, errorLog));
 
 
 	ShaderInitInfo initInf(type, spirv);
 	ShaderInitInfo initInf(type, spirv);
 	initInf.m_constValues = specVals;
 	initInf.m_constValues = specVals;

+ 0 - 4
Tests/Gr/GrTextureBuffer.cpp

@@ -7,8 +7,6 @@
 #include <Tests/Gr/GrCommon.h>
 #include <Tests/Gr/GrCommon.h>
 #include <AnKi/Gr.h>
 #include <AnKi/Gr.h>
 
 
-namespace anki {
-
 ANKI_TEST(Gr, TextureBuffer)
 ANKI_TEST(Gr, TextureBuffer)
 {
 {
 	ConfigSet cfg(allocAligned, nullptr);
 	ConfigSet cfg(allocAligned, nullptr);
@@ -80,5 +78,3 @@ void main()
 	GrManager::deleteInstance(gr);
 	GrManager::deleteInstance(gr);
 	NativeWindow::deleteInstance(win);
 	NativeWindow::deleteInstance(win);
 }
 }
-
-} // end namespace anki

+ 0 - 4
Tests/Renderer/TileAllocator.cpp

@@ -6,8 +6,6 @@
 #include <Tests/Framework/Framework.h>
 #include <Tests/Framework/Framework.h>
 #include <AnKi/Renderer/TileAllocator.h>
 #include <AnKi/Renderer/TileAllocator.h>
 
 
-namespace anki {
-
 ANKI_TEST(Renderer, TileAllocator)
 ANKI_TEST(Renderer, TileAllocator)
 {
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
@@ -69,5 +67,3 @@ ANKI_TEST(Renderer, TileAllocator)
 		ANKI_TEST_EXPECT_EQ(res, TileAllocatorResult::ALLOCATION_SUCCEEDED);
 		ANKI_TEST_EXPECT_EQ(res, TileAllocatorResult::ALLOCATION_SUCCEEDED);
 	}
 	}
 }
 }
-
-} // end namespace anki

+ 5 - 3
Tests/Resource/AsyncLoader.cpp

@@ -9,7 +9,9 @@
 #include <AnKi/Util/Atomic.h>
 #include <AnKi/Util/Atomic.h>
 #include <AnKi/Util/Functions.h>
 #include <AnKi/Util/Functions.h>
 
 
-namespace anki {
+using namespace anki;
+
+namespace {
 
 
 class Task : public AsyncLoaderTask
 class Task : public AsyncLoaderTask
 {
 {
@@ -96,6 +98,8 @@ public:
 	}
 	}
 };
 };
 
 
+} // namespace
+
 ANKI_TEST(Resource, AsyncLoader)
 ANKI_TEST(Resource, AsyncLoader)
 {
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
@@ -268,5 +272,3 @@ ANKI_TEST(Resource, AsyncLoader)
 		ANKI_TEST_EXPECT_EQ(counter.load(), 10);
 		ANKI_TEST_EXPECT_EQ(counter.load(), 10);
 	}
 	}
 }
 }
-
-} // end namespace anki

+ 0 - 4
Tests/Resource/ResourceFilesystem.cpp

@@ -6,8 +6,6 @@
 #include <Tests/Framework/Framework.h>
 #include <Tests/Framework/Framework.h>
 #include <AnKi/Resource/ResourceFilesystem.h>
 #include <AnKi/Resource/ResourceFilesystem.h>
 
 
-namespace anki {
-
 ANKI_TEST(Resource, ResourceFilesystem)
 ANKI_TEST(Resource, ResourceFilesystem)
 {
 {
 	printf("Test requires the Data dir\n");
 	printf("Test requires the Data dir\n");
@@ -33,5 +31,3 @@ ANKI_TEST(Resource, ResourceFilesystem)
 		ANKI_TEST_EXPECT_EQ(txt, "hell\n");
 		ANKI_TEST_EXPECT_EQ(txt, "hell\n");
 	}
 	}
 }
 }
-
-} // end namespace anki

+ 0 - 4
Tests/Resource/ResourceManager.cpp

@@ -8,8 +8,6 @@
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Resource/ResourceManager.h>
 #include <AnKi/Core/ConfigSet.h>
 #include <AnKi/Core/ConfigSet.h>
 
 
-namespace anki {
-
 ANKI_TEST(Resource, ResourceManager)
 ANKI_TEST(Resource, ResourceManager)
 {
 {
 	// Create
 	// Create
@@ -84,5 +82,3 @@ ANKI_TEST(Resource, ResourceManager)
 	// Delete
 	// Delete
 	alloc.deleteInstance(resources);
 	alloc.deleteInstance(resources);
 }
 }
-
-} // end namespace anki

+ 0 - 4
Tests/Scene/Octree.cpp

@@ -6,8 +6,6 @@
 #include <Tests/Framework/Framework.h>
 #include <Tests/Framework/Framework.h>
 #include <AnKi/Scene/Octree.h>
 #include <AnKi/Scene/Octree.h>
 
 
-namespace anki {
-
 ANKI_TEST(Scene, Octree)
 ANKI_TEST(Scene, Octree)
 {
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
@@ -84,5 +82,3 @@ ANKI_TEST(Scene, Octree)
 	}
 	}
 #endif
 #endif
 }
 }
-
-} // end namespace anki

+ 12 - 12
Tests/Script/LuaBinder.cpp

@@ -7,7 +7,18 @@
 #include <AnKi/Script.h>
 #include <AnKi/Script.h>
 #include <AnKi/Math.h>
 #include <AnKi/Math.h>
 
 
-static const char* script = R"(
+ANKI_TEST(Script, LuaBinder)
+{
+	ScriptManager sm;
+
+	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr));
+	Vec4 v4(2.0, 3.0, 4.0, 5.0);
+	Vec3 v3(1.1f, 2.2f, 3.3f);
+
+	sm.exposeVariable("v4", &v4);
+	sm.exposeVariable("v3", &v3);
+
+	static const char* script = R"(
 b = Vec4.new(0, 0, 0, 1.1)
 b = Vec4.new(0, 0, 0, 1.1)
 if math.abs(b:getW() - 1.1) > 0.00001 then
 if math.abs(b:getW() - 1.1) > 0.00001 then
 	print(b:getW())
 	print(b:getW())
@@ -22,17 +33,6 @@ v4:copy(v4 * b)
 v3:setZ(0.1)
 v3:setZ(0.1)
 )";
 )";
 
 
-ANKI_TEST(Script, LuaBinder)
-{
-	ScriptManager sm;
-
-	ANKI_TEST_EXPECT_NO_ERR(sm.init(allocAligned, nullptr));
-	Vec4 v4(2.0, 3.0, 4.0, 5.0);
-	Vec3 v3(1.1f, 2.2f, 3.3f);
-
-	sm.exposeVariable("v4", &v4);
-	sm.exposeVariable("v3", &v3);
-
 	ANKI_TEST_EXPECT_NO_ERR(sm.evalString(script));
 	ANKI_TEST_EXPECT_NO_ERR(sm.evalString(script));
 
 
 	ANKI_TEST_EXPECT_EQ(v4, Vec4(6, 12, 0, 5.5));
 	ANKI_TEST_EXPECT_EQ(v4, Vec4(6, 12, 0, 5.5));

+ 5 - 3
Tests/Ui/Ui.cpp

@@ -10,7 +10,9 @@
 #include <AnKi/Input.h>
 #include <AnKi/Input.h>
 #include <AnKi/Core/GpuMemoryPools.h>
 #include <AnKi/Core/GpuMemoryPools.h>
 
 
-namespace anki {
+using namespace anki;
+
+namespace {
 
 
 class Label : public UiImmediateModeBuilder
 class Label : public UiImmediateModeBuilder
 {
 {
@@ -51,6 +53,8 @@ public:
 	}
 	}
 };
 };
 
 
+} // namespace
+
 ANKI_TEST(Ui, Ui)
 ANKI_TEST(Ui, Ui)
 {
 {
 	ConfigSet cfg;
 	ConfigSet cfg;
@@ -154,5 +158,3 @@ ANKI_TEST(Ui, Ui)
 	Input::deleteInstance(in);
 	Input::deleteInstance(in);
 	NativeWindow::deleteInstance(win);
 	NativeWindow::deleteInstance(win);
 }
 }
-
-} // end namespace anki

+ 1 - 3
Tests/Util/BuddyAllocatorBuilder.cpp

@@ -7,7 +7,7 @@
 #include <AnKi/Util/BuddyAllocatorBuilder.h>
 #include <AnKi/Util/BuddyAllocatorBuilder.h>
 #include <tuple>
 #include <tuple>
 
 
-namespace anki {
+using namespace anki;
 
 
 /// Check if all memory has the same value.
 /// Check if all memory has the same value.
 static int memvcmp(const void* memory, U8 val, PtrSize size)
 static int memvcmp(const void* memory, U8 val, PtrSize size)
@@ -107,5 +107,3 @@ ANKI_TEST(Util, BuddyAllocatorBuilder)
 		}
 		}
 	}
 	}
 }
 }
-
-} // end namespace anki

+ 1 - 3
Tests/Util/ClassAllocatorBuilder.cpp

@@ -11,7 +11,7 @@
 #include <random>
 #include <random>
 #include <algorithm>
 #include <algorithm>
 
 
-namespace anki {
+using namespace anki;
 
 
 namespace {
 namespace {
 
 
@@ -216,5 +216,3 @@ ANKI_TEST(Util, ClassAllocatorBuilder)
 		allocations.clear();
 		allocations.clear();
 	}
 	}
 }
 }
-
-} // end namespace anki

+ 1 - 1
Tests/Util/HashMap.cpp

@@ -222,7 +222,7 @@ ANKI_TEST(Util, HashMap)
 		// Delete
 		// Delete
 		{
 		{
 			// Remove in random order
 			// Remove in random order
-			std::random_shuffle(vals.begin(), vals.end());
+			randomShuffle(vals.begin(), vals.end());
 
 
 			// Random delete AnKi
 			// Random delete AnKi
 			Second akTime = 0.0;
 			Second akTime = 0.0;

+ 1 - 1
Tests/Util/Process.cpp

@@ -16,7 +16,7 @@ static void createBashScript(CString code)
 	File file;
 	File file;
 
 
 	ANKI_TEST_EXPECT_NO_ERR(file.open("process_test.sh", FileOpenFlag::WRITE));
 	ANKI_TEST_EXPECT_NO_ERR(file.open("process_test.sh", FileOpenFlag::WRITE));
-	ANKI_TEST_EXPECT_NO_ERR(file.writeText("#!/bin/bash\n%s\n", code.cstr()));
+	ANKI_TEST_EXPECT_NO_ERR(file.writeTextf("#!/bin/bash\n%s\n", code.cstr()));
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 2 - 2
Tests/Util/SparseArray.cpp

@@ -377,7 +377,7 @@ ANKI_TEST(Util, SparseArrayBench)
 	// Search
 	// Search
 	{
 	{
 		// Search in random order
 		// Search in random order
-		std::random_shuffle(vals.begin(), vals.end());
+		randomShuffle(vals.begin(), vals.end());
 
 
 		int count = 0;
 		int count = 0;
 
 
@@ -413,7 +413,7 @@ ANKI_TEST(Util, SparseArrayBench)
 	// Deletes
 	// Deletes
 	{
 	{
 		// Remove in random order
 		// Remove in random order
-		std::random_shuffle(vals.begin(), vals.end());
+		randomShuffle(vals.begin(), vals.end());
 
 
 		// Random delete AnKi
 		// Random delete AnKi
 		Second akTime = 0.0;
 		Second akTime = 0.0;

+ 0 - 4
Tests/Util/String.cpp

@@ -7,8 +7,6 @@
 #include <AnKi/Util/String.h>
 #include <AnKi/Util/String.h>
 #include <string>
 #include <string>
 
 
-namespace anki {
-
 ANKI_TEST(Util, String)
 ANKI_TEST(Util, String)
 {
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
@@ -230,5 +228,3 @@ ANKI_TEST(Util, String)
 		a.destroy(alloc);
 		a.destroy(alloc);
 	}
 	}
 }
 }
-
-} // end namespace anki

+ 0 - 4
Tests/Util/StringList.cpp

@@ -6,8 +6,6 @@
 #include <Tests/Framework/Framework.h>
 #include <Tests/Framework/Framework.h>
 #include <AnKi/Util/StringList.h>
 #include <AnKi/Util/StringList.h>
 
 
-namespace anki {
-
 ANKI_TEST(Util, StringList)
 ANKI_TEST(Util, StringList)
 {
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
@@ -37,5 +35,3 @@ ANKI_TEST(Util, StringList)
 		ANKI_TEST_EXPECT_EQ(*it, "boo");
 		ANKI_TEST_EXPECT_EQ(*it, "boo");
 	}
 	}
 }
 }
-
-} // end namespace anki

+ 0 - 4
Tests/Util/Thread.cpp

@@ -10,8 +10,6 @@
 #include <AnKi/Util/ThreadPool.h>
 #include <AnKi/Util/ThreadPool.h>
 #include <cstring>
 #include <cstring>
 
 
-namespace anki {
-
 ANKI_TEST(Util, Thread)
 ANKI_TEST(Util, Thread)
 {
 {
 	static const char* THREAD_NAME = "name";
 	static const char* THREAD_NAME = "name";
@@ -115,8 +113,6 @@ struct TestJobTP : ThreadPoolTask
 	}
 	}
 };
 };
 
 
-} // end namespace anki
-
 ANKI_TEST(Util, ThreadPool)
 ANKI_TEST(Util, ThreadPool)
 {
 {
 	const U32 threadsCount = 4;
 	const U32 threadsCount = 4;

+ 9 - 3
Tests/Util/ThreadHive.cpp

@@ -8,7 +8,9 @@
 #include <AnKi/Util/HighRezTimer.h>
 #include <AnKi/Util/HighRezTimer.h>
 #include <AnKi/Util/System.h>
 #include <AnKi/Util/System.h>
 
 
-namespace anki {
+using namespace anki;
+
+namespace {
 
 
 class ThreadHiveTestContext
 class ThreadHiveTestContext
 {
 {
@@ -61,6 +63,8 @@ static void taskToWait(void* arg, [[maybe_unused]] U32 threadId, [[maybe_unused]
 	ANKI_TEST_EXPECT_GEQ(prev, 10);
 	ANKI_TEST_EXPECT_GEQ(prev, 10);
 }
 }
 
 
+} // namespace
+
 ANKI_TEST(Util, ThreadHive)
 ANKI_TEST(Util, ThreadHive)
 {
 {
 	const U32 threadCount = 32;
 	const U32 threadCount = 32;
@@ -172,6 +176,8 @@ ANKI_TEST(Util, ThreadHive)
 	}
 	}
 }
 }
 
 
+namespace {
+
 class FibTask
 class FibTask
 {
 {
 public:
 public:
@@ -225,6 +231,8 @@ static U64 fib(U64 n)
 	}
 	}
 }
 }
 
 
+} // namespace
+
 ANKI_TEST(Util, ThreadHiveBench)
 ANKI_TEST(Util, ThreadHiveBench)
 {
 {
 	static const U FIB_N = 32;
 	static const U FIB_N = 32;
@@ -248,5 +256,3 @@ ANKI_TEST(Util, ThreadHiveBench)
 	ANKI_TEST_LOGI("Total time %fms. Ground truth %fms", (timeB - timeA) * 1000.0, (timeC - timeB) * 1000.0);
 	ANKI_TEST_LOGI("Total time %fms. Ground truth %fms", (timeB - timeA) * 1000.0, (timeC - timeB) * 1000.0);
 	ANKI_TEST_EXPECT_EQ(sum.getNonAtomically(), serialFib);
 	ANKI_TEST_EXPECT_EQ(sum.getNonAtomically(), serialFib);
 }
 }
-
-} // end namespace anki

+ 3 - 3
ThirdParty/Bullet/CMakeLists.txt

@@ -71,7 +71,7 @@ ENDIF (CMAKE_SYSTEM_NAME STREQUAL WindowsPhone OR CMAKE_SYSTEM_NAME STREQUAL Win
 
 
 
 
 # Disable, MSVC workaround
 # Disable, MSVC workaround
-IF(MSVC AND FALSE)
+IF(MSVC)
 	IF (NOT USE_MSVC_INCREMENTAL_LINKING)
 	IF (NOT USE_MSVC_INCREMENTAL_LINKING)
 		#MESSAGE("MSVC_INCREMENTAL_DEFAULT"+${MSVC_INCREMENTAL_DEFAULT})
 		#MESSAGE("MSVC_INCREMENTAL_DEFAULT"+${MSVC_INCREMENTAL_DEFAULT})
 		SET( MSVC_INCREMENTAL_YES_FLAG "/INCREMENTAL:NO")
 		SET( MSVC_INCREMENTAL_YES_FLAG "/INCREMENTAL:NO")
@@ -94,7 +94,7 @@ IF(MSVC AND FALSE)
 
 
 	ENDIF (NOT USE_MSVC_INCREMENTAL_LINKING)
 	ENDIF (NOT USE_MSVC_INCREMENTAL_LINKING)
 
 
-	IF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
+	IF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL AND FALSE)
 		#We statically link to reduce dependancies
 		#We statically link to reduce dependancies
 		FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO )
 		FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO )
 			IF(${flag_var} MATCHES "/MD")
 			IF(${flag_var} MATCHES "/MD")
@@ -104,7 +104,7 @@ IF(MSVC AND FALSE)
 				STRING(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
 				STRING(REGEX REPLACE "/MDd" "/MTd" ${flag_var} "${${flag_var}}")
 			ENDIF(${flag_var} MATCHES "/MDd")
 			ENDIF(${flag_var} MATCHES "/MDd")
 		ENDFOREACH(flag_var)
 		ENDFOREACH(flag_var)
-	ENDIF (NOT USE_MSVC_RUNTIME_LIBRARY_DLL)
+	ENDIF ()
 
 
 	IF (CMAKE_CL_64)
 	IF (CMAKE_CL_64)
 	  ADD_DEFINITIONS(-D_WIN64)
 	  ADD_DEFINITIONS(-D_WIN64)

+ 1 - 1
ThirdParty/Bullet/src/LinearMath/btAlignedObjectArray.h

@@ -40,7 +40,7 @@ subject to the following restrictions:
 #endif //BT_USE_PLACEMENT_NEW
 #endif //BT_USE_PLACEMENT_NEW
 
 
 // The register keyword is deprecated in C++11 so don't use it.
 // The register keyword is deprecated in C++11 so don't use it.
-#if __cplusplus > 199711L
+#if 1 || __cplusplus > 199711L
 #define BT_REGISTER
 #define BT_REGISTER
 #else
 #else
 #define BT_REGISTER register
 #define BT_REGISTER register

+ 12 - 12
ThirdParty/FidelityFX/ffx_fsr1.h

@@ -849,12 +849,12 @@ AF1 sharpness){
   // Immediate constants for peak range.
   // Immediate constants for peak range.
   AF2 peakC=AF2(1.0,-1.0*4.0);
   AF2 peakC=AF2(1.0,-1.0*4.0);
   // Limiters, these need to be high precision RCPs.
   // Limiters, these need to be high precision RCPs.
-  AF1 hitMinR=mn4R*ARcpF1(AF1_(4.0)*mx4R);
-  AF1 hitMinG=mn4G*ARcpF1(AF1_(4.0)*mx4G);
-  AF1 hitMinB=mn4B*ARcpF1(AF1_(4.0)*mx4B);
-  AF1 hitMaxR=(peakC.x-mx4R)*ARcpF1(AF1_(4.0)*mn4R+peakC.y);
-  AF1 hitMaxG=(peakC.x-mx4G)*ARcpF1(AF1_(4.0)*mn4G+peakC.y);
-  AF1 hitMaxB=(peakC.x-mx4B)*ARcpF1(AF1_(4.0)*mn4B+peakC.y);
+  AF1 hitMinR=min(mn4R,eR)*ARcpF1(AF1_(4.0)*mx4R);
+  AF1 hitMinG=min(mn4G,eG)*ARcpF1(AF1_(4.0)*mx4G);
+  AF1 hitMinB=min(mn4B,eB)*ARcpF1(AF1_(4.0)*mx4B);
+  AF1 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpF1(AF1_(4.0)*mn4R+peakC.y);
+  AF1 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpF1(AF1_(4.0)*mn4G+peakC.y);
+  AF1 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpF1(AF1_(4.0)*mn4B+peakC.y);
   AF1 lobeR=max(-hitMinR,hitMaxR);
   AF1 lobeR=max(-hitMinR,hitMaxR);
   AF1 lobeG=max(-hitMinG,hitMaxG);
   AF1 lobeG=max(-hitMinG,hitMaxG);
   AF1 lobeB=max(-hitMinB,hitMaxB);
   AF1 lobeB=max(-hitMinB,hitMaxB);
@@ -1065,12 +1065,12 @@ AF1 sharpness){
   // Immediate constants for peak range.
   // Immediate constants for peak range.
   AH2 peakC=AH2(1.0,-1.0*4.0);
   AH2 peakC=AH2(1.0,-1.0*4.0);
   // Limiters, these need to be high precision RCPs.
   // Limiters, these need to be high precision RCPs.
-  AH2 hitMinR=mn4R*ARcpH2(AH2_(4.0)*mx4R);
-  AH2 hitMinG=mn4G*ARcpH2(AH2_(4.0)*mx4G);
-  AH2 hitMinB=mn4B*ARcpH2(AH2_(4.0)*mx4B);
-  AH2 hitMaxR=(peakC.x-mx4R)*ARcpH2(AH2_(4.0)*mn4R+peakC.y);
-  AH2 hitMaxG=(peakC.x-mx4G)*ARcpH2(AH2_(4.0)*mn4G+peakC.y);
-  AH2 hitMaxB=(peakC.x-mx4B)*ARcpH2(AH2_(4.0)*mn4B+peakC.y);
+  AH2 hitMinR=min(mn4R,eR)*ARcpH2(AH2_(4.0)*mx4R);
+  AH2 hitMinG=min(mn4G,eG)*ARcpH2(AH2_(4.0)*mx4G);
+  AH2 hitMinB=min(mn4B,eB)*ARcpH2(AH2_(4.0)*mx4B);
+  AH2 hitMaxR=(peakC.x-max(mx4R,eR))*ARcpH2(AH2_(4.0)*mn4R+peakC.y);
+  AH2 hitMaxG=(peakC.x-max(mx4G,eG))*ARcpH2(AH2_(4.0)*mn4G+peakC.y);
+  AH2 hitMaxB=(peakC.x-max(mx4B,eB))*ARcpH2(AH2_(4.0)*mn4B+peakC.y);
   AH2 lobeR=max(-hitMinR,hitMaxR);
   AH2 lobeR=max(-hitMinR,hitMaxR);
   AH2 lobeG=max(-hitMinG,hitMaxG);
   AH2 lobeG=max(-hitMinG,hitMaxG);
   AH2 lobeB=max(-hitMinB,hitMaxB);
   AH2 lobeB=max(-hitMinB,hitMaxB);

+ 1 - 0
ThirdParty/Glslang/SPIRV/GlslangToSpv.cpp

@@ -4090,6 +4090,7 @@ void TGlslangToSpvTraverser::decorateStructType(const glslang::TType& type,
     // Name and decorate the non-hidden members
     // Name and decorate the non-hidden members
     int offset = -1;
     int offset = -1;
     int locationOffset = 0;  // for use within the members of this struct
     int locationOffset = 0;  // for use within the members of this struct
+    (void)locationOffset;
     bool memberLocationInvalid = type.isArrayOfArrays() ||
     bool memberLocationInvalid = type.isArrayOfArrays() ||
         (type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false));
         (type.isArray() && (type.getQualifier().isArrayedIo(glslangIntermediate->getStage()) == false));
     for (int i = 0; i < (int)glslangMembers->size(); i++) {
     for (int i = 0; i < (int)glslangMembers->size(); i++) {

+ 3 - 1
ThirdParty/ImGui/CMakeLists.txt

@@ -5,7 +5,9 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..)
 include_directories(${CMAKE_CURRENT_SOURCE_DIR}/../..)
 include_directories(${CMAKE_CURRENT_BINARY_DIR}/../..)
 include_directories(${CMAKE_CURRENT_BINARY_DIR}/../..)
 if(NOT MSVC)
 if(NOT MSVC)
-	add_definitions("-std=c++14")
+	add_compile_options(-std=c++17)
+else()
+	add_compile_options(/std:c++17)
 endif()
 endif()
 
 
 add_library(AnKiImGui ${SRC})
 add_library(AnKiImGui ${SRC})

+ 1 - 0
ThirdParty/Sdl2/src/video/yuv2rgb/yuv_rgb_std_func.h

@@ -107,6 +107,7 @@ void STD_FUNCTION_NAME(
         uint8_t *rgb_ptr2=RGB+(y+1)*RGB_stride;
         uint8_t *rgb_ptr2=RGB+(y+1)*RGB_stride;
 		#endif
 		#endif
 
 
+		(void)y_ptr2;
 		for(x=0; x<(width-(uv_x_sample_interval-1)); x+=uv_x_sample_interval)
 		for(x=0; x<(width-(uv_x_sample_interval-1)); x+=uv_x_sample_interval)
 		{
 		{
 			// Compute U and V contributions, common to the four pixels
 			// Compute U and V contributions, common to the four pixels

+ 2 - 2
Tools/GltfImporter/Main.cpp

@@ -63,7 +63,7 @@ static Error parseCommandLineArgs(int argc, char** argv, CmdLineArgs& info)
 				}
 				}
 				else
 				else
 				{
 				{
-					info.m_texRpath.sprintf("");
+					info.m_texRpath.create("");
 				}
 				}
 			}
 			}
 			else
 			else
@@ -88,7 +88,7 @@ static Error parseCommandLineArgs(int argc, char** argv, CmdLineArgs& info)
 				}
 				}
 				else
 				else
 				{
 				{
-					info.m_rpath.sprintf("");
+					info.m_rpath.create("");
 				}
 				}
 			}
 			}
 			else
 			else

+ 2 - 3
Tools/Image/ImageViewerMain.cpp

@@ -124,8 +124,7 @@ private:
 			StringListAuto mipLabels(getFrameAllocator());
 			StringListAuto mipLabels(getFrameAllocator());
 			for(U32 mip = 0; mip < grTex.getMipmapCount(); ++mip)
 			for(U32 mip = 0; mip < grTex.getMipmapCount(); ++mip)
 			{
 			{
-				mipLabels.pushBackSprintf("Mip %u (%llu x %llu)", mip, grTex.getWidth() >> mip,
-										  grTex.getHeight() >> mip);
+				mipLabels.pushBackSprintf("Mip %u (%u x %u)", mip, grTex.getWidth() >> mip, grTex.getHeight() >> mip);
 			}
 			}
 
 
 			const U32 lastCrntMip = m_crntMip;
 			const U32 lastCrntMip = m_crntMip;
@@ -293,7 +292,7 @@ public:
 
 
 		// Change window name
 		// Change window name
 		StringAuto title(alloc);
 		StringAuto title(alloc);
-		title.sprintf("%s %llu x %llu Mips %u Format %s", argv[1], image->getWidth(), image->getHeight(),
+		title.sprintf("%s %u x %u Mips %u Format %s", argv[1], image->getWidth(), image->getHeight(),
 					  image->getTexture()->getMipmapCount(), getFormatInfo(image->getTexture()->getFormat()).m_name);
 					  image->getTexture()->getMipmapCount(), getFormatInfo(image->getTexture()->getFormat()).m_name);
 		getWindow().setWindowTitle(title);
 		getWindow().setWindowTitle(title);